protected virtual ParenthesizedExpressionNode ParseParenthesizedExpression(IPrimaryParentNode parent, SpecialCharacterToken leftParenthesis) { // PARSE: '(' <expression> ')' ParenthesizedExpressionNode result = new ParenthesizedExpressionNode(parent, leftParenthesis); Token token = this.GetNextTokenxx(Preference.NegativeSign); ExpressionNode expression = this.ParseExpression(result, token); if (expression == null) { this.ReportParserError(result, SemanticErrors.MissingExpression, token); return(result); } // Ensure the parentheses are properly closed. token = this.GetNextTokenxx(Preference.Default); SpecialCharacterToken rightParenthesis = null; if (Parser.IsClosingParenthesis(token)) { rightParenthesis = (SpecialCharacterToken)token; } else { this.ReportParserError(result, SemanticErrors.MissingExpressionClosingParenthesis, token); this.ResidueToken = token; } result.SetContents(expression, rightParenthesis); return(result); }
/// <summary> /// Create a new variable reference node. /// </summary> /// <param name="parent">The parent node that defines this node.</param> /// <param name="token">Identifier token containing the name of the variable.</param> protected internal VariableReferenceleNode(IPrimaryParentNode parent, IdentifierToken token) { #if DEBUG if (parent == null) { throw new ArgumentNullException("parent"); } if (token == null) { throw new ArgumentNullException("token"); } #endif this.Parent = parent; this.Token = token; }
/// <summary> /// Create and initialize a block node. /// </summary> /// <param name="parent">The parent node to the block node.</param> /// <param name="token">Token for the left / opening square bracket of the block.</param> protected internal BlockNode(IPrimaryParentNode parent, SpecialCharacterToken token) { #if DEBUG if (parent == null) { throw new ArgumentNullException("parent"); } if (token == null) { throw new ArgumentNullException("token"); } #endif this.Arguments = new List <BlockArgumentNode>(); this.Parent = parent; this.LeftBracket = token; }
/// <summary> /// Create a new parenthesized expression node. /// </summary> /// <param name="parent">Parent node that defines this expression.</param> /// <param name="token">Left opening parenthesis of the parenthesized expression.</param> protected internal ParenthesizedExpressionNode(IPrimaryParentNode parent, SpecialCharacterToken token) { #if DEBUG if (parent == null) { throw new ArgumentNullException("parent"); } if (!Parser.IsOpeningParenthesis(token)) { // We do expect the caller to this method to have ensured that we are actually parsing a parenthesis. throw new InvalidParserOperationException("Expected opening parenthesis token ... '('"); } #endif this.Parent = parent; this.LeftParenthesis = token; }
protected virtual IPrimaryNode ParsePrimary(IPrimaryParentNode parent, Token token) { // PARSE: <primary> ::= identifier | <literal> | <block constructor> | ( '(' <expression> ')' ) if (token is IdentifierToken) { return(new VariableReferenceleNode(parent, (IdentifierToken)token)); } else if (Parser.IsBlockStartDelimiter(token)) { return(this.ParseBlock(parent, (SpecialCharacterToken)token)); } else if (Parser.IsOpeningParenthesis(token)) { return(this.ParseParenthesizedExpression(parent, (SpecialCharacterToken)token)); } else { return(this.ParseLiteral(parent, token)); } }
/// <summary> /// Create a new variable reference node. /// </summary> /// <param name="parent">The parent node that defines this node.</param> /// <param name="token">Identifier token containing the name of the variable.</param> protected internal VariableReferenceleNode(IPrimaryParentNode parent, IdentifierToken token) { #if DEBUG if (parent == null) throw new ArgumentNullException("parent"); if (token == null) throw new ArgumentNullException("token"); #endif this.Parent = parent; this.Token = token; }
/// <summary> /// Create a new parenthesized expression node. /// </summary> /// <param name="parent">Parent node that defines this expression.</param> /// <param name="token">Left opening parenthesis of the parenthesized expression.</param> protected internal ParenthesizedExpressionNode(IPrimaryParentNode parent, SpecialCharacterToken token) { #if DEBUG if (parent == null) throw new ArgumentNullException("parent"); if (!Parser.IsOpeningParenthesis(token)) // We do expect the caller to this method to have ensured that we are actually parsing a parethesis. throw new InvalidParserOperationException("Expected opening parenthesis token ... '('"); #endif this.Parent = parent; this.LeftParenthesis = (SpecialCharacterToken)token; }
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 and intialize a block node. /// </summary> /// <param name="parent">The parent node to the block node.</param> /// <param name="token">Token for the left / opening square bracket of the block.</param> protected internal BlockNode(IPrimaryParentNode parent, SpecialCharacterToken token) { #if DEBUG if (parent == null) throw new ArgumentNullException("parent"); if (token == null) throw new ArgumentNullException("token"); #endif this.Arguments = new List<BlockArgumentNode>(); this.Parent = parent; this.LeftBracket = token; }
protected virtual IPrimaryNode ParsePrimary(IPrimaryParentNode parent, Token token) { // PARSE: <primary> ::= identifier | <literal> | <block constructor> | ( '(' <expression> ')' ) if (token is IdentifierToken) return new VariableReferenceleNode(parent, (IdentifierToken)token); else if (Parser.IsBlockStartDelimiter(token)) return this.ParseBlock(parent, (SpecialCharacterToken)token); else if (Parser.IsOpeningParenthesis(token)) return this.ParseParenthesizedExpression(parent, (SpecialCharacterToken)token); else return this.ParseLiteral(parent, token); }
protected virtual ParenthesizedExpressionNode ParseParenthesizedExpression(IPrimaryParentNode parent, SpecialCharacterToken leftParenthesis) { // PARSE: '(' <expression> ')' ParenthesizedExpressionNode result = new ParenthesizedExpressionNode(parent, leftParenthesis); Token token = this.GetNextTokenxx(Preference.NegativeSign); ExpressionNode expression = this.ParseExpression(result, token); if (expression == null) { this.ReportParserError(result, SemanticErrors.MissingExpression, token); return result; } // Ensure the parenthese are properly closed. token = this.GetNextTokenxx(Preference.Default); SpecialCharacterToken rightParenthesis = null; if (Parser.IsClosingParenthesis(token)) { rightParenthesis = (SpecialCharacterToken)token; } else { this.ReportParserError(result, SemanticErrors.MissingExpressionClosingParenthesis, token); this.ResidueToken = token; } result.SetContents(expression, rightParenthesis); 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; }