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); }
/// <summary> /// Create a new cascade message sequence. /// </summary> /// <param name="parent">Parent node that defines this cascade message node.</param> /// <param name="token">Token representing the semicolon used to delimit cascade message sequences.</param> protected internal CascadeMessageSequenceNode(ICascadeMessageSequenceParentNode parent, SpecialCharacterToken token) { #if DEBUG if (parent == null) { throw new ArgumentNullException("parent"); } if (token == null) { throw new ArgumentNullException("token"); } #endif this.Parent = parent; this.Semicolon = token; }
protected virtual ArrayLiteralNode ParseArrayLiteral(ILiteralNodeParent parent, SpecialCharacterToken arrayToken) { // PARSE: <array literal> ::= '#(' <array element>* ')' // <array element> ::= <literal> | identifier Token token = this.GetNextTokenxx(Preference.Default); if (!Parser.IsOpeningParenthesis(token)) { this.ReportParserError(parent, SemanticErrors.MissingLiteralArrayOpeningParenthesis, token); // The hash token is thrown away and lost :-/ ... only the current token is passed on. this.ResidueToken = token; return(null); } List <LiteralNode> elements = new List <LiteralNode>(); ArrayLiteralNode result = new ArrayLiteralNode(parent, arrayToken, (SpecialCharacterToken)token); // Process tokens inside the array ... while (true) { // ... get next token in the array ... token = this.GetNextTokenxx(Preference.NegativeSign | Preference.UnquotedSelector); // Is this closing parenthesis? if (Parser.IsClosingParenthesis(token)) { // Closing parenthesis ... done with the array, return litral array node. result.SetContents(elements, (SpecialCharacterToken)token); this.ResidueToken = null; return(result); } if (token is EofToken) { // Unfinished source code ... return result.SetContents(elements, null); this.ReportParserError(parent, SemanticErrors.MissingLiteralArrayClosingParenthesis, token); this.ResidueToken = token; return(result); } // PARSE: <array element> ::= <literal> | identifier if (token is ILiteralArrayIdentifierToken) { // identifier ... special case only inside arrays. elements.Add(new IdentifierLiteralNode(result, (ILiteralArrayIdentifierToken)token)); } else { // ... it's not identifier, so it must be an literal LiteralNode element = this.ParseLiteral(result, token); if (element == null) { // Report error in source code ... here, it must be a literal this.ReportParserError(result, SemanticErrors.UnrecognizedLiteral, token); result.SetContents(elements, null); return(result); } else { // ... add the child element to the array elements. elements.Add(element); } } } }
protected ByteArrayLiteralNode ParseByteArrayLiteral(ILiteralNodeParent parent, SpecialCharacterToken arrayToken, SpecialCharacterToken leftBracket) { // PARSE: <array literal> ::= '#[' <number literal>* ']' List <SmallIntegerLiteralNode> elements = new List <SmallIntegerLiteralNode>(); ByteArrayLiteralNode result = new ByteArrayLiteralNode(parent, arrayToken, leftBracket); // Process tokens inside the array ... while (true) { // ... get next token in the array ... Token token = this.GetNextTokenxx(Preference.NegativeSign); // Is this closing parenthesis? if (VseCompatibleParser.IsClosingByteArrayBracket(token)) { // Closing parenthesis ... done with the array, return litral array node. result.SetContents(elements, (SpecialCharacterToken)token); this.ResidueToken = null; return(result); } if (token is EofToken) { // Unfinished source code ... return result.SetContents(elements, null); this.ReportParserError(parent, "Missing literal byte array closing bracket.", token); this.ResidueToken = token; return(result); } // PARSE: <numeric liteal> if (token is SmallIntegerToken) { elements.Add(new SmallIntegerLiteralNode(result, (SmallIntegerToken)token, null)); } else if (token is NegativeSignToken) { NegativeSignToken negativeSign = (NegativeSignToken)token; token = this.GetNextTokenxx(Preference.NegativeSign); if (token is SmallIntegerToken) { elements.Add(new SmallIntegerLiteralNode(result, (SmallIntegerToken)token, negativeSign)); } else { this.ReportParserError(parent, "Unrecognized literal.", token); this.ResidueToken = token; result.SetContents(elements, null); return(result); } } else { this.ReportParserError(parent, "Unrecognized literal.", token); this.ResidueToken = token; result.SetContents(elements, null); return(result); } } }