예제 #1
0
        private bool ParseParenExpression(ref ASTNode retn)
        {
            if (tokenStream.Current != ExpressionTokenType.ParenOpen)
            {
                return(false);
            }

            int advance = tokenStream.FindMatchingIndex(ExpressionTokenType.ParenOpen, ExpressionTokenType.ParenClose);

            if (advance == -1)
            {
                throw new Exception("Unmatched paren");                // todo just abort
            }
            ExpressionParser subParser = CreateSubParser(advance);

            retn = subParser.ParseLoop();
            if (retn.IsCompound)
            {
                retn = ASTNode.ParenNode(retn);
            }

            ASTNode access = null;

            if (ParseParenAccessExpression(ref access))
            {
                ParenNode parenNode = (ParenNode)retn;
                parenNode.accessExpression = (MemberAccessExpressionNode)access;
            }

            subParser.Release();
            return(true);
        }
예제 #2
0
        public static ASTNode Parse(TokenStream tokenStream)
        {
            ExpressionParser parser = new ExpressionParser(tokenStream);
            ASTNode          retn   = parser.ParseLoop();

            parser.Release();
            return(retn);
        }
예제 #3
0
        // something.someValue
        // something[i]
        // something(*).x(*).y
        private bool ParseAccessExpression(ref ASTNode retn)
        {
            if (tokenStream.Current != ExpressionTokenType.Identifier)
            {
                return(false);
            }

            string identifier = tokenStream.Current.value;

            tokenStream.Save();
            LightList <ASTNode> parts = LightList <ASTNode> .Get();

            tokenStream.Advance();
            while (tokenStream.HasMoreTokens)
            {
                if (tokenStream.Current == ExpressionTokenType.Dot || tokenStream.Current == ExpressionTokenType.Elvis)
                {
                    if (tokenStream.Next != ExpressionTokenType.Identifier)
                    {
                        break;
                    }

                    tokenStream.Advance();
                    parts.Add(ASTNode.DotAccessNode(tokenStream.Current.value, tokenStream.Previous == ExpressionTokenType.Elvis));
                    tokenStream.Advance();
                    if (tokenStream.HasMoreTokens)
                    {
                        continue;
                    }
                }
                else if (tokenStream.Current == ExpressionTokenType.ArrayAccessOpen || tokenStream.Current == ExpressionTokenType.QuestionMark && tokenStream.NextTokenIs(ExpressionTokenType.ArrayAccessOpen))
                {
                    bool isElvis = false;
                    if (tokenStream.Current == ExpressionTokenType.QuestionMark)
                    {
                        isElvis = true;
                        tokenStream.Advance();
                    }

                    int advance = tokenStream.FindMatchingIndex(ExpressionTokenType.ArrayAccessOpen, ExpressionTokenType.ArrayAccessClose);
                    if (advance == -1)
                    {
                        Abort("Unmatched array bracket");
                    }

                    ExpressionParser subParser = CreateSubParser(advance);
                    parts.Add(ASTNode.IndexExpressionNode(subParser.ParseLoop(), isElvis));
                    subParser.Release();
                    if (tokenStream.HasMoreTokens)
                    {
                        continue;
                    }
                }
                else if (tokenStream.Current == ExpressionTokenType.ParenOpen)
                {
                    LightList <ASTNode> parameters = null;

                    if (!ParseListExpression(ref parameters, ExpressionTokenType.ParenOpen, ExpressionTokenType.ParenClose))
                    {
                        Abort();
                    }

                    parts.Add(ASTNode.InvokeNode(parameters));
                    if (tokenStream.HasMoreTokens)
                    {
                        continue;
                    }
                }

                else if (tokenStream.Current == ExpressionTokenType.LessThan)
                {
                    // shortcut the << operator since we can't have a << in a generic type node. List<<string>> is invalid for example
                    if (tokenStream.HasMoreTokens && tokenStream.Next == ExpressionTokenType.LessThan)
                    {
                        tokenStream.Restore();
                        LightList <ASTNode> .Release(ref parts);

                        return(false);
                    }

                    TypeLookup typePath = new TypeLookup();

                    if (!(ParseTypePathGenerics(ref typePath)))
                    {
                        tokenStream.Restore();
                        LightList <ASTNode> .Release(ref parts);

                        return(false);
                    }

                    parts.Add(ASTNode.GenericTypePath(typePath));
                    if (tokenStream.HasMoreTokens)
                    {
                        continue;
                    }
                }

                if (parts.Count == 0)
                {
                    tokenStream.Restore();
                    LightList <ASTNode> .Release(ref parts);

                    return(false);
                }

                retn = ASTNode.MemberAccessExpressionNode(identifier, parts).WithLocation(tokenStream.Peek());
                return(true);
            }

            ReleaseList(parts);
            tokenStream.Restore();
            return(false);
        }
예제 #4
0
        private ASTNode ParseLoop()
        {
            while (tokenStream.HasMoreTokens)
            {
                ASTNode operand = default;
                if (ParseExpression(ref operand))
                {
                    if (tokenStream.Current == ExpressionTokenType.Increment)
                    {
                        tokenStream.Advance();
                        expressionStack.Push(ASTNode.UnaryExpressionNode(ASTNodeType.UnaryPostIncrement, operand));
                    }
                    else if (tokenStream.Current == ExpressionTokenType.Decrement)
                    {
                        tokenStream.Advance();
                        expressionStack.Push(ASTNode.UnaryExpressionNode(ASTNodeType.UnaryPostDecrement, operand));
                    }
                    else
                    {
                        expressionStack.Push(operand);
                    }

                    continue;
                }

                if (expressionStack.Count == 0)
                {
                    Abort();
                }

                if (tokenStream.Current == ExpressionTokenType.QuestionMark && !tokenStream.NextTokenIs(ExpressionTokenType.QuestionMark))
                {
                    while (operatorStack.Count != 0)
                    {
                        OperatorNode opNode = operatorStack.Pop();
                        opNode.right = expressionStack.Pop();
                        opNode.left  = expressionStack.Pop();
                        expressionStack.Push(opNode);
                    }

                    OperatorNode condition = ASTNode.OperatorNode(OperatorType.TernaryCondition);
                    OperatorNode selection = ASTNode.OperatorNode(OperatorType.TernarySelection);

                    condition.WithLocation(tokenStream.Previous);
                    tokenStream.Advance();
                    int idx = tokenStream.FindMatchingTernaryColon();

                    if (idx != -1)
                    {
                        TokenStream stream = tokenStream.AdvanceAndReturnSubStream(idx);

                        // parse the left side of the : operator
                        ExpressionParser parser   = new ExpressionParser(stream);
                        ASTNode          leftNode = parser.ParseLoop();
                        parser.Release();

                        tokenStream.Advance(); // step over colon

                        ExpressionParser parserRight = new ExpressionParser(tokenStream);
                        ASTNode          rightNode   = parserRight.ParseLoop();
                        tokenStream.Set(parserRight.tokenStream.CurrentIndex);
                        parserRight.Release(false);

                        selection.left  = leftNode;
                        selection.right = rightNode;

                        condition.left  = expressionStack.Pop();
                        condition.right = selection;

                        expressionStack.Push(condition);
                    }
                    else
                    {
                        // read to end use implicit default value for left hand side

                        ExpressionParser parserLeft = new ExpressionParser(tokenStream);
                        ASTNode          leftNode   = parserLeft.ParseLoop();
                        tokenStream.Set(parserLeft.tokenStream.CurrentIndex);
                        parserLeft.Release(false);

                        selection.left  = leftNode;
                        selection.right = ASTNode.DefaultLiteralNode("default");

                        condition.left  = expressionStack.Pop();
                        condition.right = selection;

                        expressionStack.Push(condition);
                    }

                    continue;
                }

                OperatorNode op;
                if (!ParseOperatorExpression(out op))
                {
                    Abort();
                    break;
                }

                while (operatorStack.Count != 0 && op.priority <= operatorStack.Peek().priority)
                {
                    OperatorNode opNode = operatorStack.Pop();
                    opNode.right = expressionStack.Pop();
                    opNode.left  = expressionStack.Pop();
                    expressionStack.Push(opNode);
                }

                operatorStack.Push(op);
            }

            while (operatorStack.Count != 0)
            {
                OperatorNode opNode = operatorStack.Pop();
                opNode.right = expressionStack.Pop();
                opNode.left  = expressionStack.Pop();
                expressionStack.Push(opNode);
            }

            if (expressionStack.Count != 1)
            {
                Abort();
            }

            return(expressionStack.Pop());
        }