Exemplo n.º 1
0
        private Executable ParseFor(TokenStream tokens, TopLevelConstruct owner)
        {
            Token forToken = tokens.PopExpected(this.parser.Keywords.FOR);

            tokens.PopExpected("(");
            if (!tokens.HasMore)
            {
                tokens.ThrowEofException();
            }

            if (this.parser.IsValidIdentifier(tokens.PeekValue()) && tokens.PeekValue(1) == ":")
            {
                Token iteratorToken = tokens.Pop();
                if (this.parser.IsReservedKeyword(iteratorToken.Value))
                {
                    throw new ParserException(iteratorToken, "Cannot use this name for an iterator.");
                }
                tokens.PopExpected(":");
                Expression iterationExpression = this.parser.ExpressionParser.Parse(tokens, owner);
                tokens.PopExpected(")");
                IList <Executable> body = ParserContext.ParseBlock(parser, tokens, false, owner);

                return(new ForEachLoop(forToken, iteratorToken, iterationExpression, body, owner));
            }
            else
            {
                List <Executable> init = new List <Executable>();
                while (!tokens.PopIfPresent(";"))
                {
                    if (init.Count > 0)
                    {
                        tokens.PopExpected(",");
                    }
                    init.Add(this.Parse(tokens, true, false, owner));
                }
                Expression condition = null;
                if (!tokens.PopIfPresent(";"))
                {
                    condition = this.parser.ExpressionParser.Parse(tokens, owner);
                    tokens.PopExpected(";");
                }
                List <Executable> step = new List <Executable>();
                while (!tokens.PopIfPresent(")"))
                {
                    if (step.Count > 0)
                    {
                        tokens.PopExpected(",");
                    }
                    step.Add(this.Parse(tokens, true, false, owner));
                }

                IList <Executable> body = ParserContext.ParseBlock(parser, tokens, false, owner);

                return(new ForLoop(forToken, init, condition, step, body, owner));
            }
        }
Exemplo n.º 2
0
        private Expression ParseMultiplication(TokenStream tokens, Node owner)
        {
            Expression expr = ParseNegate(tokens, owner);
            string     next = tokens.PeekValue();

            while (MULTIPLICATION_OPS.Contains(next))
            {
                Token      op    = tokens.Pop();
                Expression right = ParseNegate(tokens, owner);
                expr = new OpChain(expr, op, right, owner);
                next = tokens.PeekValue();
            }
            return(expr);
        }
Exemplo n.º 3
0
        private Expression ParseAddition(TokenStream tokens, TopLevelConstruct owner)
        {
            Expression expr = ParseMultiplication(tokens, owner);
            string     next = tokens.PeekValue();

            while (ADDITION_OPS.Contains(next))
            {
                Token      op    = tokens.Pop();
                Expression right = ParseMultiplication(tokens, owner);
                expr = new BinaryOpChain(expr, op, right, owner);
                next = tokens.PeekValue();
            }
            return(expr);
        }
Exemplo n.º 4
0
        public static ModifierCollection Parse(TokenStream tokens)
        {
            if (!tokens.HasMore || !LOOKUP.ContainsKey(tokens.PeekValue()))
            {
                return(EMPTY);
            }

            List <Token> modifierTokens = new List <Token>();

            while (LOOKUP.ContainsKey(tokens.PeekValue()))
            {
                modifierTokens.Add(tokens.Pop());
            }
            return(new ModifierCollection(modifierTokens));
        }
Exemplo n.º 5
0
        private Expression ParseEqualityComparison(TokenStream tokens, Node owner)
        {
            Expression expr = ParseInequalityComparison(tokens, owner);
            string     next = tokens.PeekValue();

            if (next == "==" || next == "!=")
            {
                Token      equalityToken = tokens.Pop();
                Expression rightExpr     = ParseEqualityComparison(tokens, owner);
                return(new OpChain(expr, equalityToken, rightExpr, owner));
            }
            return(expr);
        }
Exemplo n.º 6
0
        private Expression ParseBitwiseOp(TokenStream tokens, Node owner)
        {
            Expression expr = ParseEqualityComparison(tokens, owner);
            string     next = tokens.PeekValue();

            if (next == "|" || next == "&" || next == "^")
            {
                Token      bitwiseToken = tokens.Pop();
                Expression rightExpr    = ParseBitwiseOp(tokens, owner);
                return(new OpChain(expr, bitwiseToken, rightExpr, owner));
            }
            return(expr);
        }
Exemplo n.º 7
0
        private Expression ParseBooleanCombination(TokenStream tokens, Node owner)
        {
            Expression expr = ParseBitwiseOp(tokens, owner);
            string     next = tokens.PeekValue();

            if (next == "||" || next == "&&")
            {
                List <Expression> expressions = new List <Expression>()
                {
                    expr
                };
                List <Token> ops = new List <Token>();
                while (next == "||" || next == "&&")
                {
                    ops.Add(tokens.Pop());
                    expressions.Add(ParseBitwiseOp(tokens, owner));
                    next = tokens.PeekValue();
                }
                return(new BooleanCombination(expressions, ops, owner));
            }
            return(expr);
        }
Exemplo n.º 8
0
        private Expression ParseExponents(TokenStream tokens, Node owner)
        {
            Expression expr = ParseIncrement(tokens, owner);
            string     next = tokens.PeekValue();

            if (next == "**")
            {
                Token      op    = tokens.Pop();
                Expression right = ParseNegate(tokens, owner);
                expr = new OpChain(expr, op, right, owner);
            }
            return(expr);
        }
Exemplo n.º 9
0
        private Expression ParseBitShift(TokenStream tokens, Node owner)
        {
            Expression expr = ParseAddition(tokens, owner);
            string     next = tokens.PeekValue();

            if (next == "<<" || next == ">>")
            {
                Token      opToken   = tokens.Pop();
                Expression rightExpr = ParseBitShift(tokens, owner);
                return(new OpChain(expr, opToken, rightExpr, owner));
            }
            return(expr);
        }
Exemplo n.º 10
0
        private Expression ParseInequalityComparison(TokenStream tokens, Node owner)
        {
            Expression expr = ParseBitShift(tokens, owner);
            string     next = tokens.PeekValue();

            if (next == "<" || next == ">" || next == "<=" || next == ">=")
            {
                // Don't allow chaining of inqeualities
                Token      opToken   = tokens.Pop();
                Expression rightExpr = ParseBitShift(tokens, owner);
                return(new OpChain(expr, opToken, rightExpr, owner));
            }
            return(expr);
        }
Exemplo n.º 11
0
        private Expression ParseNegate(TokenStream tokens, Node owner)
        {
            string next = tokens.PeekValue();

            if (NEGATE_OPS.Contains(next))
            {
                Token      negateOp = tokens.Pop();
                Expression root     = ParseNegate(tokens, owner);
                if (negateOp.Value == "!")
                {
                    return(new BooleanNot(negateOp, root, owner));
                }
                if (negateOp.Value == "-")
                {
                    return(new NegativeSign(negateOp, root, owner));
                }
                throw new Exception("This shouldn't happen.");
            }

            return(ParseExponents(tokens, owner));
        }
Exemplo n.º 12
0
        public TopLevelConstruct ParseTopLevel(
            TokenStream tokens,
            TopLevelConstruct owner,
            FileScope fileScope)
        {
            AnnotationCollection annotations = annotations = this.parser.AnnotationParser.ParseAnnotations(tokens);

            string value = tokens.PeekValue();

            // The returns are inline, so you'll have to refactor or put the check inside each parse call.
            // Or maybe a try/finally.
            TODO.CheckForUnusedAnnotations();

            Token staticToken = null;
            Token finalToken  = null;

            while (value == this.parser.Keywords.STATIC || value == this.parser.Keywords.FINAL)
            {
                if (value == this.parser.Keywords.STATIC && staticToken == null)
                {
                    staticToken = tokens.Pop();
                    value       = tokens.PeekValue();
                }
                if (value == this.parser.Keywords.FINAL && finalToken == null)
                {
                    finalToken = tokens.Pop();
                    value      = tokens.PeekValue();
                }
            }

            if (staticToken != null || finalToken != null)
            {
                if (value != this.parser.Keywords.CLASS)
                {
                    if (staticToken != null)
                    {
                        throw ParserException.ThrowException(this.parser.CurrentLocale, ErrorMessages.ONLY_CLASSES_METHODS_FIELDS_MAY_BE_STATIC, staticToken);
                    }
                    else
                    {
                        throw ParserException.ThrowException(this.parser.CurrentLocale, ErrorMessages.ONLY_CLASSES_MAY_BE_FINAL, finalToken);
                    }
                }

                if (staticToken != null && finalToken != null)
                {
                    throw ParserException.ThrowException(this.parser.CurrentLocale, ErrorMessages.CLASSES_CANNOT_BE_STATIC_AND_FINAL_SIMULTANEOUSLY, staticToken);
                }
            }

            if (value == parser.Keywords.IMPORT)
            {
                Token         importToken       = tokens.PopExpected(parser.Keywords.IMPORT);
                List <string> importPathBuilder = new List <string>();
                while (!tokens.PopIfPresent(";"))
                {
                    if (importPathBuilder.Count > 0)
                    {
                        tokens.PopExpected(".");
                    }

                    Token pathToken = tokens.Pop();
                    parser.VerifyIdentifier(pathToken);
                    importPathBuilder.Add(pathToken.Value);
                }
                string importPath = string.Join(".", importPathBuilder);

                return(new ImportStatement(importToken, importPath, parser.CurrentLibrary, fileScope));
            }

            if (value == this.parser.Keywords.NAMESPACE)
            {
                return(this.ParseNamespace(tokens, owner, fileScope, annotations));
            }
            if (value == this.parser.Keywords.CONST)
            {
                return(this.ParseConst(tokens, owner, fileScope, annotations));
            }
            if (value == this.parser.Keywords.FUNCTION)
            {
                return(this.ParseFunction(tokens, owner, fileScope, annotations));
            }
            if (value == this.parser.Keywords.CLASS)
            {
                return(this.ParseClassDefinition(tokens, owner, staticToken, finalToken, fileScope, annotations));
            }
            if (value == this.parser.Keywords.ENUM)
            {
                return(this.ParseEnumDefinition(tokens, owner, fileScope, annotations));
            }
            if (value == this.parser.Keywords.CONSTRUCTOR)
            {
                return(this.ParseConstructor(tokens, owner, annotations));
            }

            Token token = tokens.Peek();

            throw ParserException.ThrowException(
                      this.parser.CurrentLocale,
                      ErrorMessages.UNEXPECTED_TOKEN_NO_SPECIFIC_EXPECTATIONS,
                      token,
                      token.Value);
        }
Exemplo n.º 13
0
        public Executable Parse(
            TokenStream tokens,
            bool simpleOnly,
            bool semicolonPresent,
            TopLevelConstruct owner)
        {
            string value = tokens.PeekValue();

            if (!simpleOnly)
            {
                if (value == this.parser.Keywords.FUNCTION || value == this.parser.Keywords.CLASS)
                {
                    throw new ParserException(
                              tokens.Peek(),
                              (value == this.parser.Keywords.FUNCTION ? "Function" : "Class") +
                              " definition cannot be nested in another construct.");
                }

                if (value == parser.Keywords.IMPORT)
                {
                    throw this.parser.GenerateParseError(ErrorMessages.ALL_IMPORTS_MUST_OCCUR_AT_BEGINNING_OF_FILE, tokens.Peek());
                }

                if (value == this.parser.Keywords.ENUM)
                {
                    throw new ParserException(tokens.Peek(), "Enums can only be defined from the root of a file and cannot be nested inside functions/loops/etc.");
                }

                if (value == this.parser.Keywords.NAMESPACE)
                {
                    throw new ParserException(tokens.Peek(), "Namespace declarations cannot be nested in other constructs.");
                }

                if (value == this.parser.Keywords.CONST)
                {
                    throw new ParserException(tokens.Peek(), "Constant declarations cannot be nested in other constructs.");
                }

                if (value == this.parser.Keywords.FOR)
                {
                    return(this.ParseFor(tokens, owner));
                }
                if (value == this.parser.Keywords.WHILE)
                {
                    return(this.ParseWhile(tokens, owner));
                }
                if (value == this.parser.Keywords.DO)
                {
                    return(this.ParseDoWhile(tokens, owner));
                }
                if (value == this.parser.Keywords.SWITCH)
                {
                    return(this.ParseSwitch(tokens, owner));
                }
                if (value == this.parser.Keywords.IF)
                {
                    return(this.ParseIf(tokens, owner));
                }
                if (value == this.parser.Keywords.TRY)
                {
                    return(this.ParseTry(tokens, owner));
                }
                if (value == this.parser.Keywords.RETURN)
                {
                    return(this.ParseReturn(tokens, owner));
                }
                if (value == this.parser.Keywords.BREAK)
                {
                    return(this.ParseBreak(tokens, owner));
                }
                if (value == this.parser.Keywords.CONTINUE)
                {
                    return(this.ParseContinue(tokens, owner));
                }
                if (value == this.parser.Keywords.THROW)
                {
                    return(this.ParseThrow(tokens, owner));
                }
            }

            Expression expr = this.parser.ExpressionParser.Parse(tokens, owner);

            value = tokens.PeekValue();
            if (ASSIGNMENT_OPS.Contains(value))
            {
                Token      assignment      = tokens.Pop();
                Expression assignmentValue = this.parser.ExpressionParser.Parse(tokens, owner);
                if (semicolonPresent)
                {
                    tokens.PopExpected(";");
                }
                return(new Assignment(expr, assignment, assignment.Value, assignmentValue, owner));
            }

            if (semicolonPresent)
            {
                tokens.PopExpected(";");
            }

            return(new ExpressionAsExecutable(expr, owner));
        }
Exemplo n.º 14
0
        private Expression ParseEntityWithoutSuffixChain(TokenStream tokens, TopLevelConstruct owner)
        {
            string next = tokens.PeekValue();

            if (next == null)
            {
                tokens.ThrowEofException();
            }
            if (next == this.parser.Keywords.NULL)
            {
                return(new NullConstant(tokens.Pop(), owner));
            }
            if (next == this.parser.Keywords.TRUE)
            {
                return(new BooleanConstant(tokens.Pop(), true, owner));
            }
            if (next == this.parser.Keywords.FALSE)
            {
                return(new BooleanConstant(tokens.Pop(), false, owner));
            }

            Token peekToken = tokens.Peek();

            if (next.StartsWith("'"))
            {
                return(new StringConstant(tokens.Pop(), StringConstant.ParseOutRawValue(peekToken), owner));
            }
            if (next.StartsWith("\""))
            {
                return(new StringConstant(tokens.Pop(), StringConstant.ParseOutRawValue(peekToken), owner));
            }
            if (next == this.parser.Keywords.NEW)
            {
                return(this.ParseInstantiate(tokens, owner));
            }

            char firstChar = next[0];

            if (VARIABLE_STARTER.Contains(firstChar))
            {
                Token varToken = tokens.Pop();
                return(new Variable(varToken, varToken.Value, owner));
            }

            if (firstChar == '[')
            {
                Token             bracketToken = tokens.PopExpected("[");
                List <Expression> elements     = new List <Expression>();
                bool previousHasCommaOrFirst   = true;
                while (!tokens.PopIfPresent("]"))
                {
                    if (!previousHasCommaOrFirst)
                    {
                        tokens.PopExpected("]");                           // throws appropriate error
                    }
                    elements.Add(Parse(tokens, owner));
                    previousHasCommaOrFirst = tokens.PopIfPresent(",");
                }
                return(new ListDefinition(bracketToken, elements, owner));
            }

            if (firstChar == '{')
            {
                Token             braceToken = tokens.PopExpected("{");
                List <Expression> keys       = new List <Expression>();
                List <Expression> values     = new List <Expression>();
                bool previousHasCommaOrFirst = true;
                while (!tokens.PopIfPresent("}"))
                {
                    if (!previousHasCommaOrFirst)
                    {
                        tokens.PopExpected("}");                           // throws appropriate error
                    }
                    keys.Add(Parse(tokens, owner));
                    tokens.PopExpected(":");
                    values.Add(Parse(tokens, owner));
                    previousHasCommaOrFirst = tokens.PopIfPresent(",");
                }
                return(new DictionaryDefinition(braceToken, keys, values, owner));
            }

            if (next.Length > 2 && next.Substring(0, 2) == "0x")
            {
                Token intToken = tokens.Pop();
                int   intValue = IntegerConstant.ParseIntConstant(intToken, intToken.Value);
                return(new IntegerConstant(intToken, intValue, owner));
            }

            if (ParserContext.IsInteger(next))
            {
                Token  numberToken = tokens.Pop();
                string numberValue = numberToken.Value;

                if (tokens.IsNext("."))
                {
                    Token decimalToken = tokens.Pop();
                    if (decimalToken.HasWhitespacePrefix)
                    {
                        throw new ParserException(decimalToken, "Decimals cannot have whitespace before them.");
                    }

                    Token afterDecimal = tokens.Pop();
                    if (afterDecimal.HasWhitespacePrefix)
                    {
                        throw new ParserException(afterDecimal, "Cannot have whitespace after the decimal.");
                    }
                    if (!ParserContext.IsInteger(afterDecimal.Value))
                    {
                        throw new ParserException(afterDecimal, "Decimal must be followed by an integer.");
                    }

                    numberValue += "." + afterDecimal.Value;

                    double floatValue = FloatConstant.ParseValue(numberToken, numberValue);
                    return(new FloatConstant(numberToken, floatValue, owner));
                }

                int intValue = IntegerConstant.ParseIntConstant(numberToken, numberToken.Value);
                return(new IntegerConstant(numberToken, intValue, owner));
            }

            if (tokens.IsNext("."))
            {
                Token  dotToken    = tokens.PopExpected(".");
                string numberValue = "0.";
                Token  postDecimal = tokens.Pop();
                if (postDecimal.HasWhitespacePrefix || !ParserContext.IsInteger(postDecimal.Value))
                {
                    throw new ParserException(dotToken, "Unexpected dot.");
                }

                numberValue += postDecimal.Value;

                double floatValue;
                if (Util.ParseDouble(numberValue, out floatValue))
                {
                    return(new FloatConstant(dotToken, floatValue, owner));
                }

                throw new ParserException(dotToken, "Invalid float literal.");
            }

            throw new ParserException(tokens.Peek(), "Encountered unexpected token: '" + tokens.PeekValue() + "'");
        }
Exemplo n.º 15
0
        public TopLevelConstruct ParseTopLevel(
            TokenStream tokens,
            TopLevelConstruct owner,
            FileScope fileScope)
        {
            AnnotationCollection annotations = annotations = this.parser.AnnotationParser.ParseAnnotations(tokens);

            string value = tokens.PeekValue();

            // The returns are inline, so you'll have to refactor or put the check inside each parse call.
            // Or maybe a try/finally.
            TODO.CheckForUnusedAnnotations();

            Token staticToken = null;
            Token finalToken  = null;

            while (value == this.parser.Keywords.STATIC || value == this.parser.Keywords.FINAL)
            {
                if (value == this.parser.Keywords.STATIC && staticToken == null)
                {
                    staticToken = tokens.Pop();
                    value       = tokens.PeekValue();
                }
                if (value == this.parser.Keywords.FINAL && finalToken == null)
                {
                    finalToken = tokens.Pop();
                    value      = tokens.PeekValue();
                }
            }

            if (staticToken != null || finalToken != null)
            {
                if (value != this.parser.Keywords.CLASS)
                {
                    if (staticToken != null)
                    {
                        throw new ParserException(staticToken, "Only classes, methods, and fields may be marked as static");
                    }
                    else
                    {
                        throw new ParserException(finalToken, "Only classes may be marked as final.");
                    }
                }

                if (staticToken != null && finalToken != null)
                {
                    throw new ParserException(staticToken, "Classes cannot be both static and final.");
                }
            }

            if (value == parser.Keywords.IMPORT)
            {
                Token         importToken       = tokens.PopExpected(parser.Keywords.IMPORT);
                List <string> importPathBuilder = new List <string>();
                while (!tokens.PopIfPresent(";"))
                {
                    if (importPathBuilder.Count > 0)
                    {
                        tokens.PopExpected(".");
                    }

                    Token pathToken = tokens.Pop();
                    parser.VerifyIdentifier(pathToken);
                    importPathBuilder.Add(pathToken.Value);
                }
                string importPath = string.Join(".", importPathBuilder);

                return(new ImportStatement(importToken, importPath, parser.CurrentLibrary, fileScope));
            }

            if (value == this.parser.Keywords.NAMESPACE)
            {
                return(this.ParseNamespace(tokens, owner, fileScope, annotations));
            }
            if (value == this.parser.Keywords.CONST)
            {
                return(this.ParseConst(tokens, owner, fileScope, annotations));
            }
            if (value == this.parser.Keywords.FUNCTION)
            {
                return(this.ParseFunction(tokens, owner, fileScope, annotations));
            }
            if (value == this.parser.Keywords.CLASS)
            {
                return(this.ParseClassDefinition(tokens, owner, staticToken, finalToken, fileScope, annotations));
            }
            if (value == this.parser.Keywords.ENUM)
            {
                return(this.ParseEnumDefinition(tokens, owner, fileScope, annotations));
            }
            if (value == this.parser.Keywords.CONSTRUCTOR)
            {
                return(this.ParseConstructor(tokens, owner, annotations));
            }

            throw new ParserException(tokens.Peek(), "Unrecognized token.");
        }
Exemplo n.º 16
0
        internal virtual TopLevelEntity Parse(
            TokenStream tokens,
            TopLevelEntity owner,
            FileScope fileScope)
        {
            AnnotationCollection annotations = this.parser.AnnotationParser.ParseAnnotations(tokens);

            ModifierCollection modifiers = ModifierCollection.Parse(tokens);

            string value = tokens.PeekValue();

            if (value == this.parser.Keywords.IMPORT)
            {
                throw this.parser.GenerateParseError(
                          ErrorMessages.ALL_IMPORTS_MUST_OCCUR_AT_BEGINNING_OF_FILE,
                          tokens.Pop());
            }

            // The returns are inline, so you'll have to refactor or put the check inside each parse call.
            // Or maybe a try/finally.
            TODO.CheckForUnusedAnnotations();

            if (value == this.parser.Keywords.NAMESPACE)
            {
                return(this.ParseNamespace(tokens, owner, fileScope, annotations));
            }
            if (value == this.parser.Keywords.CONST)
            {
                return(this.ParseConst(tokens, owner, fileScope, modifiers, annotations));
            }
            if (value == this.parser.Keywords.FUNCTION)
            {
                return(this.ParseFunction(tokens, owner, fileScope, modifiers, annotations));
            }
            if (value == this.parser.Keywords.CLASS)
            {
                return(this.ParseClassDefinition(tokens, owner, fileScope, modifiers, annotations));
            }
            if (value == this.parser.Keywords.ENUM)
            {
                return(this.ParseEnumDefinition(tokens, owner, fileScope, modifiers, annotations));
            }
            if (value == this.parser.Keywords.CONSTRUCTOR && owner is ClassDefinition)
            {
                return(this.ParseConstructor(tokens, (ClassDefinition)owner, modifiers, annotations));
            }

            FunctionDefinition nullableFunctionDef = this.MaybeParseFunctionDefinition(tokens, owner, fileScope, annotations, modifiers);

            if (nullableFunctionDef != null)
            {
                return(nullableFunctionDef);
            }

            Token token = tokens.Peek();

            throw ParserException.ThrowException(
                      this.parser.CurrentLocale,
                      ErrorMessages.UNEXPECTED_TOKEN_NO_SPECIFIC_EXPECTATIONS,
                      token,
                      token.Value);
        }
Exemplo n.º 17
0
        private Expression ParseEntityWithoutSuffixChain(TokenStream tokens, Node owner)
        {
            tokens.EnsureNotEof();

            Token  nextToken = tokens.Peek();
            string next      = nextToken.Value;

            if (next == this.parser.Keywords.NULL)
            {
                return(new NullConstant(tokens.Pop(), owner));
            }
            if (next == this.parser.Keywords.TRUE)
            {
                return(new BooleanConstant(tokens.Pop(), true, owner));
            }
            if (next == this.parser.Keywords.FALSE)
            {
                return(new BooleanConstant(tokens.Pop(), false, owner));
            }
            if (next == this.parser.Keywords.THIS)
            {
                return(new ThisKeyword(tokens.Pop(), owner));
            }
            if (next == this.parser.Keywords.BASE)
            {
                return(new BaseKeyword(tokens.Pop(), owner));
            }

            Token peekToken = tokens.Peek();

            if (next.StartsWith("'"))
            {
                return(new StringConstant(tokens.Pop(), StringConstant.ParseOutRawValue(peekToken), owner));
            }
            if (next.StartsWith("\""))
            {
                return(new StringConstant(tokens.Pop(), StringConstant.ParseOutRawValue(peekToken), owner));
            }
            if (next == "@") // Raw strings (no escape sequences, a backslash is a literal backslash)
            {
                Token atToken         = tokens.Pop();
                Token stringToken     = tokens.Pop();
                char  stringTokenChar = stringToken.Value[0];
                if (stringTokenChar != '"' && stringTokenChar != '\'')
                {
                    throw new ParserException(atToken, "Unexpected token: '@'");
                }
                string stringValue = stringToken.Value.Substring(1, stringToken.Value.Length - 2);
                return(new StringConstant(atToken, stringValue, owner));
            }
            if (next == this.parser.Keywords.NEW)
            {
                return(this.ParseInstantiate(tokens, owner));
            }

            char firstChar = next[0];

            if (nextToken.Type == TokenType.WORD)
            {
                Token varToken = tokens.Pop();
                if (tokens.IsNext("=>"))
                {
                    return(this.ParseLambda(
                               tokens,
                               varToken,
                               new AType[] { AType.Any() },
                               new Token[] { varToken },
                               owner));
                }
                else
                {
                    return(new Variable(varToken, varToken.Value, owner));
                }
            }

            if (firstChar == '[' && nextToken.File.CompilationScope.IsCrayon)
            {
                Token             bracketToken = tokens.PopExpected("[");
                List <Expression> elements     = new List <Expression>();
                bool previousHasCommaOrFirst   = true;
                while (!tokens.PopIfPresent("]"))
                {
                    if (!previousHasCommaOrFirst)
                    {
                        tokens.PopExpected("]");                           // throws appropriate error
                    }
                    elements.Add(Parse(tokens, owner));
                    previousHasCommaOrFirst = tokens.PopIfPresent(",");
                }
                return(new ListDefinition(bracketToken, elements, AType.Any(), owner, false, null));
            }

            if (firstChar == '{' && nextToken.File.CompilationScope.IsCrayon)
            {
                Token             braceToken = tokens.PopExpected("{");
                List <Expression> keys       = new List <Expression>();
                List <Expression> values     = new List <Expression>();
                bool previousHasCommaOrFirst = true;
                while (!tokens.PopIfPresent("}"))
                {
                    if (!previousHasCommaOrFirst)
                    {
                        tokens.PopExpected("}");                           // throws appropriate error
                    }
                    keys.Add(Parse(tokens, owner));
                    tokens.PopExpected(":");
                    values.Add(Parse(tokens, owner));
                    previousHasCommaOrFirst = tokens.PopIfPresent(",");
                }
                return(new DictionaryDefinition(braceToken, AType.Any(), AType.Any(), keys, values, owner));
            }

            if (nextToken.Type == TokenType.NUMBER)
            {
                if (next.Contains("."))
                {
                    double floatValue;
                    if (double.TryParse(next, out floatValue))
                    {
                        return(new FloatConstant(tokens.Pop(), floatValue, owner));
                    }
                    throw new ParserException(nextToken, "Invalid float literal.");
                }
                return(new IntegerConstant(
                           tokens.Pop(),
                           IntegerConstant.ParseIntConstant(nextToken, next),
                           owner));
            }

            throw new ParserException(tokens.Peek(), "Encountered unexpected token: '" + tokens.PeekValue() + "'");
        }