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 + "'"); }