public static bool TryParseNode(Genero4glParser parser, out 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) { node = null; bool result = false; if (parser.PeekToken(TokenKind.DialogKeyword)) { result = true; node = new DialogBlock(true); node.Attributes = new List <DialogAttribute>(); node.Subdialogs = new List <FglNameExpression>(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; node.DecoratorEnd = parser.Token.Span.End; BuildDialogBlock(parser, node, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords); if (!(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.DialogKeyword, 2))) { parser.ReportSyntaxError("A dialog block must be terminated with \"end dialog\"."); } else { parser.NextToken(); // advance to the 'end' token parser.NextToken(); // advance to the 'dialog' token node.EndIndex = parser.Token.Span.End; } } 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); }
public static bool TryParseNode(Genero4glParser parser, out DeclarativeDialogBlock node, IModuleResult containingModule) { node = null; bool result = false; AccessModifier?accMod = null; string accModToken = null; if (parser.PeekToken(TokenKind.PublicKeyword)) { accMod = AccessModifier.Public; accModToken = parser.PeekToken().Value.ToString(); } else if (parser.PeekToken(TokenKind.PrivateKeyword)) { accMod = AccessModifier.Private; accModToken = parser.PeekToken().Value.ToString(); } uint lookAheadBy = (uint)(accMod.HasValue ? 2 : 1); if (parser.PeekToken(TokenKind.DialogKeyword, lookAheadBy)) { result = true; node = new DeclarativeDialogBlock(); if (accMod.HasValue) { parser.NextToken(); node.AccessModifier = accMod.Value; } else { node.AccessModifier = AccessModifier.Public; } parser.NextToken(); // move past the Function keyword node.StartIndex = parser.Token.Span.Start; // get the name if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { parser.NextToken(); node.Name = parser.Token.Token.Value.ToString(); node.LocationIndex = parser.Token.Span.Start; node.DecoratorEnd = parser.Token.Span.End; } else { parser.ReportSyntaxError("A declarative dialog must have a name."); } if (!parser.PeekToken(TokenKind.LeftParenthesis)) { parser.ReportSyntaxError("A declarative dialog must specify zero or more parameters in the form: ([param1][,...])"); } else { parser.NextToken(); } // get the parameters while (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { parser.NextToken(); string errMsg; if (!node.AddArgument(parser.Token, out errMsg)) { parser.ReportSyntaxError(errMsg); } if (parser.PeekToken(TokenKind.Comma)) { parser.NextToken(); } // TODO: probably need to handle "end" "function" case...won't right now } if (!parser.PeekToken(TokenKind.RightParenthesis)) { parser.ReportSyntaxError("A declarative dialog must specify zero or more parameters in the form: ([param1][,...])"); } else { parser.NextToken(); } List <List <TokenKind> > breakSequences = new List <List <TokenKind> > { new List <TokenKind> { TokenKind.InputKeyword }, new List <TokenKind> { TokenKind.ConstructKeyword }, new List <TokenKind> { TokenKind.DisplayKeyword }, new List <TokenKind> { TokenKind.EndKeyword, TokenKind.DialogKeyword } }; // only defines are allowed in declarative dialogs DefineNode defineNode; bool matchedBreakSequence = false; while (DefineNode.TryParseDefine(parser, out defineNode, out matchedBreakSequence, breakSequences) && defineNode != null) { node.Children.Add(defineNode.StartIndex, defineNode); foreach (var def in defineNode.GetDefinitions()) { foreach (var vardef in def.VariableDefinitions) { vardef.Scope = "local variable"; if (!node.Variables.ContainsKey(vardef.Name)) { node.Variables.Add(vardef.Name, vardef); } else { parser.ReportSyntaxError(vardef.LocationIndex, vardef.LocationIndex + vardef.Name.Length, string.Format("Variable {0} defined more than once.", vardef.Name), Severity.Error); } } } if (parser.PeekToken(TokenKind.EndOfFile) || (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ReportKeyword, 2))) { break; } // if a break sequence was matched, we don't want to advance the token if (!matchedBreakSequence) { // TODO: not sure whether to break or keep going...for right now, let's keep going until we hit the end keyword parser.NextToken(); } } // we don't want the dialog piece itself to be outlinable, since it's a declarative block node.Dialog = new DialogBlock(false); node.Dialog.Attributes = new List <DialogAttribute>(); node.Dialog.Subdialogs = new List <FglNameExpression>(); List <Func <PrepareStatement, bool> > prepStatementBinders = new List <Func <PrepareStatement, bool> >(); prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); DialogBlock.BuildDialogBlock(parser, node.Dialog, containingModule, prepStatementBinders); prepStatementBinders.RemoveAt(0); foreach (var child in node.Dialog.Children) { node.Children.Add(child.Key, child.Value); } if (!parser.PeekToken(TokenKind.EndOfFile)) { parser.NextToken(); if (parser.PeekToken(TokenKind.DialogKeyword)) { parser.NextToken(); node.EndIndex = parser.Token.Span.End; node.IsComplete = true; } else { parser.ReportSyntaxError(parser.Token.Span.Start, parser.Token.Span.End, "Invalid end of declarative dialog definition."); } } else { parser.ReportSyntaxError("Unexpected end of declarative dialog definition"); } } return(result); }
public bool TryParseNode(Genero4glParser parser, out FglStatement node, IModuleResult containingModule, List <Func <PrepareStatement, bool> > prepStatementBinders, Func <ReturnStatement, ParserResult> returnStatementBinder = null, Action <IAnalysisResult, int, int> limitedScopeVariableAdder = null, bool returnStatementsOnly = false, List <TokenKind> validExitKeywords = null, IEnumerable <ContextStatementFactory> contextStatementFactories = null, ExpressionParsingOptions expressionOptions = null, HashSet <TokenKind> endKeywords = null) { node = null; bool result = false; if (returnStatementsOnly) { if (parser.PeekToken(TokenKind.ReturnKeyword)) { ReturnStatement retStmt; if ((result = ReturnStatement.TryParseNode(parser, out retStmt))) { node = retStmt; } } return(result); } if (contextStatementFactories != null) { foreach (var context in contextStatementFactories) { node = context(parser); if (node != null) { break; } } if (node != null) { return(true); } } switch (parser.PeekToken().Kind) { case TokenKind.LetKeyword: { LetStatement letStmt; if ((result = LetStatement.TryParseNode(parser, out letStmt, expressionOptions))) { node = letStmt; } break; } case TokenKind.DeclareKeyword: { DeclareStatement declStmt; if ((result = DeclareStatement.TryParseNode(parser, out declStmt, containingModule))) { node = declStmt; } break; } case TokenKind.DeferKeyword: { DeferStatementNode deferStmt; if ((result = DeferStatementNode.TryParseNode(parser, out deferStmt))) { node = deferStmt; } break; } case TokenKind.PrepareKeyword: { PrepareStatement prepStmt; if ((result = PrepareStatement.TryParseNode(parser, out prepStmt, containingModule))) { node = prepStmt; foreach (var binder in prepStatementBinders) { if (binder(prepStmt)) { break; } } } break; } case TokenKind.SqlKeyword: { SqlBlockNode sqlStmt; if ((result = SqlBlockNode.TryParseSqlNode(parser, out sqlStmt))) { node = sqlStmt; } break; } case TokenKind.ReturnKeyword: { ReturnStatement retStmt; if ((result = ReturnStatement.TryParseNode(parser, out retStmt))) { if (returnStatementBinder != null) { var parseResult = returnStatementBinder(retStmt); if (!parseResult.Success && !string.IsNullOrWhiteSpace(parseResult.ErrorMessage)) { parser.ReportSyntaxError(parseResult.ErrorMessage); } } node = retStmt; } break; } case TokenKind.CallKeyword: { CallStatement callStmt; if ((result = CallStatement.TryParseNode(parser, out callStmt))) { node = callStmt; } break; } case TokenKind.IfKeyword: { IfStatement ifStmt; if ((result = IfStatement.TryParseNode(parser, out ifStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, expressionOptions, endKeywords))) { node = ifStmt; } break; } case TokenKind.WhileKeyword: { WhileStatement whileStmt; if ((result = WhileStatement.TryParseNode(parser, out whileStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, expressionOptions, endKeywords))) { node = whileStmt; } break; } case TokenKind.ExitKeyword: { ExitStatement exitStatement; if ((result = ExitStatement.TryParseNode(parser, out exitStatement))) { node = exitStatement; } break; } case TokenKind.ContinueKeyword: { ContinueStatement contStmt; if ((result = ContinueStatement.TryParseNode(parser, out contStmt))) { node = contStmt; } break; } case TokenKind.WheneverKeyword: { WheneverStatement wheneverStmt; if ((result = WheneverStatement.TryParseNode(parser, out wheneverStmt))) { node = wheneverStmt; } break; } case TokenKind.ForKeyword: { ForStatement forStmt; if ((result = ForStatement.TryParserNode(parser, out forStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, expressionOptions, endKeywords))) { node = forStmt; } break; } case TokenKind.CaseKeyword: { CaseStatement caseStmt; if ((result = CaseStatement.TryParseNode(parser, out caseStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, expressionOptions, endKeywords))) { node = caseStmt; } break; } case TokenKind.InitializeKeyword: { InitializeStatement initStmt; if ((result = InitializeStatement.TryParseNode(parser, out initStmt))) { node = initStmt; } break; } case TokenKind.LocateKeyword: { LocateStatement locateStmt; if ((result = LocateStatement.TryParseNode(parser, out locateStmt))) { node = locateStmt; } break; } case TokenKind.FreeKeyword: { FreeStatement freeStmt; if ((result = FreeStatement.TryParseNode(parser, out freeStmt))) { node = freeStmt; } break; } case TokenKind.GotoKeyword: { GotoStatement gotoStmt; if ((result = GotoStatement.TryParseNode(parser, out gotoStmt))) { node = gotoStmt; } break; } case TokenKind.LabelKeyword: { LabelStatement labelStmt; if ((result = LabelStatement.TryParseNode(parser, out labelStmt))) { node = labelStmt; } break; } case TokenKind.SleepKeyword: { SleepStatement sleepStmt; if ((result = SleepStatement.TryParseNode(parser, out sleepStmt))) { node = sleepStmt; } break; } case TokenKind.TryKeyword: { TryCatchStatement tryStmt; if ((result = TryCatchStatement.TryParseNode(parser, out tryStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = tryStmt; } break; } case TokenKind.ValidateKeyword: { ValidateStatement validateStmt; if ((result = ValidateStatement.TryParseNode(parser, out validateStmt))) { node = validateStmt; } break; } case TokenKind.OptionsKeyword: { OptionsStatement optionsStmt; if ((result = OptionsStatement.TryParseNode(parser, out optionsStmt))) { node = optionsStmt; } break; } case TokenKind.ExecuteKeyword: { ExecuteStatement exeStmt; if ((result = ExecuteStatement.TryParseNode(parser, out exeStmt))) { node = exeStmt; } break; } case TokenKind.OpenKeyword: { OpenStatement openStmt; if ((result = OpenStatement.TryParseNode(parser, out openStmt))) { node = openStmt; } break; } case TokenKind.FetchKeyword: { FetchStatement fetchStmt; if ((result = FetchStatement.TryParseNode(parser, out fetchStmt))) { node = fetchStmt; } break; } case TokenKind.CloseKeyword: { CloseStatement closeStmt; if ((result = CloseStatement.TryParseNode(parser, out closeStmt))) { node = closeStmt; } break; } case TokenKind.ClearKeyword: { ClearStatement clearStmt; if ((result = ClearStatement.TryParseNode(parser, out clearStmt))) { node = clearStmt; } break; } case TokenKind.ForeachKeyword: { ForeachStatement foreachStmt; if ((result = ForeachStatement.TryParseNode(parser, out foreachStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = foreachStmt; } break; } case TokenKind.MessageKeyword: { MessageStatement msgStmt; if ((result = MessageStatement.TryParseNode(parser, out msgStmt))) { node = msgStmt; } break; } case TokenKind.MenuKeyword: { MenuBlock menuStmt; if ((result = MenuBlock.TryParseNode(parser, out menuStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = menuStmt; if (limitedScopeVariableAdder != null) { limitedScopeVariableAdder(Genero4glAst.DialogVariable, node.StartIndex, node.EndIndex); } } break; } case TokenKind.InputKeyword: { InputBlock inputStmt; if ((result = InputBlock.TryParseNode(parser, out inputStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = inputStmt; if (limitedScopeVariableAdder != null) { limitedScopeVariableAdder(Genero4glAst.DialogVariable, node.StartIndex, node.EndIndex); } } break; } case TokenKind.ConstructKeyword: { ConstructBlock constructStmt; if ((result = ConstructBlock.TryParseNode(parser, out constructStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = constructStmt; if (limitedScopeVariableAdder != null) { limitedScopeVariableAdder(Genero4glAst.DialogVariable, node.StartIndex, node.EndIndex); } } break; } case TokenKind.FlushKeyword: { FlushStatement flushStmt; if ((result = FlushStatement.TryParseNode(parser, out flushStmt))) { node = flushStmt; } break; } case TokenKind.DisplayKeyword: { DisplayBlock dispStmt; if ((result = DisplayBlock.TryParseNode(parser, out dispStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = dispStmt; if (limitedScopeVariableAdder != null) { limitedScopeVariableAdder(Genero4glAst.DialogVariable, node.StartIndex, node.EndIndex); } } break; } case TokenKind.PromptKeyword: { PromptStatement promptStmt; if ((result = PromptStatement.TryParseNode(parser, out promptStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = promptStmt; if (limitedScopeVariableAdder != null) { limitedScopeVariableAdder(Genero4glAst.DialogVariable, node.StartIndex, node.EndIndex); } } break; } case TokenKind.DialogKeyword: { DialogBlock dialogBlock; if ((result = DialogBlock.TryParseNode(parser, out dialogBlock, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords))) { node = dialogBlock; if (limitedScopeVariableAdder != null) { limitedScopeVariableAdder(Genero4glAst.DialogVariable, node.StartIndex, node.EndIndex); } } break; } case TokenKind.AcceptKeyword: { AcceptStatement acceptStmt; if ((result = AcceptStatement.TryParseNode(parser, out acceptStmt))) { node = acceptStmt; } break; } case TokenKind.LoadKeyword: { LoadStatement loadStmt; if ((result = LoadStatement.TryParseNode(parser, out loadStmt))) { node = loadStmt; } break; } case TokenKind.CreateKeyword: { CreateStatement createStmt; if ((result = CreateStatement.TryParseNode(parser, out createStmt, containingModule))) { node = createStmt; } break; } case TokenKind.BreakpointKeyword: { BreakpointStatement brkStmt; if ((result = BreakpointStatement.TryParseNode(parser, out brkStmt))) { node = brkStmt; } break; } case TokenKind.OutputKeyword: { OutputToReportStatement outRpt; if ((result = OutputToReportStatement.TryParseNode(parser, out outRpt))) { node = outRpt; } break; } case TokenKind.StartKeyword: { StartReportStatement startRpt; if ((result = StartReportStatement.TryParseNode(parser, out startRpt))) { node = startRpt; } break; } case TokenKind.FinishKeyword: { FinishReportStatement finRpt; if ((result = FinishReportStatement.TryParseNode(parser, out finRpt))) { node = finRpt; } break; } case TokenKind.TerminateKeyword: { TerminateReportStatement termRpt; if ((result = TerminateReportStatement.TryParseNode(parser, out termRpt))) { node = termRpt; } break; } default: { if (SqlStatementFactory.IsValidStatementStart(parser.PeekToken().Kind)) { bool dummy; result = SqlStatementFactory.TryParseSqlStatement(parser, out node, out dummy); } break; } } if (result) { // check for semicolon if (parser.PeekToken(TokenKind.Semicolon)) { parser.NextToken(); } } return(result); }