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 = Parser.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 = Parser.ParseBlock(parser, tokens, false, owner); return(new ForLoop(forToken, init, condition, step, body, owner)); } }
private ConstructorDefinition ParseConstructor(TokenStream tokens, TopLevelConstruct owner) { Token constructorToken = tokens.PopExpected(this.parser.Keywords.CONSTRUCTOR); tokens.PopExpected("("); List <Token> argNames = new List <Token>(); List <Expression> argValues = new List <Expression>(); bool optionalArgFound = false; while (!tokens.PopIfPresent(")")) { if (argNames.Count > 0) { tokens.PopExpected(","); } Token argName = tokens.Pop(); this.parser.VerifyIdentifier(argName); Expression defaultValue = null; if (tokens.PopIfPresent("=")) { defaultValue = this.parser.ExpressionParser.Parse(tokens, owner); optionalArgFound = true; } else if (optionalArgFound) { throw new ParserException(argName, "All optional arguments must come at the end of the argument list."); } argNames.Add(argName); argValues.Add(defaultValue); } List <Expression> baseArgs = new List <Expression>(); Token baseToken = null; if (tokens.PopIfPresent(":")) { baseToken = tokens.PopExpected(this.parser.Keywords.BASE); tokens.PopExpected("("); while (!tokens.PopIfPresent(")")) { if (baseArgs.Count > 0) { tokens.PopExpected(","); } baseArgs.Add(this.parser.ExpressionParser.Parse(tokens, owner)); } } IList <Executable> code = Parser.ParseBlock(parser, tokens, true, owner); return(new ConstructorDefinition(constructorToken, argNames, argValues, baseArgs, code, baseToken, owner)); }
private Executable ParseWhile(TokenStream tokens, TopLevelConstruct owner) { Token whileToken = tokens.PopExpected(this.parser.Keywords.WHILE); tokens.PopExpected("("); Expression condition = this.parser.ExpressionParser.Parse(tokens, owner); tokens.PopExpected(")"); IList <Executable> body = Parser.ParseBlock(parser, tokens, false, owner); return(new WhileLoop(whileToken, condition, body, owner)); }
private static Executable ParseWhile(Parser parser, TokenStream tokens, Executable owner) { Token whileToken = tokens.PopExpected("while"); tokens.PopExpected("("); Expression condition = ExpressionParser.Parse(tokens, owner); tokens.PopExpected(")"); IList <Executable> body = Parser.ParseBlock(parser, tokens, false, owner); return(new WhileLoop(whileToken, condition, body, owner)); }
private Executable ParseDoWhile(TokenStream tokens, TopLevelConstruct owner) { Token doToken = tokens.PopExpected(this.parser.Keywords.DO); IList <Executable> body = Parser.ParseBlock(parser, tokens, true, owner); tokens.PopExpected(this.parser.Keywords.DO_WHILE_END); tokens.PopExpected("("); Expression condition = this.parser.ExpressionParser.Parse(tokens, owner); tokens.PopExpected(")"); tokens.PopExpected(";"); return(new DoWhileLoop(doToken, body, condition, owner)); }
private Executable ParseIf(TokenStream tokens, TopLevelConstruct owner) { Token ifToken = tokens.PopExpected(this.parser.Keywords.IF); tokens.PopExpected("("); Expression condition = this.parser.ExpressionParser.Parse(tokens, owner); tokens.PopExpected(")"); IList <Executable> body = Parser.ParseBlock(parser, tokens, false, owner); IList <Executable> elseBody; if (tokens.PopIfPresent(this.parser.Keywords.ELSE)) { elseBody = Parser.ParseBlock(parser, tokens, false, owner); } else { elseBody = new Executable[0]; } return(new IfStatement(ifToken, condition, body, elseBody, owner)); }
private static Executable ParseIf(Parser parser, TokenStream tokens, Executable owner) { Token ifToken = tokens.PopExpected("if"); tokens.PopExpected("("); Expression condition = ExpressionParser.Parse(tokens, owner); tokens.PopExpected(")"); IList <Executable> body = Parser.ParseBlock(parser, tokens, false, owner); IList <Executable> elseBody; if (tokens.PopIfPresent("else")) { elseBody = Parser.ParseBlock(parser, tokens, false, owner); } else { elseBody = new Executable[0]; } return(new IfStatement(ifToken, condition, body, elseBody, owner)); }
private static Executable ParseTry(Parser parser, TokenStream tokens, Executable owner) { Token tryToken = tokens.PopExpected("try"); IList <Executable> tryBlock = Parser.ParseBlock(parser, tokens, true, owner); Token catchToken = null; IList <Executable> catchBlock = null; Token exceptionToken = null; Token finallyToken = null; IList <Executable> finallyBlock = null; if (tokens.IsNext("catch")) { catchToken = tokens.Pop(); if (tokens.PopIfPresent("(")) { exceptionToken = tokens.Pop(); char firstChar = exceptionToken.Value[0]; if (firstChar != '_' && !(firstChar >= 'a' && firstChar <= 'z') && !(firstChar >= 'A' && firstChar <= 'Z')) { throw new ParserException(exceptionToken, "Invalid name for variable."); } tokens.PopExpected(")"); } catchBlock = Parser.ParseBlock(parser, tokens, true, owner); } if (tokens.IsNext("finally")) { finallyToken = tokens.Pop(); finallyBlock = Parser.ParseBlock(parser, tokens, true, owner); } return(new TryStatement(tryToken, tryBlock, catchToken, exceptionToken, catchBlock, finallyToken, finallyBlock, owner)); }
private Executable ParseTry(TokenStream tokens, TopLevelConstruct owner) { Token tryToken = tokens.PopExpected(this.parser.Keywords.TRY); IList <Executable> tryBlock = Parser.ParseBlock(parser, tokens, true, owner); List <Token> catchTokens = new List <Token>(); List <string[]> exceptionTypes = new List <string[]>(); List <Token[]> exceptionTypeTokens = new List <Token[]>(); List <Token> exceptionVariables = new List <Token>(); List <Executable[]> catchBlocks = new List <Executable[]>(); Token finallyToken = null; IList <Executable> finallyBlock = null; while (tokens.IsNext(this.parser.Keywords.CATCH)) { /* * Parse patterns: * All exceptions: * 1a: catch { ... } * 1b: catch (e) { ... } * * A certain exception: * 2a: catch (ExceptionName) { ... } * 2b: catch (ExceptionName e) { ... } * * Certain exceptions: * 3a: catch (ExceptionName1 | ExceptionName2) { ... } * 3b: catch (ExceptionName1 | ExceptionName2 e) { ... } * * Non-Context-Free alert: * Note that if the exception variable does not contain a '.' character, 1b and 2a are * ambiguous at parse time. Treat them both as 1b and then if the classname resolution * fails, treat this as a variable. * * This is actually kind of bad because a typo in the classname will not be known. * e.g "catch (Excpetion) {" will compile as a variable called "Excpetion" * * End-user workarounds: * - always use a variable name OR * - always fully qualify exception types e.g. Core.Exception * Long-term plan: * - add warning support and emit warnings for: * - unused variables * - style-breaking uppercase variables. */ Token catchToken = tokens.PopExpected(this.parser.Keywords.CATCH); List <string> classNames = new List <string>(); List <Token> classTokens = new List <Token>(); Token variableToken = null; if (tokens.PopIfPresent("(")) { // This first one might actually be a variable. Assume class for now and sort it out later. // (and by "later" I mean the ResolveNames phase) Token classFirstToken = tokens.Pop(); string className = this.parser.PopClassNameWithFirstTokenAlreadyPopped(tokens, classFirstToken); classNames.Add(className); classTokens.Add(classFirstToken); while (tokens.PopIfPresent("|")) { classFirstToken = tokens.Pop(); className = this.parser.PopClassNameWithFirstTokenAlreadyPopped(tokens, classFirstToken); classNames.Add(className); classTokens.Add(classFirstToken); } if (!tokens.IsNext(")")) { variableToken = tokens.Pop(); this.parser.VerifyIdentifier(variableToken); } tokens.PopExpected(")"); } else { classNames.Add(null); classTokens.Add(null); } Executable[] catchBlockCode = Parser.ParseBlock(parser, tokens, true, owner).ToArray(); catchTokens.Add(catchToken); exceptionTypes.Add(classNames.ToArray()); exceptionTypeTokens.Add(classTokens.ToArray()); exceptionVariables.Add(variableToken); catchBlocks.Add(catchBlockCode); } if (tokens.IsNext(this.parser.Keywords.FINALLY)) { finallyToken = tokens.Pop(); finallyBlock = Parser.ParseBlock(parser, tokens, true, owner); } return(new TryStatement(tryToken, tryBlock, catchTokens, exceptionVariables, exceptionTypeTokens, exceptionTypes, catchBlocks, finallyToken, finallyBlock, owner)); }
private FunctionDefinition ParseFunction(TokenStream tokens, TopLevelConstruct nullableOwner, FileScope fileScope) { bool isStatic = nullableOwner != null && nullableOwner is ClassDefinition && tokens.PopIfPresent(this.parser.Keywords.STATIC); Token functionToken = tokens.PopExpected(this.parser.Keywords.FUNCTION); List <Annotation> functionAnnotations = new List <Annotation>(); while (tokens.IsNext("@")) { functionAnnotations.Add(this.parser.AnnotationParser.ParseAnnotation(tokens)); } Token functionNameToken = tokens.Pop(); this.parser.VerifyIdentifier(functionNameToken); FunctionDefinition fd = new FunctionDefinition(functionToken, parser.CurrentLibrary, nullableOwner, isStatic, functionNameToken, functionAnnotations, parser.CurrentNamespace, fileScope); tokens.PopExpected("("); List <Token> argNames = new List <Token>(); List <Expression> defaultValues = new List <Expression>(); List <Annotation> argAnnotations = new List <Annotation>(); bool optionalArgFound = false; while (!tokens.PopIfPresent(")")) { if (argNames.Count > 0) { tokens.PopExpected(","); } Annotation annotation = tokens.IsNext("@") ? this.parser.AnnotationParser.ParseAnnotation(tokens) : null; Token argName = tokens.Pop(); Expression defaultValue = null; this.parser.VerifyIdentifier(argName); if (tokens.PopIfPresent("=")) { optionalArgFound = true; defaultValue = this.parser.ExpressionParser.Parse(tokens, fd); } else if (optionalArgFound) { throw new ParserException(argName, "All optional arguments must come at the end of the argument list."); } argAnnotations.Add(annotation); argNames.Add(argName); defaultValues.Add(defaultValue); } IList <Executable> code = Parser.ParseBlock(parser, tokens, true, fd); fd.ArgNames = argNames.ToArray(); fd.DefaultValues = defaultValues.ToArray(); fd.ArgAnnotations = argAnnotations.ToArray(); fd.Code = code.ToArray(); return(fd); }