public static CSharpType TryParse(TokenStream tokens) { tokens.SetTypeParsingMode(true); CSharpType type = TryParseImpl(tokens, true); tokens.SetTypeParsingMode(false); return(type); }
public static CSharpType ParseWithoutNullable(TokenStream tokens) { CSharpType type = TryParseWithoutNullable(tokens); if (type == null) { throw new ParserException(tokens.Peek(), "Expected a type."); } return(type); }
public static TopLevelEntity ParseClassMember( ClassLikeDefinition classDef, Token className, ParserContext context, TokenStream tokens) { Token firstToken = tokens.Peek(); Dictionary <string, Token> modifiers = ParseModifiers(context, tokens); if (tokens.IsNext("enum")) { return(ParseEnumDefinition(context, classDef, firstToken, modifiers, tokens)); } if (tokens.IsNext("class")) { return(ParseClass(context, classDef, firstToken, modifiers, tokens)); } if (tokens.IsNext("const")) { return(ParseConstDefinition(context, classDef, firstToken, modifiers, tokens)); } CSharpType type = CSharpType.TryParse(tokens); if (tokens.IsNext("(") && type.SimpleTypeName == className.Value) { return(ParseClassConstructor(context, classDef, firstToken, modifiers, type, tokens)); } Token memberName = tokens.PopWord(); if (tokens.IsNext(";") || tokens.IsNext("=")) { return(ParseClassField(context, classDef, firstToken, modifiers, type, memberName, tokens)); } if (tokens.IsNext("[") && memberName.Value == "this") { return(ParseIndexProperty(context, classDef, firstToken, modifiers, type, tokens)); } if (tokens.IsNext("{")) { return(ParseClassProperty(context, classDef, firstToken, modifiers, type, memberName, tokens)); } if (tokens.IsNext("(")) { return(ParseClassMethod(classDef, context, firstToken, modifiers, type, memberName, tokens)); } throw new ParserException(tokens.Peek(), "Not implemented"); }
private static TopLevelEntity ParseIndexProperty( ParserContext context, ClassLikeDefinition parent, Token firstToken, Dictionary <string, Token> modifiers, CSharpType type, TokenStream tokens) { tokens.PopExpected("["); CSharpType indexType = CSharpType.Parse(tokens); Token indexVariableName = tokens.PopWord(); tokens.PopExpected("]"); tokens.PopExpected("{"); PropertyDefinition indexProperty = new PropertyDefinition(firstToken, modifiers, type, null, parent); PropertyBody getter = null; PropertyBody setter = null; while (tokens.IsNext("get") || tokens.IsNext("set")) { Token getOrSetToken = tokens.Peek(); bool isGet = getOrSetToken.Value == "get"; if (!isGet && setter != null) { tokens.PopExpected("}"); // intentionally throw } if (isGet && getter != null) { tokens.PopExpected("set"); //intentionally throw } tokens.Pop(); // get/set already fetched with Peek() above. PropertyBody body = new PropertyBody(getOrSetToken, new Dictionary <string, Token>(), isGet, indexProperty); Executable[] code = ExecutableParser.ParseCodeBlock(context, tokens, body, true); body.Code = code; if (isGet) { getter = body; } else { setter = body; } } indexProperty.IndexType = indexType; indexProperty.IndexVariableName = indexVariableName; indexProperty.Getter = getter; indexProperty.Setter = setter; return(indexProperty); }
private static TopLevelEntity ParseClassProperty( ParserContext context, ClassLikeDefinition parent, Token firstToken, Dictionary <string, Token> modifiers, CSharpType type, Token propertyName, TokenStream tokens) { tokens.PopExpected("{"); PropertyDefinition propertyDefinition = new PropertyDefinition(firstToken, modifiers, type, propertyName, parent); PropertyBody getter = null; PropertyBody setter = null; while (!tokens.IsNext("}") && (getter == null || setter == null)) { Token bodyFirstToken = tokens.Peek(); Dictionary <string, Token> bodyModifiers = ParseModifiers(context, tokens); if (tokens.IsNext("get") && getter == null) { Token getToken = tokens.Pop(); getter = new PropertyBody(bodyFirstToken, bodyModifiers, true, propertyDefinition); if (!tokens.PopIfPresent(";")) { getter.Code = ExecutableParser.ParseCodeBlock(context, tokens, getter, true); } } else if (tokens.IsNext("set") && setter == null) { Token setToken = tokens.Pop(); setter = new PropertyBody(bodyFirstToken, bodyModifiers, false, propertyDefinition); if (!tokens.PopIfPresent(";")) { setter.Code = ExecutableParser.ParseCodeBlock(context, tokens, setter, true); } } else if (getter == null) { tokens.PopExpected("get"); // intentionally throw } else { tokens.PopExpected("set"); // intentionally throw } } tokens.PopExpected("}"); propertyDefinition.Getter = getter; propertyDefinition.Setter = setter; return(propertyDefinition); }
private static CSharpType ParseOutArraySuffix(CSharpType current, TokenStream tokens) { while (tokens.AreNext("[", "]")) { Token openBracket = tokens.Pop(); tokens.Pop(); Token firstToken = current.FirstToken; current = new CSharpType(new Token[] { openBracket }, new CSharpType[] { current }); current.FirstToken = firstToken; } return(current); }
private static Executable ParseForEachLoop(ParserContext context, TokenStream tokens, TopLevelEntity parent) { Token foreachToken = tokens.PopExpected("foreach"); tokens.PopExpected("("); CSharpType type = CSharpType.Parse(tokens); Token variableToken = tokens.PopWord(); tokens.PopExpected("in"); Expression listExpression = ExpressionParser.Parse(context, tokens, parent); tokens.PopExpected(")"); Executable[] loopBody = ParseCodeBlock(context, tokens, parent, false); return(new ForEachLoop(foreachToken, type, variableToken, listExpression, loopBody, parent)); }
private static Executable ParseTryStatement(ParserContext context, TokenStream tokens, TopLevelEntity parent) { Token tryToken = tokens.PopExpected("try"); Executable[] tryCode = ExecutableParser.ParseCodeBlock(context, tokens, parent, true); List <Token> catchTokens = new List <Token>(); List <CSharpType> catchBlockTypes = new List <CSharpType>(); List <Token> catchBlockVariables = new List <Token>(); List <Executable[]> catchBlockCode = new List <Executable[]>(); Token finallyToken = null; Executable[] finallyCode = null; while (tokens.IsNext("catch")) { catchTokens.Add(tokens.Pop()); tokens.PopExpected("("); catchBlockTypes.Add(CSharpType.Parse(tokens)); if (!tokens.PopIfPresent(")")) { catchBlockVariables.Add(tokens.PopWord()); tokens.PopExpected(")"); } else { catchBlockVariables.Add(null); } catchBlockCode.Add(ParseCodeBlock(context, tokens, parent, true)); } if (tokens.IsNext("finally")) { finallyToken = tokens.Pop(); finallyCode = ParseCodeBlock(context, tokens, parent, true); } return(new TryStatement( tryToken, tryCode, catchTokens, catchBlockTypes, catchBlockVariables, catchBlockCode, finallyToken, finallyCode, parent)); }
private static TopLevelEntity ParseClassConstructor( ParserContext context, ClassLikeDefinition classDef, Token firstToken, Dictionary <string, Token> modifiers, CSharpType type, TokenStream tokens) { List <CSharpType> argTypes = new List <CSharpType>(); List <Token> argNames = new List <Token>(); List <Token> argModifiers = new List <Token>(); ParseArgList(argTypes, argNames, argModifiers, tokens); ConstructorDefinition constructorDef = new ConstructorDefinition( firstToken, modifiers, argTypes, argNames, argModifiers, classDef); if (tokens.PopIfPresent(":")) { if (!tokens.IsNext("base") && !tokens.IsNext("this")) { tokens.PopExpected("base"); // intentionally throw } constructorDef.BaseConstructorInvocation = tokens.Pop(); tokens.PopExpected("("); List <Expression> baseConstructorArgs = new List <Expression>(); while (!tokens.PopIfPresent(")")) { if (baseConstructorArgs.Count > 0) { tokens.PopExpected(","); } baseConstructorArgs.Add(ExpressionParser.Parse(context, tokens, constructorDef)); } constructorDef.BaseConstructorArgs = baseConstructorArgs.ToArray(); } constructorDef.Code = ExecutableParser.ParseCodeBlock(context, tokens, constructorDef, true); return(constructorDef); }
private static TopLevelEntity ParseConstDefinition( ParserContext context, TopLevelEntity parent, Token firstToken, Dictionary <string, Token> modifiers, TokenStream tokens) { Token constToken = tokens.PopExpected("const"); CSharpType constType = CSharpType.Parse(tokens); Token name = tokens.PopWord(); tokens.PopExpected("="); ConstDefinition constDef = new ConstDefinition(firstToken, modifiers, constType, name, parent); Expression value = ExpressionParser.Parse(context, tokens, constDef); tokens.PopExpected(";"); constDef.Value = value; return(constDef); }
public static ClassLikeDefinition ParseClass(ParserContext context, TopLevelEntity parent, Token firstToken, Dictionary <string, Token> modifiers, TokenStream tokens) { if (!tokens.IsNext("class") && !tokens.IsNext("interface")) { tokens.PopExpected("class"); // intentionally throw } Token classToken = tokens.Pop(); bool isInterface = classToken.Value == "interface"; Token classNameToken = tokens.PopWord(); List <CSharpType> subClassesAndSuch = new List <CSharpType>(); if (tokens.PopIfPresent(":")) { while (!tokens.IsNext("{")) { if (subClassesAndSuch.Count > 0) { tokens.PopExpected(","); } subClassesAndSuch.Add(CSharpType.Parse(tokens)); } } tokens.PopExpected("{"); ClassLikeDefinition cd; if (isInterface) { cd = new InterfaceDefinition(firstToken, modifiers, classToken, classNameToken, subClassesAndSuch, parent); } else { cd = new ClassDefinition(firstToken, modifiers, classToken, classNameToken, subClassesAndSuch, parent); } while (!tokens.PopIfPresent("}")) { TopLevelEntity classMember = ParseClassMember(cd, classNameToken, context, tokens); cd.AddMember(classMember); } return(cd); }
private static TopLevelEntity ParseClassField( ParserContext context, ClassLikeDefinition parent, Token firstToken, Dictionary <string, Token> modifiers, CSharpType type, Token fieldName, TokenStream tokens) { FieldDefinition fieldDef = new FieldDefinition(firstToken, modifiers, type, fieldName, null, parent); if (!tokens.PopIfPresent(";")) { tokens.PopExpected("="); Expression initialValue = ExpressionParser.Parse(context, tokens, fieldDef); tokens.PopExpected(";"); fieldDef.InitialValue = initialValue; } return(fieldDef); }
private static Executable ParseUsingStatement(ParserContext context, TokenStream tokens, TopLevelEntity parent) { Token usingToken = tokens.PopExpected("using"); tokens.PopExpected("("); CSharpType type = null; Token variable = null; Token equalsToken = null; if (!tokens.IsNext("new")) { type = CSharpType.Parse(tokens); variable = tokens.PopWord(); equalsToken = tokens.PopExpected("="); } Expression expression = ExpressionParser.Parse(context, tokens, parent); tokens.PopExpected(")"); Executable[] code = ExecutableParser.ParseCodeBlock(context, tokens, parent, false); return(new UsingStatement(usingToken, type, variable, expression, code, parent)); }
private static void ParseArgList(List <CSharpType> typesOut, List <Token> namesOut, List <Token> modifiers, TokenStream tokens) { tokens.PopExpected("("); while (!tokens.IsNext(")")) { if (namesOut.Count > 0) { tokens.PopExpected(","); } if (tokens.IsNext("params") || tokens.IsNext("out")) { modifiers.Add(tokens.Pop()); } else { modifiers.Add(null); } typesOut.Add(CSharpType.Parse(tokens)); namesOut.Add(tokens.PopWord()); } tokens.PopExpected(")"); }
private static TopLevelEntity ParseClassMethod( ClassLikeDefinition classDef, ParserContext context, Token firstToken, Dictionary <string, Token> modifiers, CSharpType returnType, Token methodName, TokenStream tokens) { List <CSharpType> argTypes = new List <CSharpType>(); List <Token> argNames = new List <Token>(); List <Token> argModifiers = new List <Token>(); ParseArgList(argTypes, argNames, argModifiers, tokens); MethodDefinition methodDef = new MethodDefinition( firstToken, modifiers, returnType, methodName, argNames, argTypes, argModifiers, classDef); if (methodDef.IsAbstract || classDef is InterfaceDefinition) { tokens.PopExpected(";"); } else { methodDef.Code = ExecutableParser.ParseCodeBlock(context, tokens, methodDef, true); } return(methodDef); }
// this function is called after the first ( is popped off the token stream. // It is destructive to the token stream. private static ParenthesisSituation IdentifyParenthesisSituationImpl(TokenStream tokens) { int state = tokens.CurrentState; // if any of these cause an EOF exception, it's a legit EOF exception. // The }'s alone for any body of code that an expression can appear in would be enough padding // to avoid non-legit errors. Token t1 = tokens.Pop(); Token t2 = tokens.Pop(); Token t3 = tokens.Pop(); if (!t1.IsIdentifier) { return(ParenthesisSituation.WRAPPED_EXPRESSION); } if (t2.Value == ",") { return(ParenthesisSituation.LAMBDA_ARG); } if (t2.Value == ")" && t3.Value == "=>") { return(ParenthesisSituation.LAMBDA_ARG); } if (t2.Value == ")") { switch (t1.Value) { case "string": case "int": case "float": case "double": case "bool": case "object": case "byte": case "char": case "long": return(ParenthesisSituation.CAST); } } tokens.RestoreState(state); CSharpType type = CSharpType.TryParse(tokens); if (type == null || !tokens.IsNext(")")) { return(ParenthesisSituation.WRAPPED_EXPRESSION); } if (type.Generics.Length > 0) { return(ParenthesisSituation.CAST); } if (!tokens.PopIfPresent(")")) { return(ParenthesisSituation.WRAPPED_EXPRESSION); } if (!tokens.HasMore) { return(ParenthesisSituation.WRAPPED_EXPRESSION); } // At this point you have a sequence words and dots in parentheses. Token next = tokens.Peek(); if (next.IsIdentifier || next.IsNumber) { return(ParenthesisSituation.CAST); } char c = next.Value[0]; if (c == '(') { return(ParenthesisSituation.CAST); } if (c == '@') { return(ParenthesisSituation.CAST); } if (c == '.') { return(ParenthesisSituation.WRAPPED_EXPRESSION); } if (c == '!') { return(ParenthesisSituation.CAST); } return(ParenthesisSituation.WRAPPED_EXPRESSION); }
public static ResolvedType Create(CSharpType type, string[] prefixes, ParserContext context) { ResolvedType[] generics = EMPTY_GENERICS; if (type.Generics.Length > 0) { generics = type.Generics.Select(g => Create(g, prefixes, context)).ToArray(); } string typeString = type.RootTypeString; if (typeString == "[" || typeString == "?") { return(new ResolvedType() { IsArray = typeString == "[", IsNullable = typeString == "?", Generics = generics, }); } if (PRIMITIVE_TYPES.Contains(typeString)) { return(new ResolvedType() { Generics = EMPTY_GENERICS, PrimitiveType = typeString, IsVoid = typeString == "void", }); } foreach (string prefix in prefixes) { string fullyQualifiedName = prefix + typeString; if (FRAMEWORK_CLASSES_AND_PARENTS.ContainsKey(fullyQualifiedName)) { return(new ResolvedType() { FrameworkClass = fullyQualifiedName, Generics = generics, }); } if (GetFrameworkEnum(fullyQualifiedName) != null) { return(new ResolvedType() { FrameworkClass = fullyQualifiedName, Generics = EMPTY_GENERICS, IsEnum = true, }); } if (context != null) { TopLevelEntity tle = context.DoLookup(fullyQualifiedName); if (tle != null) { return(new ResolvedType() { CustomType = tle, Generics = generics, IsEnum = tle is EnumDefinition, }); } } } return(null); }
private static CSharpType TryParseImpl(TokenStream tokens, bool allowNullable) { int tokenState = tokens.CurrentState; IList <Token> rootType = GetRootType(tokens); if (rootType == null) { tokens.RestoreState(tokenState); return(null); } if (!PRIMITIVES_LOOKUP.Contains(rootType[0].Value)) { int preGenerics = tokens.CurrentState; if (tokens.PopIfPresent("<")) { bool isValid = true; CSharpType first = TryParseImpl(tokens, allowNullable); List <CSharpType> generics = new List <CSharpType>(); if (first != null) { generics.Add(first); while (isValid && !tokens.IsNext(">")) { if (!tokens.PopIfPresent(",")) { isValid = false; } else { CSharpType next = TryParseImpl(tokens, allowNullable); if (next == null) { isValid = false; } generics.Add(next); } } if (isValid && tokens.PopIfPresent(">")) { CSharpType o = new CSharpType(rootType, generics); if (tokens.IsNext("[")) { o = ParseOutArraySuffix(o, tokens); } return(o); } } } tokens.RestoreState(preGenerics); } CSharpType output = new CSharpType(rootType, EMPTY_GENERICS); if (allowNullable && tokens.IsNext("?")) { Token questionMark = tokens.Pop(); output = new CSharpType(new Token[] { questionMark }, new CSharpType[] { output }); } if (tokens.IsNext("[")) { output = ParseOutArraySuffix(output, tokens); } return(output); }
public static Executable Parse(ParserContext context, TokenStream tokens, TopLevelEntity parent, bool enableSemicolon) { switch (tokens.PeekValue()) { case "for": return(ParseForLoop(context, tokens, parent)); case "foreach": return(ParseForEachLoop(context, tokens, parent)); case "if": return(ParseIfStatement(context, tokens, parent)); case "while": return(ParseWhileLoop(context, tokens, parent)); case "do": return(ParseDoWhileLoop(context, tokens, parent)); case "switch": return(ParseSwitchStatement(context, tokens, parent)); case "throw": return(ParseThrowStatement(context, tokens, parent)); case "return": return(ParseReturnStatement(context, tokens, parent)); case "using": return(ParseUsingStatement(context, tokens, parent)); case "try": return(ParseTryStatement(context, tokens, parent)); default: break; } // check for variable declaration int state = tokens.CurrentState; CSharpType variableDeclarationType = CSharpType.TryParse(tokens); if (variableDeclarationType != null) { Token variableName = tokens.PopWordIfPresent(); if (variableName != null && (tokens.IsNext(";") || tokens.IsNext("=") || tokens.IsNext(","))) { // This is a variable declaration. Executable varDecl = ParseVariableDeclaration(context, tokens, variableDeclarationType, variableName, parent); if (enableSemicolon) { tokens.PopExpected(";"); } return(varDecl); } tokens.RestoreState(state); } Expression expr = ExpressionParser.Parse(context, tokens, parent); Executable exec; string nextToken = tokens.PeekValue(); switch (nextToken) { case "=": case "+=": case "-=": case "*=": case "/=": case "%=": case "|=": case "&=": case "^=": case "<<=": case ">>=": Token assignmentOpToken = tokens.Pop(); Expression assignmentValue = ExpressionParser.Parse(context, tokens, parent); exec = new AssignmentStatement(expr.FirstToken, expr, assignmentOpToken, assignmentValue, parent); break; default: exec = new ExpressionAsExecutable(expr, parent); break; } if (enableSemicolon) { tokens.PopExpected(";"); } return(exec); }
private static Expression ParseAtomWithSuffix(ParserContext context, TokenStream tokens, TopLevelEntity parent) { Expression root; if (tokens.IsNext("(")) { Token openParen = tokens.Pop(); switch (IdentifyParenthesisSituation(tokens)) { case ParenthesisSituation.CAST: CSharpType castType = CSharpType.Parse(tokens); tokens.PopExpected(")"); Expression castValue = ParseAtomWithSuffix(context, tokens, parent); return(new CastExpression(openParen, castType, castValue, parent)); case ParenthesisSituation.LAMBDA_ARG: List <Token> lambdaArgs = new List <Token>() { tokens.PopWord() }; while (tokens.PopIfPresent(",")) { lambdaArgs.Add(tokens.PopWord()); } tokens.PopExpected(")"); Token arrowToken = tokens.PopExpected("=>"); Executable[] lambdaBody; if (tokens.IsNext("{")) { lambdaBody = ExecutableParser.ParseCodeBlock(context, tokens, parent, true); } else { Expression expr = Parse(context, tokens, parent); lambdaBody = new Executable[] { new ReturnStatement(expr.FirstToken, expr, parent) }; } return(new Lambda(openParen, lambdaArgs, arrowToken, lambdaBody, parent)); case ParenthesisSituation.WRAPPED_EXPRESSION: root = Parse(context, tokens, parent); tokens.PopExpected(")"); break; default: throw new Exception(); // not valid } } else { root = ParseAtom(context, tokens, parent); } bool anythingInteresting = true; string next = tokens.PeekValue(); while (anythingInteresting) { switch (next) { case ".": Token dotToken = tokens.Pop(); Token fieldName = tokens.PopWord(); root = new DotField(root.FirstToken, root, dotToken, fieldName, parent); break; case "[": Token openBracket = tokens.Pop(); Expression index = Parse(context, tokens, parent); tokens.PopExpected("]"); root = new BracketIndex(root, openBracket, index, parent); break; case "<": if (root is DotField) { CSharpType[] functionInvocationTypeSpecification = MaybeParseOutOneOfThoseInlineTypeSpecificationsForFunctionInvocations(tokens); if (functionInvocationTypeSpecification != null) { ((DotField)root).InlineTypeSpecification = functionInvocationTypeSpecification; } else { anythingInteresting = false; } } else { anythingInteresting = false; } break; case "(": Token openParen = tokens.Pop(); List <Expression> args = new List <Expression>(); List <Token> outTokens = new List <Token>(); while (!tokens.PopIfPresent(")")) { if (args.Count > 0) { tokens.PopExpected(","); } if (tokens.IsNext("out")) { outTokens.Add(tokens.Pop()); } else { outTokens.Add(null); } args.Add(Parse(context, tokens, parent)); } root = new FunctionInvocation(root.FirstToken, root, openParen, args, outTokens, parent); break; case "{": // e.g. new List<int>() { 1, 2, 3 }. This only follows a constructor. FunctionInvocation fi = root as FunctionInvocation; ConstructorInvocationFragment cif = fi == null ? null : (ConstructorInvocationFragment)fi.Root; if (root is FunctionInvocation && ((FunctionInvocation)root).Root is ConstructorInvocationFragment) { tokens.Pop(); // { ConstructorSuffixData format = DetermineConstructorSuffixDataFormat(tokens); bool nextAllowed = true; List <Expression> values = new List <Expression>(); List <Expression> kvpKeys = new List <Expression>(); List <Token> propertyNames = new List <Token>(); while (!tokens.PopIfPresent("}")) { if (!nextAllowed) { tokens.PopExpected("}"); // intentionally throw } switch (format) { case ConstructorSuffixData.KVP_ENTRIES: tokens.PopExpected("{"); kvpKeys.Add(Parse(context, tokens, parent)); tokens.PopExpected(","); values.Add(Parse(context, tokens, parent)); tokens.PopExpected("}"); break; case ConstructorSuffixData.PROPERTIES: propertyNames.Add(tokens.PopWord()); tokens.PopExpected("="); values.Add(Parse(context, tokens, parent)); break; case ConstructorSuffixData.SEQUENTIAL_ITEMS: values.Add(Parse(context, tokens, parent)); break; } nextAllowed = tokens.PopIfPresent(","); } cif.InitialDataValues = values.ToArray(); int t = cif.InitialDataValues.Length; if (kvpKeys.Count == t) { cif.InitialDataKeys = kvpKeys.ToArray(); } if (propertyNames.Count == t) { cif.InitialDataPropertyNames = propertyNames.ToArray(); } } else { throw new ParserException(tokens.Peek(), "Unexpected '{'"); } break; default: anythingInteresting = false; break; } next = tokens.PeekValue(); } if (next == "++" || next == "--") { Token incrementToken = tokens.Pop(); root = new InlineIncrement(root.FirstToken, incrementToken, false, root, parent); } return(root); }
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 + "'"); }
private static Executable ParseVariableDeclaration(ParserContext context, TokenStream tokens, CSharpType type, Token name, TopLevelEntity parent) { Expression targetValue = null; Token assignmentToken = null; if (tokens.IsNext("=")) { assignmentToken = tokens.Pop(); targetValue = ExpressionParser.Parse(context, tokens, parent); } else if (tokens.IsNext(",")) { List <Token> variableNames = new List <Token>() { name }; while (tokens.PopIfPresent(",")) { variableNames.Add(tokens.PopWord()); } return(new MultiVariableDeclaration(type.FirstToken, type, variableNames, parent)); } return(new VariableDeclaration(type.FirstToken, type, name, assignmentToken, targetValue, parent)); }