public static bool TryParseNode(Genero4glParser parser, out MenuOption 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 = new MenuOption(); bool result = true; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); switch (parser.PeekToken().Kind) { case TokenKind.Ampersand: { PreprocessorNode preNode; PreprocessorNode.TryParseNode(parser, out preNode); node.StartIndex = -1; break; } case TokenKind.CommandKeyword: { parser.NextToken(); node.StartIndex = parser.Token.Span.Start; bool getOptionName = false; if (parser.PeekToken(TokenKind.KeyKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); VirtualKey keyName; if (VirtualKey.TryGetKey(parser, out keyName)) { node.KeyName = keyName; } else { parser.ReportSyntaxError("Invalid key-name found in menu command option."); } if (parser.PeekToken(TokenKind.RightParenthesis)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expecting right-paren in menu command option."); } } else { parser.ReportSyntaxError("Expecting left-paren in menu command option."); } node.DecoratorEnd = parser.Token.Span.End; } else { getOptionName = true; } // at this point we need to try to get a menu-statement. If it doesn't work, we have some other stuff to gather FglStatement menuStmt = null; if (getOptionName || !MenuStatementFactory.TryGetStatement(parser, out menuStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords)) { ExpressionNode optionName; if (FglExpressionNode.TryGetExpressionNode(parser, out optionName)) { node.OptionName = optionName; } else { parser.ReportSyntaxError("Invalid option-name found in menu command option."); } node.DecoratorEnd = parser.Token.Span.End; if (parser.PeekToken(TokenCategory.StringLiteral) || parser.PeekToken(TokenCategory.Identifier)) { ExpressionNode optionComment; if (FglExpressionNode.TryGetExpressionNode(parser, out optionComment)) { node.OptionComment = optionComment; } } if (parser.PeekToken(TokenKind.HelpKeyword)) { parser.NextToken(); ExpressionNode optionNumber; if (FglExpressionNode.TryGetExpressionNode(parser, out optionNumber)) { node.HelpNumber = optionNumber; } else { parser.ReportSyntaxError("Invalid help-number found in menu command option."); } } } else if (menuStmt != null) { node.Children.Add(menuStmt.StartIndex, menuStmt); } while (MenuStatementFactory.TryGetStatement(parser, out menuStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords)) { if (menuStmt != null && !node.Children.ContainsKey(menuStmt.StartIndex)) { node.Children.Add(menuStmt.StartIndex, menuStmt); } } break; } case TokenKind.OnKeyword: { parser.NextToken(); node.StartIndex = parser.Token.Span.Start; if (parser.PeekToken(TokenKind.ActionKeyword)) { parser.NextToken(); FglNameExpression action; if (FglNameExpression.TryParseNode(parser, out action)) { node.ActionName = action; } else { parser.ReportSyntaxError("Invalid action-name found in menu option."); } node.DecoratorEnd = parser.Token.Span.End; FglStatement menuStmt = null; while (MenuStatementFactory.TryGetStatement(parser, out menuStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords) && menuStmt != null) { node.Children.Add(menuStmt.StartIndex, menuStmt); } } else if (parser.PeekToken(TokenKind.IdleKeyword)) { parser.NextToken(); ExpressionNode idleExpr; if (FglExpressionNode.TryGetExpressionNode(parser, out idleExpr)) { node.IdleSeconds = idleExpr; } else { parser.ReportSyntaxError("Invalid idle-seconds found in menu block."); } node.DecoratorEnd = parser.Token.Span.End; FglStatement menuStmt = null; while (MenuStatementFactory.TryGetStatement(parser, out menuStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords) && menuStmt != null) { node.Children.Add(menuStmt.StartIndex, menuStmt); } } else { parser.ReportSyntaxError("Expecting \"action\" or \"idle\" keyword in menu option."); } break; } default: result = false; break; } prepStatementBinders.RemoveAt(0); node.EndIndex = parser.Token.Span.End; return(result); }
public static bool TryParseNode(Genero4glParser parser, out MenuBlock 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.MenuKeyword)) { result = true; node = new MenuBlock(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; node.Attributes = new List <ExpressionNode>(); if (parser.PeekToken(TokenCategory.StringLiteral)) { parser.NextToken(); node.MenuTitle = parser.Token.Token.Value.ToString(); } node.DecoratorEnd = parser.Token.Span.End; if (parser.PeekToken(TokenKind.AttributesKeyword) || parser.PeekToken(TokenKind.AttributeKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); ExpressionNode expr; while (FglExpressionNode.TryGetExpressionNode(parser, out expr, new List <TokenKind> { TokenKind.Comma, TokenKind.RightParenthesis })) { node.Attributes.Add(expr); if (!parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } if (parser.PeekToken(TokenKind.RightParenthesis)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expecting right-paren for menu attributes."); } } else { parser.ReportSyntaxError("Expecting left-paren for menu attributes."); } } List <TokenKind> validExits = new List <TokenKind>(); if (validExitKeywords != null) { validExits.AddRange(validExitKeywords); } validExits.Add(TokenKind.MenuKeyword); HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.MenuKeyword); int beforeStart = -1, beforeDecEnd = -1, beforeEnd = -1; if (parser.PeekToken(TokenKind.BeforeKeyword)) { parser.NextToken(); beforeStart = parser.Token.Span.Start; if (parser.PeekToken(TokenKind.MenuKeyword)) { parser.NextToken(); beforeDecEnd = parser.Token.Span.End; FglStatement menuStmt; List <FglStatement> stmts = new List <FglStatement>(); prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (MenuStatementFactory.TryGetStatement(parser, out menuStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExits, contextStatementFactories, newEndKeywords)) { stmts.Add(menuStmt); beforeEnd = menuStmt.EndIndex; } prepStatementBinders.RemoveAt(0); if (beforeEnd < 0) { beforeEnd = beforeDecEnd; } MenuOption beforeMenu = new MenuOption(beforeStart, beforeDecEnd, beforeEnd, stmts); if (beforeMenu != null) { node.Children.Add(beforeMenu.StartIndex, beforeMenu); } } else { parser.ReportSyntaxError("Expecting \"before\" keyword for menu block."); } } prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.MenuKeyword, 2))) { MenuOption menuOpt; if (MenuOption.TryParseNode(parser, out menuOpt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExits, contextStatementFactories, newEndKeywords) && menuOpt != null) { if (menuOpt.StartIndex < 0) { continue; } node.Children.Add(menuOpt.StartIndex, menuOpt); } else if (parser.PeekToken(TokenKind.EndKeyword) && endKeywords != null && endKeywords.Contains(parser.PeekToken(2).Kind)) { break; } else { parser.NextToken(); } } prepStatementBinders.RemoveAt(0); if (!(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.MenuKeyword, 2))) { parser.ReportSyntaxError("A menu block must be terminated with \"end menu\"."); } else { parser.NextToken(); // advance to the 'end' token parser.NextToken(); // advance to the 'menu' token node.EndIndex = parser.Token.Span.End; } } return(result); }