private ConstructorDefinition ParseConstructor( TokenStream tokens, TopLevelConstruct owner, AnnotationCollection annotations) { 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 this.parser.GenerateParseError( ErrorMessages.OPTIONAL_ARGUMENT_WAS_NOT_AT_END_OF_ARGUMENT_LIST, argName); } 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 = ParserContext.ParseBlock(parser, tokens, true, owner); return(new ConstructorDefinition(constructorToken, argNames, argValues, baseArgs, code, baseToken, annotations, owner)); }
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)); } }
private FunctionDefinition ParseFunction( TokenStream tokens, TopLevelConstruct nullableOwner, FileScope fileScope, AnnotationCollection annotations) { bool isStatic = nullableOwner != null && nullableOwner is ClassDefinition && tokens.PopIfPresent(this.parser.Keywords.STATIC); Token functionToken = tokens.PopExpected(this.parser.Keywords.FUNCTION); Token functionNameToken = tokens.Pop(); this.parser.VerifyIdentifier(functionNameToken); FunctionDefinition fd = new FunctionDefinition(functionToken, parser.CurrentLibrary, nullableOwner, isStatic, functionNameToken, annotations, fileScope); tokens.PopExpected("("); List <Token> argNames = new List <Token>(); List <Expression> defaultValues = new List <Expression>(); bool optionalArgFound = false; while (!tokens.PopIfPresent(")")) { if (argNames.Count > 0) { tokens.PopExpected(","); } 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."); } argNames.Add(argName); defaultValues.Add(defaultValue); } IList <Executable> code = ParserContext.ParseBlock(parser, tokens, true, fd); fd.ArgNames = argNames.ToArray(); fd.DefaultValues = defaultValues.ToArray(); fd.Code = code.ToArray(); return(fd); }
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 = ParserContext.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 = ParserContext.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 = ParserContext.ParseBlock(parser, tokens, false, owner); IList <Executable> elseBody; if (tokens.PopIfPresent(this.parser.Keywords.ELSE)) { elseBody = ParserContext.ParseBlock(parser, tokens, false, owner); } else { elseBody = new Executable[0]; } return(new IfStatement(ifToken, condition, body, elseBody, owner)); }
private Executable ParseTry(TokenStream tokens, TopLevelConstruct owner) { Token tryToken = tokens.PopExpected(this.parser.Keywords.TRY); IList <Executable> tryBlock = ParserContext.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 = ParserContext.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 = ParserContext.ParseBlock(parser, tokens, true, owner); } return(new TryStatement(tryToken, tryBlock, catchTokens, exceptionVariables, exceptionTypeTokens, exceptionTypes, catchBlocks, finallyToken, finallyBlock, owner)); }