예제 #1
0
        private static Expression ParseAtom(ParserContext context, TokenStream tokens, TopLevelEntity parent)
        {
            string next = tokens.PeekValue();

            switch (next)
            {
            case "true":
            case "false":
                Token booleanToken = tokens.Pop();
                return(new BooleanConstant(booleanToken, booleanToken.Value == "true", parent));

            case "null":
                Token nullToken = tokens.Pop();
                return(new NullConstant(nullToken, parent));

            case "new":
                Token      newToken  = tokens.Pop();
                CSharpType className = CSharpType.TryParse(tokens);
                if (className == null)
                {
                    throw new ParserException(newToken, "'new' keyword must be followed by a className");
                }
                if (!tokens.IsNext("("))
                {
                    // could be a new array of which there are two ways to define it...
                    if (className.IsArray && tokens.IsNext("{"))
                    {
                        List <Expression> arrayItems = new List <Expression>();
                        tokens.PopExpected("{");
                        bool nextAllowed = true;
                        while (!tokens.PopIfPresent("}"))
                        {
                            if (!nextAllowed)
                            {
                                tokens.PopExpected("}");
                            }
                            arrayItems.Add(ExpressionParser.Parse(context, tokens, parent));
                            nextAllowed = tokens.PopIfPresent(",");
                        }
                        return(new ArrayInitialization(newToken, className.Generics[0], null, arrayItems, parent));
                    }

                    if (tokens.IsNext("["))
                    {
                        // a new array with specified length
                        tokens.PopExpected("[");
                        Expression arrayLength = ExpressionParser.Parse(context, tokens, parent);
                        tokens.PopExpected("]");
                        return(new ArrayInitialization(newToken, className, arrayLength, null, parent));
                    }

                    // if this isn't an array construction, then give a reasonable error message...
                    tokens.PopExpected("(");
                }
                return(new ConstructorInvocationFragment(newToken, className, parent));

            case "@":
                // raw string
                Token  rawStringAt       = tokens.Pop();
                Token  stringValue       = tokens.Pop();
                string stringValueActual = stringValue.Value;
                if (stringValueActual[0] != '"')
                {
                    throw new ParserException(stringValue, "Expected a string value");
                }
                return(new StringConstant(rawStringAt, stringValueActual.Substring(1, stringValueActual.Length - 2), parent));

            default: break;
            }

            Token token = tokens.Pop();
            char  c     = next[0];

            if (c == '"' || c == '\'')
            {
                string stringValue = StringUtil.ConvertStringTokenToValue(token);
                if (c == '"')
                {
                    return(new StringConstant(token, stringValue, parent));
                }
                else
                {
                    return(new CharConstant(token, stringValue, parent));
                }
            }

            if (c == '0' && next.Length > 2 && next[1] == 'x')
            {
                string hex         = next.Substring(2);
                int    parsedValue = 0;

                for (int i = 0; i < hex.Length; ++i)
                {
                    c = hex[i];
                    if (c >= '0' && c <= '9')
                    {
                        parsedValue = parsedValue * 16 + (c - '0');
                    }
                    else if (c >= 'a' && c <= 'f')
                    {
                        parsedValue = parsedValue * 16 + (10 + c - 'a');
                    }
                    else if (c >= 'A' && c <= 'F')
                    {
                        parsedValue = parsedValue * 16 + (10 + c - 'A');
                    }
                    else
                    {
                        throw new ParserException(token, "Invalid hexidecimal value: '" + hex + "'");
                    }
                }
                return(new IntegerConstant(token, parsedValue, parent));
            }

            if (c == '.' && next.Length > 1)
            {
                double value;
                if (!double.TryParse(next, out value))
                {
                    throw new ParserException(token, "Invalid double constant: '" + next + "'");
                }
                return(new DoubleConstant(token, value, parent));
            }

            if (c >= '0' && c <= '9')
            {
                if (next.Contains('.'))
                {
                    if (next.EndsWith("f") || next.EndsWith("F"))
                    {
                        throw new NotImplementedException();
                    }
                    double floatValue;
                    if (!double.TryParse(next, out floatValue))
                    {
                        throw new ParserException(token, "Invalid number: '" + next + "'");
                    }
                    return(new DoubleConstant(token, floatValue, parent));
                }
                else
                {
                    if (next.EndsWith("f") || next.EndsWith("F"))
                    {
                        throw new NotImplementedException();
                    }

                    int intValue;
                    if (!int.TryParse(next, out intValue))
                    {
                        throw new ParserException(token, "Invalid number: '" + next + "'");
                    }

                    return(new IntegerConstant(token, intValue, parent));
                }
            }

            if ((c >= 'a' && c <= 'z') ||
                (c >= 'A' && c <= 'Z') ||
                c == '_')
            {
                if (tokens.IsNext("=>"))
                {
                    List <Token> args = new List <Token>()
                    {
                        token
                    };
                    Token        arrowToken = tokens.Pop();
                    Executable[] lambdaBody;
                    if (tokens.IsNext("{"))
                    {
                        lambdaBody = ExecutableParser.ParseCodeBlock(context, tokens, parent, true);
                    }
                    else
                    {
                        Expression lambdaBodyExpr = Parse(context, tokens, parent);
                        lambdaBody = new Executable[] {
                            new ReturnStatement(lambdaBodyExpr.FirstToken, lambdaBodyExpr, parent),
                        };
                    }
                    return(new Lambda(token, args, arrowToken, lambdaBody, parent));
                }
                return(new Variable(token, parent));
            }

            throw new ParserException(token, "Unexpected token: '" + token.Value + "'");
        }