public static bool TryParseNode(Genero4glParser parser, out InputBlock node, IModuleResult containingModule, List <Func <PrepareStatement, bool> > prepStatementBinders, Func <ReturnStatement, ParserResult> returnStatementBinder = null, Action <IAnalysisResult, int, int> limitedScopeVariableAdder = null, List <TokenKind> validExitKeywords = null, IEnumerable <ContextStatementFactory> contextStatementFactories = null, HashSet <TokenKind> endKeywords = null) { node = null; bool result = false; if (parser.PeekToken(TokenKind.InputKeyword)) { result = true; node = new InputBlock(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; node.VariableList = new List <FglNameExpression>(); node.FieldList = new List <FglNameExpression>(); node.Attributes = new List <InputAttribute>(); if (parser.PeekToken(TokenKind.ByKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.NameKeyword)) { parser.NextToken(); // Implicit field mapping node.IsImplicitMapping = true; } else { parser.ReportSyntaxError("Expected \"name\" token in input statement."); } } else if (parser.PeekToken(TokenKind.ArrayKeyword)) { parser.NextToken(); node.IsArray = true; FglNameExpression arrName; if (FglNameExpression.TryParseNode(parser, out arrName)) { node.ArrayName = arrName; } else { parser.ReportSyntaxError("Invalid array name found in input statement."); } } node.DecoratorEnd = parser.Token.Span.End; FglNameExpression nameExpr; if (!node.IsArray) { // read the variable list while (FglNameExpression.TryParseNode(parser, out nameExpr)) { node.VariableList.Add(nameExpr); if (!parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } } if (parser.PeekToken(TokenKind.WithoutKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.DefaultsKeyword)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expected \"defaults\" token in input statement."); } } if (!node.IsImplicitMapping || node.IsArray) { if (parser.PeekToken(TokenKind.FromKeyword)) { parser.NextToken(); // read the field list while (FglNameExpression.TryParseNode(parser, out nameExpr)) { node.FieldList.Add(nameExpr); if (node.IsArray || !parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } } else { parser.ReportSyntaxError("Expected \"from\" token in input statement."); } } if (parser.PeekToken(TokenKind.AttributesKeyword) || parser.PeekToken(TokenKind.AttributeKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); // get the list of display or control attributes InputAttribute attrib; while (InputAttribute.TryParseNode(parser, out attrib, node.IsArray)) { node.Attributes.Add(attrib); if (!parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } if (parser.PeekToken(TokenKind.RightParenthesis)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expecting right-paren in input attributes section."); } } else { parser.ReportSyntaxError("Expecting left-paren in input attributes section."); } } if (parser.PeekToken(TokenKind.HelpKeyword)) { parser.NextToken(); // get the help number ExpressionNode optionNumber; if (FglExpressionNode.TryGetExpressionNode(parser, out optionNumber)) { node.HelpNumber = optionNumber; } else { parser.ReportSyntaxError("Invalid help-number found in input statement."); } } List <TokenKind> validExits = new List <TokenKind>(); if (validExitKeywords != null) { validExits.AddRange(validExits); } validExits.Add(TokenKind.InputKeyword); HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.InputKeyword); bool hasControlBlocks = false; InputControlBlock icb; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (InputControlBlock.TryParseNode(parser, out icb, containingModule, hasControlBlocks, node.IsArray, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExits, contextStatementFactories, newEndKeywords) && icb != null) { if (icb.StartIndex < 0) { continue; } node.Children.Add(icb.StartIndex, icb); hasControlBlocks = true; if (parser.PeekToken(TokenKind.EndOfFile) || (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.InputKeyword, 2))) { break; } } prepStatementBinders.RemoveAt(0); if (hasControlBlocks || (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.InputKeyword, 2))) { if (!(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.InputKeyword, 2))) { parser.ReportSyntaxError("A input block must be terminated with \"end input\"."); } else { parser.NextToken(); // advance to the 'end' token parser.NextToken(); // advance to the 'input' token node.EndIndex = parser.Token.Span.End; } } } return(result); }
public static bool TryParseNode(Genero4glParser parser, out InputControlBlock node, IModuleResult containingModule, bool allowNonControlBlockStmts, bool isArray, List <Func <PrepareStatement, bool> > prepStatementBinders, Func <ReturnStatement, ParserResult> returnStatementBinder = null, Action <IAnalysisResult, int, int> limitedScopeVariableAdder = null, List <TokenKind> validExitKeywords = null, IEnumerable <ContextStatementFactory> contextStatementFactories = null, HashSet <TokenKind> endKeywords = null) { node = new InputControlBlock(); bool result = true; node.FieldSpecList = new List <FglNameExpression>(); node.KeyNameList = new List <VirtualKey>(); switch (parser.PeekToken().Kind) { case TokenKind.Ampersand: { // handle include file PreprocessorNode preNode; PreprocessorNode.TryParseNode(parser, out preNode); node.StartIndex = -1; break; } case TokenKind.BeforeKeyword: case TokenKind.AfterKeyword: { parser.NextToken(); node.StartIndex = parser.Token.Span.Start; if (parser.PeekToken(TokenKind.FieldKeyword)) { parser.NextToken(); node.Type = InputControlBlockType.Field; // get the list of field specs FglNameExpression fieldSpec; while (FglNameExpression.TryParseNode(parser, out fieldSpec)) { node.FieldSpecList.Add(fieldSpec); if (!parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } node.DecoratorEnd = parser.Token.Span.End; } else if (parser.PeekToken(TokenKind.InputKeyword)) { parser.NextToken(); node.Type = InputControlBlockType.Input; node.DecoratorEnd = parser.Token.Span.End; } else if (isArray && parser.PeekToken(TokenKind.DeleteKeyword)) { parser.NextToken(); node.Type = InputControlBlockType.Delete; node.DecoratorEnd = parser.Token.Span.End; } else if (isArray && parser.PeekToken(TokenKind.RowKeyword)) { parser.NextToken(); node.Type = InputControlBlockType.Row; node.DecoratorEnd = parser.Token.Span.End; } else if (isArray && parser.PeekToken(TokenKind.InsertKeyword)) { parser.NextToken(); node.Type = InputControlBlockType.Insert; node.DecoratorEnd = parser.Token.Span.End; } else { parser.ReportSyntaxError("Unexpected token found in input control block."); result = false; } break; } case TokenKind.OnKeyword: { parser.NextToken(); node.StartIndex = parser.Token.Span.Start; switch (parser.PeekToken().Kind) { case TokenKind.ChangeKeyword: parser.NextToken(); node.Type = InputControlBlockType.Change; // get the list of field specs FglNameExpression fieldSpec; while (FglNameExpression.TryParseNode(parser, out fieldSpec)) { node.FieldSpecList.Add(fieldSpec); if (!parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } node.DecoratorEnd = parser.Token.Span.End; break; case TokenKind.IdleKeyword: parser.NextToken(); node.Type = InputControlBlockType.Idle; // get the idle seconds ExpressionNode idleExpr; if (FglExpressionNode.TryGetExpressionNode(parser, out idleExpr)) { node.IdleSeconds = idleExpr; } else { parser.ReportSyntaxError("Invalid idle-seconds found in input statement."); } node.DecoratorEnd = parser.Token.Span.End; break; case TokenKind.ActionKeyword: parser.NextToken(); node.Type = InputControlBlockType.Action; // get the action name FglNameExpression actionName; if (FglNameExpression.TryParseNode(parser, out actionName)) { node.ActionName = actionName; } else { parser.ReportSyntaxError("Invalid action-name found in input statement."); } node.DecoratorEnd = parser.Token.Span.End; if (parser.PeekToken(TokenKind.InfieldKeyword)) { parser.NextToken(); // get the field-spec if (FglNameExpression.TryParseNode(parser, out actionName)) { node.ActionField = actionName; } else { parser.ReportSyntaxError("Invalid field-spec found in input statement."); } } break; case TokenKind.KeyKeyword: parser.NextToken(); node.Type = InputControlBlockType.Key; if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); // get the list of key names VirtualKey keyName; while (VirtualKey.TryGetKey(parser, out keyName)) { node.KeyNameList.Add(keyName); if (!parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } if (parser.PeekToken(TokenKind.RightParenthesis)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expected right-paren in input control block."); } node.DecoratorEnd = parser.Token.Span.End; } else { parser.ReportSyntaxError("Expected left-paren in input control block."); } break; case TokenKind.RowKeyword: if (isArray) { parser.NextToken(); node.Type = InputControlBlockType.Row; if (parser.PeekToken(TokenKind.ChangeKeyword)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expected \"change\" keyword in input statement."); } node.DecoratorEnd = parser.Token.Span.End; } else { parser.ReportSyntaxError("\"on row\" syntax is only allowed in input array statement."); } break; default: parser.ReportSyntaxError("Unexpected token found in input control block."); //result = false; break; } break; } default: if (!allowNonControlBlockStmts) { result = false; } else { node.StartIndex = parser.Token.Span.Start; } break; } if (result && node.StartIndex >= 0) { // get the dialog statements FglStatement inputStmt; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (InputDialogStatementFactory.TryGetStatement(parser, out inputStmt, isArray, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords)) { if (inputStmt != null) { node.Children.Add(inputStmt.StartIndex, inputStmt); node.EndIndex = inputStmt.EndIndex; } } prepStatementBinders.RemoveAt(0); if (node.EndIndex <= 0) { node.EndIndex = node.DecoratorEnd; } if (node.Type == InputControlBlockType.None && node.Children.Count == 0) { result = false; } } return(result); }