public static bool TryParseNode(Genero4glParser parser, out DialogControlBlock 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 DialogControlBlock(); node.StartIndex = parser.Token.Span.Start; node.KeyNames = new List <VirtualKey>(); bool result = true; 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(); if (parser.PeekToken(TokenKind.DialogKeyword)) { parser.NextToken(); node.Type = DialogControlBlockType.Dialog; } else { parser.ReportSyntaxError("Expected \"dialog\" keyword in dialog statement."); } break; case TokenKind.CommandKeyword: { parser.NextToken(); node.Type = DialogControlBlockType.Command; if (parser.PeekToken(TokenKind.KeyKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); VirtualKey vKey; while (VirtualKey.TryGetKey(parser, out vKey)) { node.KeyNames.Add(vKey); if (parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } } else { parser.ReportSyntaxError("Expecting left-paren in dialog statement."); } } ExpressionNode FglNameExpression; if (FglExpressionNode.TryGetExpressionNode(parser, out FglNameExpression)) { node.OptionName = FglNameExpression; } else { parser.ReportSyntaxError("Invalid expression found in dialog statement."); } if (!parser.PeekToken(TokenKind.HelpKeyword) && parser.PeekToken(TokenCategory.StringLiteral)) { ExpressionNode commentExpr; if (FglExpressionNode.TryGetExpressionNode(parser, out commentExpr, new List <TokenKind> { TokenKind.HelpKeyword })) { node.OptionComment = commentExpr; } else { parser.ReportSyntaxError("Invalid expression found in dialog statement."); } } if (parser.PeekToken(TokenKind.HelpKeyword)) { parser.NextToken(); ExpressionNode optionNumber; if (FglExpressionNode.TryGetExpressionNode(parser, out optionNumber)) { node.HelpNumber = optionNumber; } else { parser.ReportSyntaxError("Invalid expression found in dialog statement."); } } break; } case TokenKind.OnKeyword: { parser.NextToken(); switch (parser.PeekToken().Kind) { case TokenKind.ActionKeyword: parser.NextToken(); node.Type = DialogControlBlockType.Action; FglNameExpression nameExpr; if (FglNameExpression.TryParseNode(parser, out nameExpr)) { node.ActionName = nameExpr; } else { parser.ReportSyntaxError("Invalid name found in dialog statement."); } break; case TokenKind.KeyKeyword: parser.NextToken(); node.Type = DialogControlBlockType.Key; if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); VirtualKey vKey; while (VirtualKey.TryGetKey(parser, out vKey)) { node.KeyNames.Add(vKey); if (parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } } else { parser.ReportSyntaxError("Expecting left-paren in dialog statement."); } break; case TokenKind.IdleKeyword: parser.NextToken(); node.Type = DialogControlBlockType.Idle; // get the idle seconds ExpressionNode idleExpr; if (FglExpressionNode.TryGetExpressionNode(parser, out idleExpr)) { node.IdleSeconds = idleExpr; } else { parser.ReportSyntaxError("Invalid idle-seconds found in dialog statement."); } break; default: parser.ReportSyntaxError("Unexpected token found in dialog control block."); break; } break; } default: break; } if (result && node.StartIndex >= 0) { // get the dialog statements FglStatement inputStmt; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (DialogStatementFactory.TryGetStatement(parser, out inputStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords) && inputStmt != null) { node.Children.Add(inputStmt.StartIndex, inputStmt); } prepStatementBinders.RemoveAt(0); if (node.Type == DialogControlBlockType.None && node.Children.Count == 0) { result = false; } } return(result); }
internal static void BuildDialogBlock(Genero4glParser parser, DialogBlock 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) { if (parser.PeekToken(TokenKind.AttributeKeyword) || parser.PeekToken(TokenKind.AttributesKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); // get the list of display or control attributes DialogAttribute attrib; while (DialogAttribute.TryParseNode(parser, out attrib)) { 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 dialog attributes section."); } } else { parser.ReportSyntaxError("Expecting left-paren in dialog attributes section."); } } // parse input, construct, display or SUBDIALOG bool moreBlocks = true; List <ContextStatementFactory> csfs = new List <ContextStatementFactory>(); if (contextStatementFactories != null) { csfs.AddRange(contextStatementFactories); } csfs.Add((x) => { DialogStatement testNode; DialogStatementFactory.TryGetDialogStatement(x, out testNode, true); return(testNode); }); prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (moreBlocks) { switch (parser.PeekToken().Kind) { case TokenKind.InputKeyword: { InputBlock inputBlock; if (InputBlock.TryParseNode(parser, out inputBlock, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, csfs, endKeywords) && inputBlock != null) { node.Children.Add(inputBlock.StartIndex, inputBlock); } else { parser.ReportSyntaxError("Invalid input block found in dialog statement."); } break; } case TokenKind.ConstructKeyword: { ConstructBlock constructBlock; if (ConstructBlock.TryParseNode(parser, out constructBlock, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, csfs, endKeywords) && constructBlock != null) { node.Children.Add(constructBlock.StartIndex, constructBlock); } else { parser.ReportSyntaxError("Invalid construct block found in dialog statement."); } break; } case TokenKind.DisplayKeyword: { DisplayBlock dispBlock; if (DisplayBlock.TryParseNode(parser, out dispBlock, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, csfs, endKeywords) && dispBlock != null) { node.Children.Add(dispBlock.StartIndex, dispBlock); } else { parser.ReportSyntaxError("Invalid display block found in dialog statement."); } break; } case TokenKind.SubdialogKeyword: { parser.NextToken(); FglNameExpression nameExpr; if (FglNameExpression.TryParseNode(parser, out nameExpr)) { node.Subdialogs.Add(nameExpr); } else { parser.ReportSyntaxError("Invalid subdialog name found in dialog statement."); } break; } default: moreBlocks = false; break; } } prepStatementBinders.RemoveAt(0); List <TokenKind> validExits = new List <TokenKind>(); if (validExitKeywords != null) { validExits.AddRange(validExits); } validExits.Add(TokenKind.DialogKeyword); HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.DialogKeyword); // get the dialog control blocks prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.DialogKeyword, 2))) { DialogControlBlock icb; if (DialogControlBlock.TryParseNode(parser, out icb, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExits, contextStatementFactories, newEndKeywords) && icb != null) { if (icb.StartIndex < 0) { continue; } node.Children.Add(icb.StartIndex, icb); } else if (parser.PeekToken(TokenKind.EndKeyword) && endKeywords != null && endKeywords.Contains(parser.PeekToken(2).Kind)) { break; } else { parser.NextToken(); } } prepStatementBinders.RemoveAt(0); }