protected virtual ParseTemporariesResult ParseTemporaries(FunctionNode function, Token token) { // PARSE: <temporaries> ::= '|' <temporary variable list> '|' ParseTemporariesResult result = new ParseTemporariesResult(); if (!(token is VerticalBarToken)) { this.ResidueToken = token; return(result); } result.LeftBar = (VerticalBarToken)token; while (true) { token = this.GetNextTokenxx(Preference.VerticalBar); if (token is VerticalBarToken) { // Done with temp variables. result.RightBar = (VerticalBarToken)token; return(result); } if (token is IdentifierToken) { result.Temporaries.Add(new TemporaryVariableNode(function, (IdentifierToken)token)); } else { this.ReportParserError(function, SemanticErrors.MissingClosingTempBar, token); this.ResidueToken = token; return(result); } } }
protected virtual MethodNode ParseMethod() { // PARSE X3J20: <method definition> ::= <message pattern> [<temporaries> ] [<statements>] // NB: We've extended the method definition to allow API calls into the .Net Framework, // PARSE: <method definition> ::= <message pattern> [<temporaries>] [<api call>] [<statements>] MethodNode result = this.ParseMessagePattern(); Token token = this.GetNextTokenxx(Preference.NegativeSign | Preference.VerticalBar); // PARSE: [<temporaries>] ParseTemporariesResult ptr = this.ParseTemporaries(result, token); // PARSE [<api call>] token = this.GetNextTokenxx(Preference.NegativeSign); if (Parser.IsApiOpeningDelimiter(token)) { result.SetContents(this.ParseApiCall(result, (BinarySelectorToken)token)); token = this.GetNextTokenxx(Preference.NegativeSign); } // PARSE: <statements> StatementNode statements = this.ParseStatement(result, token); // Should be done. token = this.GetNextTokenxx(Preference.Default); if (!(token is EofToken)) { this.ReportParserError(result, SemanticErrors.UnexpectedCodeAfterMethodDefinition, token); } result.SetContents(ptr.LeftBar, ptr.Temporaries, ptr.RightBar, statements); return(result); }
protected virtual InitializerNode ParseInitializer() { // PARSE: <initializer definition> ::= [<temporaries>] [<statements>] InitializerNode result = new InitializerNode(); Token token = this.GetNextTokenxx(Preference.VerticalBar | Preference.NegativeSign); // PARSE: [<temporaries>] ParseTemporariesResult ptr = this.ParseTemporaries(result, token); // PARSE: <statements> token = this.GetNextTokenxx(Preference.NegativeSign); StatementNode statements = this.ParseStatement(result, token); // Should be done. token = this.GetNextTokenxx(Preference.Default); if (!(token is EofToken)) { this.ReportParserError(result, SemanticErrors.UnexpectedCodeAfterInitializer, token); } result.SetContents(ptr.LeftBar, ptr.Temporaries, ptr.RightBar, statements); return(result); }
protected virtual BlockNode ParseBlock(IPrimaryParentNode parent, SpecialCharacterToken leftBracket) { // PARSE: <block constructor> ::= '[' <block body> ']' // <block body> ::= [<block argument>* '|'] [<temporaries>] [<statements>] // <block argument> ::= ':' identifier BlockNode result = new BlockNode(parent, leftBracket); // PARSE: [<block argument>* '|'] // ISSUE: It this a bug in X3J20. Shouldn't it be: [<block argument>+ '|'] // The current definition allows blocks like: [ | ] ... or ... [ | self doStuff ] ... or ... [ | | temp | temp := self something ] // We assume X3J20 bug and expect: [<block argument>+ '|'] VerticalBarToken argumentsBar = null; List <BlockArgumentNode> arguments = new List <BlockArgumentNode>(); Token token = this.GetNextTokenxx(Preference.VerticalBar | Preference.NegativeSign); // Check if the block has arguments if (Parser.IsBlockArgumentPrefix(token)) { // ... yes arguments ... parse them ... while (true) { if (Parser.IsBlockArgumentPrefix(token)) { // <block argument> arguments.Add(this.ParseBlockArgument(result, (SpecialCharacterToken)token)); } else if (token is VerticalBarToken) { // The '|' after the arguments. argumentsBar = (VerticalBarToken)token; token = this.GetNextTokenxx(Preference.NegativeSign | Preference.VerticalBar); break; // Done with block arguments } else { this.ReportParserError(result, SemanticErrors.MissingBlockClosingArgsBar, token); break; } // Get the next token token = this.GetNextTokenxx(Preference.VerticalBar | Preference.NegativeSign); } } // PARSE: [<temporaries>] ParseTemporariesResult ptr = this.ParseTemporaries(result, token); // PARSE: <statements> token = this.GetNextTokenxx(Preference.NegativeSign); StatementNode statements = this.ParseStatement(result, token); // Ensure the block is properly closed. SpecialCharacterToken rightBracket = null; token = this.GetNextTokenxx(Preference.Default); if (!Parser.IsBlockEndDelimiter(token)) { this.ReportParserError(result, SemanticErrors.MissingBlockClosingBracket, token); this.ResidueToken = token; } else { rightBracket = (SpecialCharacterToken)token; } result.SetContents(arguments, argumentsBar, ptr.LeftBar, ptr.Temporaries, ptr.RightBar, statements, rightBracket); return(result); }
protected virtual ParseTemporariesResult ParseTemporaries(FunctionNode function, Token token) { // PARSE: <temporaries> ::= '|' <temporary variable list> '|' ParseTemporariesResult result = new ParseTemporariesResult(); if (!(token is VerticalBarToken)) { this.ResidueToken = token; return result; } result.LeftBar = (VerticalBarToken)token; while (true) { token = this.GetNextTokenxx(Preference.VerticalBar); if (token is VerticalBarToken) { // Done with temp variables. result.RightBar = (VerticalBarToken)token; return result; } if (token is IdentifierToken) { result.Temporaries.Add(new TemporaryVariableNode(function, (IdentifierToken)token)); } else { this.ReportParserError(function, SemanticErrors.MissingClosingTempBar, token); this.ResidueToken = token; return result; } } }