Example #1
0
        private bool ParseListExpressionStep(ref LightList <ASTNode> retn)
        {
            while (true)
            {
                int commaIndex = tokenStream.FindNextIndexAtSameLevel(ExpressionTokenType.Comma);
                if (commaIndex != -1)
                {
                    ExpressionParser parser = CreateUndelimitedSubParser(commaIndex);
                    tokenStream.Advance();
                    bool valid = parser.ParseListExpressionStep(ref retn);
                    parser.Release();
                    if (!valid)
                    {
                        ReleaseList(retn);
                        return(false);
                    }
                }
                else
                {
                    ASTNode node = ParseLoop();
                    if (node == null)
                    {
                        return(false);
                    }

                    retn.Add(node);
                    return(true);
                }
            }
        }
Example #2
0
        private bool ParseTypeOfExpression(ref ASTNode retn)
        {
            if (tokenStream.Current != ExpressionTokenType.TypeOf || tokenStream.Next != ExpressionTokenType.ParenOpen)
            {
                return(false);
            }

            tokenStream.Advance();

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

            if (advance == -1)
            {
                Abort();
                return(false);
            }

            tokenStream.Save();

            ExpressionParser subParser  = CreateSubParser(advance);
            TypeLookup       typeLookup = new TypeLookup();
            bool             valid      = subParser.ParseTypePath(ref typeLookup);

            subParser.Release();

            if (!valid)
            {
                Abort(); // hard fail since typeof token has no other paths to go
                tokenStream.Restore();
                return(false);
            }

            retn = ASTNode.TypeOfNode(typeLookup);
            return(true);
        }
Example #3
0
        private bool ParseTypePathGenerics(ref TypeLookup retn)
        {
            if (tokenStream.Current != ExpressionTokenType.LessThan)
            {
                return(false);
            }

            int advance = tokenStream.FindMatchingIndex(ExpressionTokenType.LessThan, ExpressionTokenType.GreaterThan);

            if (advance == -1)
            {
                //  Abort();
                return(false);
            }

            tokenStream.Save();

            ExpressionParser subParser = CreateSubParser(advance);
            bool             valid     = subParser.ParseTypePathGenericStep(ref retn);

            subParser.Release();

            if (!valid)
            {
                Abort();
            }

            //tokenStream.Advance();
            return(true);
        }
Example #4
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);
        }
Example #5
0
        public static ASTNode Parse(TokenStream tokenStream)
        {
            ExpressionParser parser = new ExpressionParser(tokenStream);
            ASTNode          retn   = parser.ParseLoop();

            parser.Release();
            return(retn);
        }
Example #6
0
        public static bool ParseSignature(TokenStream tokenStream, StructList <LambdaArgument> signature)
        {
            ExpressionParser parser = new ExpressionParser(tokenStream);
            bool             retn   = parser.ParseLambdaSignature(ref signature);

            parser.Release();
            if (!retn)
            {
                signature.Clear();
            }

            return(retn);
        }
Example #7
0
        public static bool TryParseTypeName(string typeName, out TypeLookup typeLookup)
        {
            StructList <ExpressionToken> list = StructList <ExpressionToken> .Get();

            ExpressionTokenizer.Tokenize(typeName, list);
            ExpressionParser parser = new ExpressionParser(new TokenStream(list));

            typeLookup = default;
            bool valid = parser.ParseTypePath(ref typeLookup);

            parser.Release();
            list.Release();
            return(valid);
        }
Example #8
0
        private bool ParseAttribute(ref AttributeNode node)
        {
            if (tokenStream.Current != ExpressionTokenType.ArrayAccessOpen)
            {
                return(false);
            }

            tokenStream.Save();
            tokenStream.Advance();
            TypeLookup       typeLookup = default;
            ExpressionParser parser     = new ExpressionParser(tokenStream);

            if (!parser.ParseTypePath(ref typeLookup))
            {
                goto fail;
            }

            tokenStream.Set(parser.GetTokenPosition());
            parser.Release(false);

            if (tokenStream.Current == ExpressionTokenType.ArrayAccessClose)
            {
                tokenStream.Advance();
                node = new AttributeNode()
                {
                    typeLookup = typeLookup
                };
                return(true);
            }

fail:
            {
                typeLookup.Release();
                parser.Release(false);
                return(false);
            }
        }
Example #9
0
        private bool ParseListExpression(ref LightList <ASTNode> retn, ExpressionTokenType openExpressionToken, ExpressionTokenType closeExpressionToken)
        {
            if (tokenStream.Current != openExpressionToken)
            {
                return(false);
            }

            int range = tokenStream.FindMatchingIndex(openExpressionToken, closeExpressionToken);

            tokenStream.Save();

            if (range == 1)
            {
                tokenStream.Advance(2);
                retn = LightList <ASTNode> .Get();

                return(true);
            }

            if (retn != null)
            {
                LightList <ASTNode> .Release(ref retn);
            }

            retn = LightList <ASTNode> .Get();

            //todo find next comma at same level (meaning not inside [ or ( or <

            ExpressionParser parser = CreateSubParser(range);
            bool             valid  = parser.ParseListExpressionStep(ref retn);

            parser.Release();

            if (!valid)
            {
                tokenStream.Restore();
                ReleaseList(retn);
                return(false);
            }

            return(true);
        }
Example #10
0
        // (int)something
        private bool ParseDirectCastExpression(ref ASTNode retn)
        {
            if (tokenStream.Current != ExpressionTokenType.ParenOpen)
            {
                return(false);
            }

            ASTNode expression = null;

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

            if (advance == -1)
            {
                Abort();
                return(false);
            }

            tokenStream.Save();

            ExpressionParser subParser  = CreateSubParser(advance);
            TypeLookup       typeLookup = new TypeLookup();
            bool             valid      = subParser.ParseTypePath(ref typeLookup);

            subParser.Release();

            if (!valid)
            {
                tokenStream.Restore();
                return(false);
            }

            if (!ParseExpression(ref expression))
            {
                typeLookup.Release();
                tokenStream.Restore();
                tokenStream.Restore();
                return(false);
            }

            retn = ASTNode.DirectCastNode(typeLookup, expression);
            return(true);
        }
Example #11
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);
        }
Example #12
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());
        }
Example #13
0
        private bool ParseDeclaration(ref ASTNode node)
        {
            AttributeNode             attrNode   = null;
            LightList <AttributeNode> attributes = LightList <AttributeNode> .Get();

            while (ParseAttribute(ref attrNode))
            {
                attributes.Add(attrNode);
                if (tokenStream.Current != ExpressionTokenType.ArrayAccessOpen)
                {
                    break;
                }
            }

            if (attributes.size == 0)
            {
                LightList <AttributeNode> .Release(ref attributes);
            }

            if (tokenStream.Current != ExpressionTokenType.Identifier)
            {
                return(false);
            }

            // modifiers? -> returnType -> name -> signature -> openBrace * closeBrace

            tokenStream.Save();

            bool isStatic = false;

            if (tokenStream.Current == "static")
            {
                isStatic = true;
                tokenStream.Advance();
            }

            ExpressionParser            parser    = new ExpressionParser(tokenStream);
            StructList <LambdaArgument> signature = null;
            TypeLookup typeLookup = default;

            if (!parser.ParseTypePath(ref typeLookup))
            {
                goto fail;
            }

            tokenStream.Set(parser.GetTokenPosition());
            parser.Release(false);

            if (tokenStream.Current != ExpressionTokenType.Identifier)
            {
                goto fail;
            }

            string name = tokenStream.Current.value;

            tokenStream.Advance();

            // if semi colon then we have a field!
            if (tokenStream.Current == ExpressionTokenType.SemiColon)
            {
                tokenStream.Advance();
                node = new FieldNode()
                {
                    name       = name,
                    isStatic   = isStatic,
                    attributes = attributes,
                    typeLookup = typeLookup
                };
                return(true);
            }

            if (tokenStream.Current != ExpressionTokenType.ParenOpen)
            {
                goto fail;
            }

            signature = StructList <LambdaArgument> .Get();

            if (tokenStream.NextTokenIs(ExpressionTokenType.ParenClose))
            {
                tokenStream.Advance(2);
            }
            else
            {
                int matchingIndex = tokenStream.FindMatchingIndex(ExpressionTokenType.ParenOpen, ExpressionTokenType.ParenClose);

                if (matchingIndex == -1)
                {
                    goto fail;
                }

                TokenStream subStream = tokenStream.AdvanceAndReturnSubStream(matchingIndex);
                subStream.Advance();
                tokenStream.Advance();
                if (!ExpressionParser.ParseSignature(subStream, signature))
                {
                    goto fail;
                }

                for (int i = 0; i < signature.size; i++)
                {
                    if (signature.array[i].type == null)
                    {
                        throw new ParseException($"When defining a method you must specify a type for all arguments. Found identifier {signature.array[i].identifier} but no type was given.");
                    }
                }
            }

            if (tokenStream.Current != ExpressionTokenType.ExpressionOpen)
            {
                goto fail;
            }

            BlockNode block = ParseBlock();

            node = new MethodNode()
            {
                body             = block,
                returnTypeLookup = typeLookup,
                attributes       = attributes,
                name             = name,
                isStatic         = isStatic,
                signatureList    = signature != null?signature.ToArray() : s_EmptySignature
            };

            StructList <LambdaArgument> .Release(ref signature);

            parser.Release(false);

            return(true);

fail:
            {
                tokenStream.Restore();
                parser.Release(false);
                typeLookup.Release();
                signature?.Release();
                return(false);
            }
        }
Example #14
0
        private bool ParseLocalVariableDeclaration(ref ASTNode node)
        {
            ExpressionParser parser     = default;
            TypeLookup       typeLookup = default;

            if (tokenStream.Current == ExpressionTokenType.Var)
            {
                if (!tokenStream.NextTokenIs(ExpressionTokenType.Identifier))
                {
                    return(false);
                }

                tokenStream.Advance();
            }
            else if (tokenStream.Current == ExpressionTokenType.Identifier)
            {
                tokenStream.Save();
                parser = new ExpressionParser(tokenStream);
                if (!parser.ParseTypePath(ref typeLookup))
                {
                    goto fail;
                }

                tokenStream.Set(parser.GetTokenPosition());
                parser.Release(false);
            }
            else
            {
                goto fail;
            }

            if (tokenStream.Current != ExpressionTokenType.Identifier)
            {
                goto fail;
            }

            string name = tokenStream.Current.value;

            tokenStream.Advance();

            if (tokenStream.Current == ExpressionTokenType.SemiColon)
            {
                tokenStream.Advance();
                node = new LocalVariableNode()
                {
                    name       = name,
                    typeLookup = typeLookup // will be default for var
                };
                return(true);
            }

            if (tokenStream.Current == ExpressionTokenType.Assign)
            {
                // todo -- would fail on this: var x = new F(() => { return x; });

                tokenStream.Advance();

                ASTNode expression = null;
                if (!ParseTerminatedExpression(ref expression))
                {
                    goto fail;
                }

                node = new LocalVariableNode()
                {
                    name       = name,
                    value      = expression,
                    typeLookup = typeLookup // will be default for var
                };

                return(true);
            }

fail:
            {
                parser.Release(false);
                typeLookup.Release();
                tokenStream.Restore();
                return(false);
            }
        }