internal IAnalysisResult TryGetUserDefinedType(string typeName, int index) { // do a binary search to determine what node we're in IAnalysisResult type = null; _body.SetNamespace(null); // TODO: need to handle multiple results of the same name AstNode containingNode = GetContainingNode(_body, index); if (containingNode != null) { if (containingNode is IFunctionResult) { if ((containingNode as IFunctionResult).Types.TryGetValue(typeName, out type)) { return(type); } } if (_body is IModuleResult) { if ((_body as IModuleResult).Types.TryGetValue(typeName, out type) || (_body as IModuleResult).GlobalTypes.TryGetValue(typeName, out type)) { return(type); } } } // TODO: this could probably be done more efficiently by having each GeneroAst load globals and functions into // dictionaries stored on the IGeneroProject, instead of in each project entry. // However, this does required more upkeep when changes occur. Will look into it... if (_projEntry != null && _projEntry is IGeneroProjectEntry) { IGeneroProjectEntry genProj = _projEntry as IGeneroProjectEntry; if (genProj.ParentProject != null) { foreach (var projEntry in genProj.ParentProject.ProjectEntries.Where(x => x.Value != genProj)) { if (projEntry.Value.Analysis != null && projEntry.Value.Analysis.Body != null) { projEntry.Value.Analysis.Body.SetNamespace(null); IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult; if (modRes != null) { // check global types if (modRes.GlobalTypes.TryGetValue(typeName, out type)) { return(type); } } } } } } return(type); }
public static bool TryParseNode(Genero4glParser parser, out OtherwiseStatement 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, ExpressionParsingOptions expressionOptions = null, HashSet <TokenKind> endKeywords = null) { node = null; bool result = false; if (parser.PeekToken(TokenKind.OtherwiseKeyword)) { result = true; node = new OtherwiseStatement(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; node.DecoratorEnd = parser.Token.Span.End; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (!parser.PeekToken(TokenKind.EndOfFile) && !parser.PeekToken(TokenKind.WhenKeyword) && !parser.PeekToken(TokenKind.OtherwiseKeyword) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.CaseKeyword, 2))) { FglStatement statement; if (parser.StatementFactory.TryParseNode(parser, out statement, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, false, validExitKeywords, contextStatementFactories, expressionOptions) && statement != null) { AstNode4gl stmtNode = statement as AstNode4gl; node.Children.Add(stmtNode.StartIndex, stmtNode); if (statement is ExitStatement && (statement as ExitStatement).ExitType != TokenKind.CaseKeyword) { if (validExitKeywords != null && !validExitKeywords.Contains((statement as ExitStatement).ExitType)) { parser.ReportSyntaxError("Invalid exit statement for case statement block detected."); } } } else if (parser.PeekToken(TokenKind.EndKeyword) && endKeywords != null && endKeywords.Contains(parser.PeekToken(2).Kind)) { break; } else { parser.NextToken(); } } prepStatementBinders.RemoveAt(0); node.EndIndex = parser.Token.Span.End; } return(result); }
internal IAnalysisResult GetMemberOfType(string name, object ast, bool vars, bool types, bool consts, bool funcs, out IProjectEntry definingProjEntry) { string projNamespace = string.Format("{0}", this.Name); string tempStart = string.Format("{0}.", projNamespace); if (name.StartsWith(tempStart, StringComparison.OrdinalIgnoreCase)) { name = name.Substring(tempStart.Length); } definingProjEntry = null; IAnalysisResult res = null; foreach (var projEntry in ProjectEntries) { if (projEntry.Value.Analysis != null && projEntry.Value.Analysis.Body != null) { projEntry.Value.Analysis.Body.SetNamespace(projNamespace); IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult; if (modRes != null) { // check global vars, types, and constants if ((vars && modRes.GlobalVariables.TryGetValue(name, out res)) || (types && modRes.GlobalTypes.TryGetValue(name, out res)) || (consts && modRes.GlobalConstants.TryGetValue(name, out res))) { //found = true; definingProjEntry = projEntry.Value; break; } if (((vars && modRes.Variables.TryGetValue(name, out res)) || (types && modRes.Types.TryGetValue(name, out res)) || (consts && modRes.Constants.TryGetValue(name, out res))) && res.IsPublic) { definingProjEntry = projEntry.Value; break; } // check project functions IFunctionResult funcRes = null; if (funcs && modRes.Functions.TryGetValue(name, out funcRes)) { if (funcRes.AccessModifier == AccessModifier.Public) { res = funcRes; //found = true; definingProjEntry = projEntry.Value; break; } } } } } return(res); }
public IEnumerable <MemberResult> GetMembers(GetMultipleMembersInput input) { string projNamespace = string.Format("{0}", this.Name); List <MemberResult> members = new List <MemberResult>(); foreach (var projEntry in ProjectEntries) { if (projEntry.Value.Analysis != null && projEntry.Value.Analysis.Body != null) { projEntry.Value.Analysis.Body.SetNamespace(projNamespace); IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult; if (modRes != null) { if (input.MemberType.HasFlag(MemberType.Variables)) { members.AddRange(modRes.GlobalVariables.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, input.AST))); members.AddRange(modRes.Variables.Where(x => x.Value.IsPublic).Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, input.AST))); members.AddRange(projEntry.Value.GetIncludedFiles().Where(x => x.Analysis != null).SelectMany(x => x.Analysis.GetDefinedMembers(1, AstMemberType.Variables, input.IsMemberAccess))); } if (input.MemberType.HasFlag(MemberType.Types)) { members.AddRange(modRes.GlobalTypes.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, input.AST))); members.AddRange(modRes.Types.Where(x => x.Value.IsPublic).Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, input.AST))); members.AddRange(projEntry.Value.GetIncludedFiles().Where(x => x.Analysis != null).SelectMany(x => x.Analysis.GetDefinedMembers(1, AstMemberType.UserDefinedTypes, input.IsMemberAccess))); } if (input.MemberType.HasFlag(MemberType.Constants)) { members.AddRange(modRes.GlobalConstants.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, input.AST))); members.AddRange(modRes.Constants.Where(x => x.Value.IsPublic).Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, input.AST))); members.AddRange(projEntry.Value.GetIncludedFiles().Where(x => x.Analysis != null).SelectMany(x => x.Analysis.GetDefinedMembers(1, AstMemberType.Constants, input.IsMemberAccess))); } if (input.MemberType.HasFlag(MemberType.Functions)) { members.AddRange(modRes.Functions.Where(x => x.Value.IsPublic).Select(x => new MemberResult(x.Key, x.Value, x.Value.FunctionType, input.AST))); members.AddRange(projEntry.Value.GetIncludedFiles().Where(x => x.Analysis != null).SelectMany(x => x.Analysis.GetDefinedMembers(1, AstMemberType.Functions, input.IsMemberAccess))); } } } } return(members); }
public static bool TryParseNode(Genero4glParser parser, out IfBlockContentsNode 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, ExpressionParsingOptions expressionOptions = null, HashSet <TokenKind> endKeywords = null) { node = new IfBlockContentsNode(); node.StartIndex = parser.Token.Span.Start; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (!parser.PeekToken(TokenKind.EndOfFile) && !parser.PeekToken(TokenKind.ElseKeyword) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.IfKeyword, 2))) { FglStatement statement; if (parser.StatementFactory.TryParseNode(parser, out statement, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, false, validExitKeywords, contextStatementFactories, expressionOptions, endKeywords)) { AstNode4gl stmtNode = statement as AstNode4gl; if (stmtNode != null && !node.Children.ContainsKey(stmtNode.StartIndex)) { node.Children.Add(stmtNode.StartIndex, stmtNode); } } else if (parser.PeekToken(TokenKind.EndKeyword) && endKeywords != null && endKeywords.Contains(parser.PeekToken(2).Kind)) { break; } else { parser.NextToken(); } } prepStatementBinders.RemoveAt(0); node.EndIndex = parser.Token.Span.End; return(true); }
public IEnumerable <MemberResult> GetMembers(Genero4glAst ast, MemberType memberType, bool function) { string projNamespace = string.Format("{0}", this.Name); List <MemberResult> members = new List <MemberResult>(); foreach (var projEntry in ProjectEntries) { if (projEntry.Value.Analysis != null && projEntry.Value.Analysis.Body != null) { projEntry.Value.Analysis.Body.SetNamespace(projNamespace); IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult; if (modRes != null) { if (memberType.HasFlag(MemberType.Variables)) { members.AddRange(modRes.GlobalVariables.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, ast))); members.AddRange(modRes.Variables.Where(x => x.Value.IsPublic).Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, ast))); } if (memberType.HasFlag(MemberType.Types)) { members.AddRange(modRes.GlobalTypes.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, ast))); members.AddRange(modRes.Types.Where(x => x.Value.IsPublic).Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, ast))); } if (memberType.HasFlag(MemberType.Constants)) { members.AddRange(modRes.GlobalConstants.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, ast))); members.AddRange(modRes.Constants.Where(x => x.Value.IsPublic).Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, ast))); } if (memberType.HasFlag(MemberType.Functions)) { members.AddRange(modRes.Functions.Where(x => x.Value.IsPublic).Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Method, ast))); } } } } return(members); }
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); }
public static bool TryGetStatement(Genero4glParser parser, out FglStatement node, bool isArray, 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) { bool result = false; node = null; DisplayStatement inputStmt; if ((result = TryGetDisplayStatement(parser, out inputStmt, isArray))) { node = inputStmt; } else { List <ContextStatementFactory> csfs = new List <ContextStatementFactory>(); if (contextStatementFactories != null) { csfs.AddRange(contextStatementFactories); } csfs.Add((x) => { DisplayStatement testNode; TryGetDisplayStatement(x, out testNode, isArray, true); return(testNode); }); result = parser.StatementFactory.TryParseNode(parser, out node, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, false, validExitKeywords, csfs, null, endKeywords); } return(result); }
public static bool TryGetStatement(Genero4glParser parser, out FglStatement node, IModuleResult containingModule, ReportBlockNode reportNode, List <Func <PrepareStatement, bool> > prepStatementBinders, Func <ReturnStatement, ParserResult> returnStatementBinder = null, Action <IAnalysisResult, int, int> limitedScopeVariableAdder = null, List <TokenKind> validExitKeywords = null, IEnumerable <ContextStatementFactory> contextStatementFactories = null) { bool result = false; node = null; if (!(result = TryGetReportStatement(parser, out node, reportNode))) { List <ContextStatementFactory> csfs = new List <ContextStatementFactory>(); if (contextStatementFactories != null) { csfs.AddRange(contextStatementFactories); } csfs.Add((x) => { FglStatement testNode; TryGetReportStatement(x, out testNode, reportNode, true); return(testNode); }); result = parser.StatementFactory.TryParseNode(parser, out node, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, false, validExitKeywords, csfs, new ExpressionParsingOptions { AllowStarParam = true, AdditionalExpressionParsers = new ExpressionParser[] { (x) => ParseAggregateReportFunction(x, reportNode) } }); } 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 static bool TryParseNode(Genero4glParser parser, out ForeachStatement 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.ForeachKeyword)) { result = true; node = new ForeachStatement(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; node.InputVars = new List <FglNameExpression>(); node.OutputVars = new List <FglNameExpression>(); FglNameExpression cid; if (FglNameExpression.TryParseNode(parser, out cid)) { node.CursorId = cid; } else { parser.ReportSyntaxError("Invalid declared cursor id found in foreach statement."); } HashSet <TokenKind> inVarMods = new HashSet <TokenKind> { TokenKind.InKeyword, TokenKind.OutKeyword, TokenKind.InOutKeyword }; if (parser.PeekToken(TokenKind.UsingKeyword)) { parser.NextToken(); FglNameExpression inVar; while (FglNameExpression.TryParseNode(parser, out inVar, TokenKind.Comma)) { node.InputVars.Add(inVar); if (inVarMods.Contains(parser.PeekToken().Kind)) { parser.NextToken(); } if (parser.PeekToken(TokenKind.Comma)) { parser.NextToken(); } else { break; } } } if (parser.PeekToken(TokenKind.IntoKeyword)) { parser.NextToken(); FglNameExpression outVar; while (FglNameExpression.TryParseNode(parser, out outVar, TokenKind.Comma)) { node.InputVars.Add(outVar); if (parser.PeekToken(TokenKind.Comma)) { parser.NextToken(); } else { break; } } } node.DecoratorEnd = parser.Token.Span.End; if (parser.PeekToken(TokenKind.WithKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.ReoptimizationKeyword)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expecting keyword \"reoptimization\" in open statement."); } } List <TokenKind> validExits = new List <TokenKind>(); if (validExitKeywords != null) { validExits.AddRange(validExitKeywords); } validExits.Add(TokenKind.ForeachKeyword); HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.ForeachKeyword); prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ForeachKeyword, 2))) { FglStatement statement; if (parser.StatementFactory.TryParseNode(parser, out statement, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, false, validExits, contextStatementFactories, null, newEndKeywords) && statement != null) { AstNode4gl stmtNode = statement as AstNode4gl; node.Children.Add(stmtNode.StartIndex, stmtNode); if (statement is ExitStatement && (statement as ExitStatement).ExitType != TokenKind.ForeachKeyword) { if (validExitKeywords == null || !validExitKeywords.Contains((statement as ExitStatement).ExitType)) { parser.ReportSyntaxError("Invalid exit statement for for loop detected."); } } if (statement is ContinueStatement && (statement as ContinueStatement).ContinueType != TokenKind.ForeachKeyword) { if (validExitKeywords == null || !validExitKeywords.Contains((statement as ContinueStatement).ContinueType)) { parser.ReportSyntaxError("Invalid continue statement for for loop detected."); } } } 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.ForeachKeyword, 2))) { parser.ReportSyntaxError("A foreach statement must be terminated with \"end foreach\"."); } else { parser.NextToken(); // advance to the 'end' token parser.NextToken(); // advance to the 'foreach' token node.EndIndex = parser.Token.Span.End; } } return(result); }
public static bool TryParseNode(Genero4glParser parser, out CaseStatement 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, ExpressionParsingOptions expressionOptions = null, HashSet <TokenKind> endKeywords = null) { node = null; bool result = false; if (parser.PeekToken(TokenKind.CaseKeyword)) { result = true; node = new CaseStatement(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; if (!parser.PeekToken(TokenKind.WhenKeyword)) { ExpressionNode tempExpr; if (FglExpressionNode.TryGetExpressionNode(parser, out tempExpr, new List <TokenKind> { TokenKind.WhenKeyword })) { node.ConditionExpression = tempExpr; } else { parser.ReportSyntaxError("Invalid conditional expression found in case statement"); } } node.DecoratorEnd = parser.Token.Span.End; List <TokenKind> validExits = new List <TokenKind>(); if (validExitKeywords != null) { validExits.AddRange(validExitKeywords); } validExits.Add(TokenKind.CaseKeyword); HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.CaseKeyword); // need to allow multiple when statements bool whenCases = true; while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.CaseKeyword, 2))) { WhenStatement whenStmt; if (WhenStatement.TryParseNode(parser, out whenStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExits, contextStatementFactories, expressionOptions, newEndKeywords) && whenStmt != null) { if (whenCases) { node.Children.Add(whenStmt.StartIndex, whenStmt); } else { parser.ReportSyntaxError("A when case cannot come after an otherwise case block."); break; } } else { OtherwiseStatement otherStmt; if (OtherwiseStatement.TryParseNode(parser, out otherStmt, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExits, contextStatementFactories, expressionOptions, newEndKeywords) && otherStmt != null) { whenCases = false; node.Children.Add(otherStmt.StartIndex, otherStmt); } else { parser.ReportSyntaxError("Invalid statement detected within case statement block."); break; } } } if (!(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.CaseKeyword, 2))) { parser.ReportSyntaxError("A case statement must be terminated with \"end case\"."); } else { parser.NextToken(); // advance to the 'end' token parser.NextToken(); // advance to the 'case' token node.EndIndex = parser.Token.Span.End; } } return(result); }
public static bool TryParseNode(Genero4glParser parser, out ConstructBlock 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.ConstructKeyword)) { result = true; node = new ConstructBlock(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; node.ColumnList = new List <FglNameExpression>(); node.FieldList = new List <FglNameExpression>(); node.Attributes = new List <ConstructAttribute>(); 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 construct statement."); } } FglNameExpression varName; if (FglNameExpression.TryParseNode(parser, out varName)) { node.Variable = varName; } else { parser.ReportSyntaxError("Invalid variable name found in construct statement."); } node.DecoratorEnd = parser.Token.Span.End; if (parser.PeekToken(TokenKind.OnKeyword)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expecting \"on\" keyword in construct statement."); } FglNameExpression colName; while (FglNameExpression.TryParseNode(parser, out colName)) { node.ColumnList.Add(colName); if (!parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } if (!node.IsImplicitMapping) { if (parser.PeekToken(TokenKind.FromKeyword)) { parser.NextToken(); // read the field list FglNameExpression nameExpr; while (FglNameExpression.TryParseNode(parser, out nameExpr)) { node.FieldList.Add(nameExpr); if (!parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } } else { parser.ReportSyntaxError("Expected \"from\" token in construct 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 ConstructAttribute attrib; while (ConstructAttribute.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 construct attributes section."); } } else { parser.ReportSyntaxError("Expecting left-paren in construct 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 construct statement."); } } List <TokenKind> validExits = new List <TokenKind>(); if (validExitKeywords != null) { validExits.AddRange(validExitKeywords); } validExits.Add(TokenKind.ConstructKeyword); HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.ConstructKeyword); bool hasControlBlocks = false; ConstructControlBlock icb; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (ConstructControlBlock.TryParseNode(parser, out icb, containingModule, 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.ConstructKeyword, 2))) { break; } } prepStatementBinders.RemoveAt(0); if (hasControlBlocks || (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ConstructKeyword, 2))) { if (!(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ConstructKeyword, 2))) { parser.ReportSyntaxError("A construct block must be terminated with \"end construct\"."); } else { parser.NextToken(); // advance to the 'end' token parser.NextToken(); // advance to the 'construct' token node.EndIndex = parser.Token.Span.End; } } } return(result); }
internal static bool TryParseNode(Genero4glParser parser, out CreateTableStatement node, IModuleResult containingModule) { node = null; bool result = false; bool temp = false; int tempIndex = -1; if (parser.PeekToken(TokenKind.TempKeyword)) { tempIndex = parser.Token.Span.Start; temp = true; parser.NextToken(); } if (parser.PeekToken(TokenKind.TableKeyword)) { result = true; node = new CreateTableStatement(); node.TempTable = temp; if (tempIndex >= 0) { node.StartIndex = tempIndex; } else { node.StartIndex = parser.Token.Span.Start; } parser.NextToken(); if (parser.PeekToken(TokenKind.IfKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.NotKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.ExistsKeyword)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expecting \"exists\" keyword in create table statement."); } } else { parser.ReportSyntaxError("Expecting \"not\" keyword in create table statement."); } } FglNameExpression nameExpr; if (FglNameExpression.TryParseNode(parser, out nameExpr)) { node.TableName = nameExpr; } else { parser.ReportSyntaxError("Invalid name found for create table statement."); } if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); CreatedTableColumn tableCol; while (CreatedTableColumn.TryParseNode(parser, out tableCol) && tableCol != null) { node.Children.Add(tableCol.StartIndex, tableCol); if (parser.PeekToken(TokenKind.Comma)) { parser.NextToken(); } else { break; } } if (parser.PeekToken(TokenKind.RightParenthesis)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expected right-paren in create table statement."); } if (parser.PeekToken(TokenKind.WithKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.NoKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.LogKeyword)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expecting \"log\" keyword in create table statement."); } } else { parser.ReportSyntaxError("Expecting \"no\" keyword in create table statement."); } } if (parser.PeekToken(TokenKind.InKeyword)) { parser.NextToken(); if (FglNameExpression.TryParseNode(parser, out nameExpr)) { node.TablespaceName = nameExpr; } else { parser.ReportSyntaxError("Invalid name found for create table statement."); } } if (parser.PeekToken(TokenKind.ExtentKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.SizeKeyword)) { parser.NextToken(); ExpressionNode extSize; if (FglExpressionNode.TryGetExpressionNode(parser, out extSize)) { node.ExtentSize = extSize; } else { parser.ReportSyntaxError("Invalid expression found for extent size in create table statement."); } } else { parser.ReportSyntaxError("Expecting \"size\" keyword in create table statement."); } } if (parser.PeekToken(TokenKind.NextKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.SizeKeyword)) { parser.NextToken(); ExpressionNode extSize; if (FglExpressionNode.TryGetExpressionNode(parser, out extSize)) { node.NextSize = extSize; } else { parser.ReportSyntaxError("Invalid expression found for next size in create table statement."); } } else { parser.ReportSyntaxError("Expecting \"size\" keyword in create table statement."); } } if (parser.PeekToken(TokenKind.LockKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.ModeKeyword)) { parser.NextToken(); switch (parser.PeekToken().Kind) { case TokenKind.PageKeyword: parser.NextToken(); break; case TokenKind.RowKeyword: parser.NextToken(); break; default: parser.ReportSyntaxError("Expecting \"page\" or \"row\" keyword in create table statement."); break; } } else { parser.ReportSyntaxError("Expecting \"mode\" keyword in create table statement."); } } } else { parser.ReportSyntaxError("Expected left-paren in create table statement."); } containingModule.BindTableResult(node, parser); } return(result); }
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 DeclareStatement defNode, IModuleResult containingModule) { defNode = null; bool result = false; if (parser.PeekToken(TokenKind.DeclareKeyword)) { result = true; defNode = new DeclareStatement(); parser.NextToken(); defNode.StartIndex = parser.Token.Span.Start; defNode._prepStatementResolver = containingModule.PreparedCursorResolver; if (parser.PeekToken(TokenCategory.Identifier) || parser.PeekToken(TokenCategory.Keyword)) { parser.NextToken(); defNode.Identifier = parser.Token.Token.Value.ToString(); if (parser.PeekToken(TokenKind.ScrollKeyword)) { parser.NextToken(); defNode.Scroll = true; } if (parser.PeekToken(TokenKind.CursorKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.WithKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.HoldKeyword)) { parser.NextToken(); defNode.WithHold = true; } else { parser.ReportSyntaxError("SQL declare statement missing \"hold\" keyword."); } } if (parser.PeekToken(TokenKind.FromKeyword)) { parser.NextToken(); // We have a string expression declare ExpressionNode exprNode; if (FglExpressionNode.TryGetExpressionNode(parser, out exprNode) /* && exprNode is StringExpressionNode*/ && exprNode != null) { defNode.Children.Add(exprNode.StartIndex, exprNode); defNode.EndIndex = exprNode.EndIndex; containingModule.BindCursorResult(defNode, parser); } else { parser.ReportSyntaxError("String expression not found for SQl declare statement"); } } else if (parser.PeekToken(TokenKind.ForKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.SqlKeyword)) { // we have a sql block declare SqlBlockNode sqlBlock; if (SqlBlockNode.TryParseSqlNode(parser, out sqlBlock) && sqlBlock != null) { defNode.Children.Add(sqlBlock.StartIndex, sqlBlock); defNode.EndIndex = sqlBlock.EndIndex; defNode.IsComplete = true; containingModule.BindCursorResult(defNode, parser); } } else if (parser.PeekToken(TokenKind.SelectKeyword)) { // we have a static sql select statement FglStatement sqlStmt; bool dummy; if (SqlStatementFactory.TryParseSqlStatement(parser, out sqlStmt, out dummy, TokenKind.SelectKeyword) && sqlStmt != null) { defNode.Children.Add(sqlStmt.StartIndex, sqlStmt); defNode.EndIndex = sqlStmt.EndIndex; defNode.IsComplete = true; containingModule.BindCursorResult(defNode, parser); } else { parser.ReportSyntaxError("Static SQL declare statement must specify a SELECT statement."); } } else if (parser.PeekToken(TokenCategory.Identifier) || parser.PeekToken(TokenCategory.Keyword)) { // we have a prepared statment parser.NextToken(); defNode.PreparedStatementId = parser.Token.Token.Value.ToString(); defNode.EndIndex = parser.Token.Span.End; defNode.IsComplete = true; containingModule.BindCursorResult(defNode, parser); } else { parser.ReportSyntaxError("Invalid token found in SQL declare statment."); } } else { parser.ReportSyntaxError("SQL declare statement must have either \"for\" or \"from\" keyword."); } } else { parser.ReportSyntaxError("SQL declare statement missing \"cursor\" keyword."); } } else { parser.ReportSyntaxError("SQL declare statement must specify an identifier to declare."); } } return(result); }
public override IEnumerable <MemberResult> GetDefinedMembers(int index, AstMemberType memberType, bool isMemberAccess = false) { HashSet <MemberResult> members = new HashSet <MemberResult>(); HashSet <GeneroPackage> includedPackages = new HashSet <GeneroPackage>(); if (memberType.HasFlag(AstMemberType.SystemTypes) && !isMemberAccess) { // Built-in types members.AddRange(BuiltinTypes.Select(x => new MemberResult(Tokens.TokenKinds[x], GeneroMemberType.Keyword, this))); foreach (var package in Packages.Values.Where(x => _importedPackages[x.Name] && x.ContainsInstanceMembers && (this.LanguageVersion >= x.MinimumLanguageVersion && this.LanguageVersion <= x.MaximumLanguageVersion))) { members.Add(new MemberResult(package.Name, GeneroMemberType.Module, this)); includedPackages.Add(package); } } if (memberType.HasFlag(AstMemberType.Constants) && !isMemberAccess) { members.AddRange(SystemConstants.Where(x => this.LanguageVersion >= x.Value.MinimumLanguageVersion && this.LanguageVersion <= x.Value.MaximumLanguageVersion) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Keyword, this))); members.AddRange(SystemMacros.Where(x => this.LanguageVersion >= x.Value.MinimumLanguageVersion && this.LanguageVersion <= x.Value.MaximumLanguageVersion) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, this))); } if (memberType.HasFlag(AstMemberType.Variables) && !isMemberAccess) { members.AddRange(SystemVariables.Where(x => this.LanguageVersion >= x.Value.MinimumLanguageVersion && this.LanguageVersion <= x.Value.MaximumLanguageVersion) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Keyword, this))); } if (memberType.HasFlag(AstMemberType.Functions) && !isMemberAccess) { members.AddRange(SystemFunctions.Where(x => this.LanguageVersion >= x.Value.MinimumLanguageVersion && this.LanguageVersion <= x.Value.MaximumLanguageVersion) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Function, this))); foreach (var package in Packages.Values.Where(x => _importedPackages[x.Name] && x.ContainsStaticClasses && (this.LanguageVersion >= x.MinimumLanguageVersion && this.LanguageVersion <= x.MaximumLanguageVersion))) { if (!includedPackages.Contains(package)) { members.Add(new MemberResult(package.Name, GeneroMemberType.Module, this)); } } } // TODO: need to handle multiple results of the same name AstNode containingNode = GetContainingNode(_body, index); if (containingNode != null) { if (containingNode is IFunctionResult) { if (memberType.HasFlag(AstMemberType.Variables)) { members.AddRange((containingNode as IFunctionResult).Variables.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))); foreach (var varList in (containingNode as IFunctionResult).LimitedScopeVariables) { foreach (var item in varList.Value) { if (item.Item2.IsInSpan(index)) { members.Add(new MemberResult(item.Item1.Name, item.Item1, GeneroMemberType.Instance, this)); break; } } } } if (memberType.HasFlag(AstMemberType.SystemTypes)) { members.AddRange((containingNode as IFunctionResult).Types.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, this))); } if (memberType.HasFlag(AstMemberType.Constants)) { members.AddRange((containingNode as IFunctionResult).Constants.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, this))); } if (memberType.HasFlag(AstMemberType.Functions)) { foreach (var res in (containingNode as IFunctionResult).Variables /*.Where(x => x.Value.HasChildFunctions(this)) */.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))) { if (!members.Contains(res)) { members.Add(res); } } foreach (var varList in (containingNode as IFunctionResult).LimitedScopeVariables) { foreach (var item in varList.Value) { if (item.Item2.IsInSpan(index)) { members.Add(new MemberResult(item.Item1.Name, item.Item1, GeneroMemberType.Instance, this)); break; } } } } } if (_body is IModuleResult) { // check for module vars, types, and constants (and globals defined in this module) if (memberType.HasFlag(AstMemberType.Variables)) { members.AddRange((_body as IModuleResult).Variables.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))); members.AddRange((_body as IModuleResult).GlobalVariables.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))); } if (memberType.HasFlag(AstMemberType.UserDefinedTypes)) { members.AddRange((_body as IModuleResult).Types.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, this))); members.AddRange((_body as IModuleResult).GlobalTypes.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, this))); } if (memberType.HasFlag(AstMemberType.Constants)) { members.AddRange((_body as IModuleResult).Constants.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, this))); members.AddRange((_body as IModuleResult).GlobalConstants.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, this))); } if (memberType.HasFlag(AstMemberType.Dialogs)) { members.AddRange((_body as IModuleResult).Functions.Where(x => x.Value is DeclarativeDialogBlock) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Dialog, this))); members.AddRange((_body as IModuleResult).FglImports.Select(x => new MemberResult(x, GeneroMemberType.Module, this))); } if (memberType.HasFlag(AstMemberType.Reports)) { members.AddRange((_body as IModuleResult).Functions.Where(x => x.Value is ReportBlockNode) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Report, this))); } if (memberType.HasFlag(AstMemberType.Functions)) { members.AddRange((_body as IModuleResult).Functions .Where(x => !(x.Value is ReportBlockNode) && !(x.Value is DeclarativeDialogBlock)) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Method, this))); foreach (var res in (_body as IModuleResult).Variables /*.Where(x => x.Value.HasChildFunctions(this)) */.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))) { if (!members.Contains(res)) { members.Add(res); } } foreach (var res in (_body as IModuleResult).GlobalVariables /*.Where(x => x.Value.HasChildFunctions(this)) */.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))) { if (!members.Contains(res)) { members.Add(res); } } } // Tables and cursors are module specific, and cannot be accessed via fgl import if (memberType.HasFlag(AstMemberType.DeclaredCursors) || memberType.HasFlag(AstMemberType.PreparedCursors) || memberType.HasFlag(AstMemberType.Tables)) { if (memberType.HasFlag(AstMemberType.DeclaredCursors)) { members.AddRange((_body as IModuleResult).Cursors.Where(x => x.Value is DeclareStatement).Select(x => new MemberResult(x.Value.Name, x.Value, GeneroMemberType.Cursor, this))); } if (memberType.HasFlag(AstMemberType.PreparedCursors)) { members.AddRange((_body as IModuleResult).Cursors.Where(x => x.Value is PrepareStatement).Select(x => new MemberResult(x.Value.Name, x.Value, GeneroMemberType.Cursor, this))); } if (memberType.HasFlag(AstMemberType.Tables)) { members.AddRange((_body as IModuleResult).Tables.Select(x => new MemberResult(x.Value.Name, x.Value, GeneroMemberType.DbTable, this))); } } else { members.AddRange((_body as IModuleResult).FglImports.Select(x => new MemberResult(x, GeneroMemberType.Module, this))); } } } // TODO: this could probably be done more efficiently by having each GeneroAst load globals and functions into // dictionaries stored on the IGeneroProject, instead of in each project entry. // However, this does required more upkeep when changes occur. Will look into it... if (_projEntry != null && _projEntry is IGeneroProjectEntry) { IGeneroProjectEntry genProj = _projEntry as IGeneroProjectEntry; if (genProj.ParentProject != null && !genProj.FilePath.ToLower().EndsWith(".inc")) { foreach (var projEntry in genProj.ParentProject.ProjectEntries.Where(x => x.Value != genProj)) { if (projEntry.Value.Analysis != null && projEntry.Value.Analysis.Body != null) { projEntry.Value.Analysis.Body.SetNamespace(null); IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult; if (modRes != null) { // check global types // TODO: need to add an option to enable/disable legacy linking (to not reference other modules' non-public members if (memberType.HasFlag(AstMemberType.Variables)) { members.AddRange(modRes.GlobalVariables.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))); members.AddRange(modRes.Variables.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))); } if (memberType.HasFlag(AstMemberType.UserDefinedTypes)) { members.AddRange(modRes.GlobalTypes.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, this))); members.AddRange(modRes.Types.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Class, this))); } if (memberType.HasFlag(AstMemberType.Constants)) { members.AddRange(modRes.GlobalConstants.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, this))); members.AddRange(modRes.Constants.Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Constant, this))); } if (memberType.HasFlag(AstMemberType.Dialogs)) { members.AddRange(modRes.Functions.Where(x => x.Value is DeclarativeDialogBlock) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Dialog, this))); } if (memberType.HasFlag(AstMemberType.Reports)) { members.AddRange(modRes.Functions.Where(x => x.Value is ReportBlockNode) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Report, this))); } if (memberType.HasFlag(AstMemberType.Functions)) { members.AddRange(modRes.Functions.Where(x => !(x.Value is ReportBlockNode) && !(x.Value is DeclarativeDialogBlock)) .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Method, this))); foreach (var res in modRes.GlobalVariables/*.Where(x => * { * return x.Value.HasChildFunctions(this); * })*/ .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))) { if (!members.Contains(res)) { members.Add(res); } } foreach (var res in modRes.Variables/*.Where(x => * { * return x.Value.HasChildFunctions(this); * })*/ .Select(x => new MemberResult(x.Key, x.Value, GeneroMemberType.Variable, this))) { if (!members.Contains(res)) { members.Add(res); } } } } } } } } if (memberType.HasFlag(AstMemberType.Functions)) { _includePublicFunctions = true; // allow for deferred adding of public functions } if (memberType.HasFlag(AstMemberType.Tables)) { _includeDatabaseTables = true; // allow for deferred adding of external database tables } members.AddRange(this.ProjectEntry.GetIncludedFiles().Where(x => x.Analysis != null).SelectMany(x => x.Analysis.GetDefinedMembers(1, memberType))); return(members); }
public static bool TryParseNode(Genero4glParser parser, out DisplayBlock 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.DisplayKeyword)) { result = true; node = new DisplayBlock(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; node.Attributes = new List <DisplayAttribute>(); node.ByNameFields = new List <FglNameExpression>(); node.FieldSpecs = new List <FglNameExpression>(); node.DecoratorEnd = parser.Token.Span.End; if (parser.PeekToken(TokenKind.ByKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.NameKeyword)) { parser.NextToken(); // get the bynamefields FglNameExpression nameExpr; while (FglNameExpression.TryParseNode(parser, out nameExpr)) { node.ByNameFields.Add(nameExpr); if (!parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } node.DecoratorEnd = parser.Token.Span.End; // get the optional attributes if (parser.PeekToken(TokenKind.AttributesKeyword) || parser.PeekToken(TokenKind.AttributeKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); DisplayAttribute attrib; while (DisplayAttribute.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 display attributes section."); } } else { parser.ReportSyntaxError("Expecting left-paren in display attributes section."); } } node.EndIndex = parser.Token.Span.End; } else { parser.ReportSyntaxError("Expected \"name\" keyword in display 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 display array statement."); } node.DecoratorEnd = parser.Token.Span.End; if (parser.PeekToken(TokenKind.ToKeyword)) { parser.NextToken(); if (FglNameExpression.TryParseNode(parser, out arrName)) { node.ScreenArrayName = arrName; } else { parser.ReportSyntaxError("Invalid array name found in display array statement."); } 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."); } } // get the optional attributes if (parser.PeekToken(TokenKind.AttributesKeyword) || parser.PeekToken(TokenKind.AttributeKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); DisplayAttribute attrib; while (DisplayAttribute.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 display attributes section."); } } else { parser.ReportSyntaxError("Expecting left-paren in display attributes section."); } } List <TokenKind> validExits = new List <TokenKind>(); if (validExitKeywords != null) { validExits.AddRange(validExitKeywords); } validExits.Add(TokenKind.DisplayKeyword); HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.DisplayKeyword); bool hasControlBlocks = false; DisplayControlBlock icb; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (DisplayControlBlock.TryParseNode(parser, out icb, containingModule, hasControlBlocks, node.IsArray, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExits, contextStatementFactories, newEndKeywords) && icb != null) { // check for include file sign 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.DisplayKeyword, 2))) { break; } } prepStatementBinders.RemoveAt(0); if (hasControlBlocks || (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.DisplayKeyword, 2))) { if (!(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.DisplayKeyword, 2))) { parser.ReportSyntaxError("A display block must be terminated with \"end display\"."); } else { parser.NextToken(); // advance to the 'end' token parser.NextToken(); // advance to the 'display' token node.EndIndex = parser.Token.Span.End; } } } else { parser.ReportSyntaxError("Expected \"to\" keyword in display array statement."); } } else { // get the expression(s) ExpressionNode mainExpression = null; while (true) { ExpressionNode expr; if (!FglExpressionNode.TryGetExpressionNode(parser, out expr, new List <TokenKind> { TokenKind.ToKeyword, TokenKind.AttributeKeyword, TokenKind.AttributesKeyword })) { parser.ReportSyntaxError("Display statement must have one or more comma-separated expressions."); break; } if (mainExpression == null) { mainExpression = expr; } else { mainExpression.AppendExpression(expr); } if (!parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } if (mainExpression != null) { node.Expression = mainExpression; } else { parser.ReportSyntaxError("Invalid expression found in display statement."); } if (parser.PeekToken(TokenKind.ToKeyword)) { parser.NextToken(); // get the field specs FglNameExpression nameExpr; while (FglNameExpression.TryParseNode(parser, out nameExpr)) { node.FieldSpecs.Add(nameExpr); if (!parser.PeekToken(TokenKind.Comma)) { break; } parser.NextToken(); } // get the optional attributes if (parser.PeekToken(TokenKind.AttributesKeyword) || parser.PeekToken(TokenKind.AttributeKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); DisplayAttribute attrib; while (DisplayAttribute.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 display attributes section."); } } } node.EndIndex = parser.Token.Span.End; } } return(result); }
/// <summary> /// Gets the variables the given expression evaluates to. Variables include parameters, locals, and fields assigned on classes, modules and instances. /// /// Variables are classified as either definitions or references. Only parameters have unique definition points - all other types of variables /// have only one or more references. /// /// index is a 0-based absolute index into the file. /// </summary> public override IEnumerable <IAnalysisVariable> GetVariablesByIndex(string exprText, int index, IFunctionInformationProvider functionProvider, IDatabaseInformationProvider databaseProvider, IProgramFileProvider programFileProvider, bool isFunctionCallOrDefinition) { _functionProvider = functionProvider; _databaseProvider = databaseProvider; _programFileProvider = programFileProvider; List <IAnalysisVariable> vars = new List <IAnalysisVariable>(); _body.SetNamespace(null); AstNode containingNode = GetContainingNode(_body, index); if (containingNode != null) { if (!isFunctionCallOrDefinition) { if (containingNode is IFunctionResult) { // Check for local vars, types, and constants IFunctionResult func = containingNode as IFunctionResult; IAnalysisResult res; if (func.Variables.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (func.Types.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (func.Constants.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } List <Tuple <IAnalysisResult, IndexSpan> > limitedScopeVars; if (func.LimitedScopeVariables.TryGetValue(exprText, out limitedScopeVars)) { foreach (var item in limitedScopeVars) { if (item.Item2.IsInSpan(index)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Reference)); } } } } } if (_body is IModuleResult) { // check for module vars, types, and constants (and globals defined in this module) IModuleResult mod = _body as IModuleResult; IAnalysisResult res; if (!isFunctionCallOrDefinition) { if (mod.Variables.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (mod.Types.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (mod.Constants.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (mod.GlobalVariables.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (mod.GlobalTypes.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } if (mod.GlobalConstants.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } // check for cursors in this module if (mod.Cursors.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(this.ResolveLocation(res), VariableType.Definition)); } } else { // check for module functions IFunctionResult funcRes; if (mod.Functions.TryGetValue(exprText, out funcRes)) { vars.Add(new AnalysisVariable(this.ResolveLocation(funcRes), VariableType.Definition, funcRes.Name, 1)); } } } } // TODO: this could probably be done more efficiently by having each GeneroAst load globals and functions into // dictionaries stored on the IGeneroProject, instead of in each project entry. // However, this does required more upkeep when changes occur. Will look into it... if (_projEntry != null && _projEntry is IGeneroProjectEntry) { IGeneroProjectEntry genProj = _projEntry as IGeneroProjectEntry; if (genProj.ParentProject != null && !genProj.FilePath.ToLower().EndsWith(".inc")) { foreach (var projEntry in genProj.ParentProject.ProjectEntries.Where(x => x.Value != genProj)) { if (projEntry.Value.Analysis != null && projEntry.Value.Analysis.Body != null) { projEntry.Value.Analysis.Body.SetNamespace(null); IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult; if (modRes != null) { if (!isFunctionCallOrDefinition) { // check global vars, types, and constants // TODO: need to introduce option to enable/disable legacy linking IAnalysisResult res; if (modRes.GlobalVariables.TryGetValue(exprText, out res) || modRes.Variables.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(projEntry.Value.Analysis.ResolveLocation(res), VariableType.Definition)); } if (modRes.GlobalTypes.TryGetValue(exprText, out res) || modRes.Types.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(projEntry.Value.Analysis.ResolveLocation(res), VariableType.Definition)); } if (modRes.GlobalConstants.TryGetValue(exprText, out res) || modRes.Constants.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(projEntry.Value.Analysis.ResolveLocation(res), VariableType.Definition)); } // check for cursors in this module if (modRes.Cursors.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(projEntry.Value.Analysis.ResolveLocation(res), VariableType.Definition)); } } else { // check for module functions IFunctionResult funcRes; if (modRes.Functions.TryGetValue(exprText, out funcRes)) { vars.Add(new AnalysisVariable(projEntry.Value.Analysis.ResolveLocation(funcRes), VariableType.Definition, funcRes.Name, 1)); } } } } } } } /* TODO: * Need to check for: * 1) Temp tables * 2) DB Tables and columns * 3) Record fields */ if (isFunctionCallOrDefinition && _functionProvider != null) { var funcRes = _functionProvider.GetFunction(exprText); if (funcRes != null) { vars.AddRange(funcRes.Select(x => new AnalysisVariable(x.Location, VariableType.Definition, x.Name, 2))); } IFunctionResult funcResult; if (SystemFunctions.TryGetValue(exprText, out funcResult)) { vars.Add(new AnalysisVariable(funcResult.Location, VariableType.Definition, funcResult.Name, 2)); } } // try an imported module if (Body is IModuleResult && ProjectEntry != null) { if ((Body as IModuleResult).FglImports.Contains(exprText)) { // need to get the ast for the other project entry var refProjKVP = (ProjectEntry as IGeneroProjectEntry).ParentProject.ReferencedProjects.Values.FirstOrDefault( x => { var fn = Path.GetFileNameWithoutExtension(x.Directory); return(fn?.Equals(exprText, StringComparison.OrdinalIgnoreCase) ?? false); }); if (refProjKVP is IAnalysisResult) { IGeneroProject definingProject = refProjKVP; vars.Add(new AnalysisVariable(new LocationInfo(definingProject.Directory, 1), VariableType.Definition)); } } } if (exprText.Contains('.') && vars.Count == 0) { IGeneroProject definingProj; IProjectEntry projEntry; bool dummyDef; IAnalysisResult res = GetValueByIndex(exprText, index, functionProvider, databaseProvider, _programFileProvider, isFunctionCallOrDefinition, out dummyDef, out definingProj, out projEntry); if (res != null) { LocationInfo locInfo = null; if (definingProj != null || projEntry != null) { locInfo = ResolveLocationInternal(definingProj, projEntry, res); } else { locInfo = this.ResolveLocation(res); } if (locInfo != null && ( (locInfo.Index > 0 || (locInfo.Line > 0 && locInfo.Column > 0)) || !string.IsNullOrWhiteSpace(locInfo.DefinitionURL) ) ) { vars.Add(new AnalysisVariable(locInfo, VariableType.Definition)); } } } if (_body is IModuleResult && _projEntry is IGeneroProjectEntry) { string dotPiece = exprText; string[] dotPieces = exprText.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); if (dotPieces.Length > 1) { dotPiece = dotPieces[0]; } if ((_body as IModuleResult).FglImports.Contains(dotPiece)) { // need to get the ast for the other project entry var refProjKVP = (_projEntry as IGeneroProjectEntry).ParentProject.ReferencedProjects.Values.FirstOrDefault( x => { var fn = Path.GetFileName(x.Directory); return(fn?.Equals(dotPiece, StringComparison.OrdinalIgnoreCase) ?? false); }); if (refProjKVP is IAnalysisResult) { IProjectEntry dummyEntry; bool dummyDef; IAnalysisResult res = GetValueByIndex(exprText, index, functionProvider, databaseProvider, _programFileProvider, isFunctionCallOrDefinition, out dummyDef, out refProjKVP, out dummyEntry); if (res != null) { LocationInfo locInfo = null; locInfo = refProjKVP != null?ResolveLocationInternal(refProjKVP, dummyEntry, res) : this.ResolveLocation(res); if (locInfo != null && (locInfo.Index > 0 || (locInfo.Line > 0 && locInfo.Column > 0))) { vars.Add(new AnalysisVariable(locInfo, VariableType.Definition)); } } } } } if (!isFunctionCallOrDefinition) { foreach (var includeFile in this.ProjectEntry.GetIncludedFiles()) { IAnalysisResult res; if (includeFile.Analysis != null && includeFile.Analysis.Body is IModuleResult) { includeFile.Analysis.Body.SetNamespace(null); var mod = includeFile.Analysis.Body as IModuleResult; if (mod.Types.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(ResolveLocationInternal(null, includeFile, res), VariableType.Definition)); } if (mod.Constants.TryGetValue(exprText, out res)) { vars.Add(new AnalysisVariable(ResolveLocationInternal(null, includeFile, res), VariableType.Definition)); } } } } return(vars); }
public static IAnalysisResult GetValueByIndex(string exprText, int index, Genero4glAst ast, out IGeneroProject definingProject, out IProjectEntry projectEntry, out bool isDeferredFunction, FunctionProviderSearchMode searchInFunctionProvider = FunctionProviderSearchMode.NoSearch, bool isFunctionCallOrDefinition = false, bool getTypes = true, bool getVariables = true, bool getConstants = true) { isDeferredFunction = false; definingProject = null; projectEntry = null; //_functionProvider = functionProvider; //_databaseProvider = databaseProvider; //_programFileProvider = programFileProvider; AstNode containingNode = null; if (ast != null) { containingNode = GetContainingNode(ast.Body, index); ast.Body.SetNamespace(null); } IAnalysisResult res = null; int tmpIndex = 0; int bracketDepth = 0; bool doSearch = false; bool resetStartIndex = false; int startIndex = 0, endIndex = 0; bool noEndIndexSet = false; if (exprText == null) { return(null); } while (tmpIndex < exprText.Length) { if (resetStartIndex) { startIndex = tmpIndex; resetStartIndex = false; if (startIndex + 1 > exprText.Length) { break; } } doSearch = false; switch (exprText[tmpIndex]) { case '.': { if (bracketDepth == 0) { endIndex = tmpIndex - 1; if (endIndex >= startIndex) { // we have our 'piece' doSearch = true; } if (exprText[startIndex] == '.') { startIndex++; } } tmpIndex++; } break; case '[': if (noEndIndexSet) { noEndIndexSet = false; } else { if (bracketDepth == 0) { endIndex = tmpIndex - 1; } } bracketDepth++; tmpIndex++; break; case ']': { bracketDepth--; if (bracketDepth == 0) { if (exprText.Length <= tmpIndex + 1 || exprText[tmpIndex + 1] != '[') { // we have our first 'piece' doSearch = true; } else { noEndIndexSet = true; } } tmpIndex++; } break; default: { if (bracketDepth == 0 && (tmpIndex + 1 == exprText.Length)) { endIndex = tmpIndex; doSearch = true; } tmpIndex++; } break; } if (!doSearch) { continue; } // we can do our search var dotPiece = exprText.Substring(startIndex, (endIndex - startIndex) + 1); if (dotPiece.Contains('(')) { // remove the params piece int remIndex = dotPiece.IndexOf('('); dotPiece = dotPiece.Substring(0, remIndex); } bool lookForFunctions = isFunctionCallOrDefinition && (endIndex + 1 == exprText.Length); resetStartIndex = true; if (res != null) { if (ast != null) { var gmi = new GetMemberInput { Name = dotPiece, AST = ast, IsFunction = lookForFunctions }; IAnalysisResult tempRes = res.GetMember(gmi); if (gmi.DefiningProject != null && definingProject != gmi.DefiningProject) { definingProject = gmi.DefiningProject; } if (gmi.ProjectEntry != null && projectEntry != gmi.ProjectEntry) { projectEntry = gmi.ProjectEntry; } res = tempRes; if (tempRes == null) { res = null; break; } } else { res = null; break; } } else { IFunctionResult funcRes; if (!lookForFunctions) { if (SystemVariables.TryGetValue(dotPiece, out res) || SystemConstants.TryGetValue(dotPiece, out res) || SystemMacros.TryGetValue(dotPiece, out res)) { continue; } } else { if (SystemFunctions.TryGetValue(dotPiece, out funcRes)) { res = funcRes; continue; } if (ast != null && ast._functionProvider != null && ast._functionProvider.Name.Equals(dotPiece, StringComparison.OrdinalIgnoreCase)) { res = ast._functionProvider; continue; } } if (containingNode != null && containingNode is IFunctionResult) { IFunctionResult func = containingNode as IFunctionResult; if ((getVariables && func.Variables.TryGetValue(dotPiece, out res))) { continue; } if (!lookForFunctions) { // Check for local vars, types, and constants if ((getTypes && func.Types.TryGetValue(dotPiece, out res)) || (getConstants && func.Constants.TryGetValue(dotPiece, out res))) { continue; } List <Tuple <IAnalysisResult, IndexSpan> > limitedScopeVars; if ((getVariables && func.LimitedScopeVariables.TryGetValue(dotPiece, out limitedScopeVars))) { foreach (var item in limitedScopeVars) { if (item.Item2.IsInSpan(index)) { res = item.Item1; break; } } if (res != null) { continue; } } } } if (ast != null && ast.Body is IModuleResult) { IModuleResult mod = ast.Body as IModuleResult; if (!lookForFunctions) { // check for module vars, types, and constants (and globals defined in this module) if ((getVariables && (mod.Variables.TryGetValue(dotPiece, out res) || mod.GlobalVariables.TryGetValue(dotPiece, out res))) || (getTypes && (mod.Types.TryGetValue(dotPiece, out res) || mod.GlobalTypes.TryGetValue(dotPiece, out res))) || (getConstants && (mod.Constants.TryGetValue(dotPiece, out res) || mod.GlobalConstants.TryGetValue(dotPiece, out res)))) { continue; } // check for cursors in this module if (mod.Cursors.TryGetValue(dotPiece, out res)) { continue; } } else { // check for module functions if (mod.Functions.TryGetValue(dotPiece, out funcRes)) { // check for any function info collected at the project entry level, and update the function's documentation with that. if (ast._projEntry != null && ast._projEntry is IGeneroProjectEntry) { var commentInfo = (ast._projEntry as IGeneroProjectEntry).GetFunctionInfo(funcRes.Name); if (commentInfo != null) { funcRes.SetCommentDocumentation(commentInfo); } } res = funcRes; continue; } } } // TODO: this could probably be done more efficiently by having each GeneroAst load globals and functions into // dictionaries stored on the IGeneroProject, instead of in each project entry. // However, this does required more upkeep when changes occur. Will look into it... if (ast != null && ast.ProjectEntry != null && ast.ProjectEntry is IGeneroProjectEntry) { IGeneroProjectEntry genProj = ast.ProjectEntry as IGeneroProjectEntry; if (genProj.ParentProject != null && !genProj.FilePath.ToLower().EndsWith(".inc")) { bool found = false; foreach (var projEntry in genProj.ParentProject.ProjectEntries.Where(x => x.Value != genProj)) { if (projEntry.Value.Analysis != null && projEntry.Value.Analysis.Body != null) { projEntry.Value.Analysis.Body.SetNamespace(null); IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult; if (modRes != null) { if (!lookForFunctions) { // check global vars, types, and constants // TODO: need option to enable/disable legacy linking if ((getVariables && (modRes.Variables.TryGetValue(dotPiece, out res) || modRes.GlobalVariables.TryGetValue(dotPiece, out res))) || (getTypes && (modRes.Types.TryGetValue(dotPiece, out res) || modRes.GlobalTypes.TryGetValue(dotPiece, out res))) || (getConstants && (modRes.Constants.TryGetValue(dotPiece, out res) || modRes.GlobalConstants.TryGetValue(dotPiece, out res)))) { found = true; break; } // check for cursors in this module if (modRes.Cursors.TryGetValue(dotPiece, out res)) { found = true; break; } } else { // check project functions if (modRes.Functions.TryGetValue(dotPiece, out funcRes)) { if (funcRes.AccessModifier == AccessModifier.Public) { res = funcRes; found = true; break; } } } } } } if (found) { continue; } } } // check for classes GeneroPackage package; if (Packages.TryGetValue(dotPiece, out package)) { res = package; continue; } /* TODO: * Need to check for: * 1) Temp tables */ // Nothing found yet... // If our containing node is at the function or globals level, we need to go deeper if (containingNode != null && (containingNode is GlobalsNode || containingNode is FunctionBlockNode || containingNode is ReportBlockNode)) { containingNode = GetContainingNode(containingNode, index); } // check for record field if (containingNode != null && (containingNode is DefineNode || containingNode is TypeDefNode)) { containingNode = GetContainingNode(containingNode, index); if (containingNode != null && (containingNode is VariableDefinitionNode || containingNode is TypeDefinitionNode) && containingNode.Children.Count == 1 && containingNode.Children[containingNode.Children.Keys[0]] is TypeReference) { var typeRef = containingNode.Children[containingNode.Children.Keys[0]] as TypeReference; while (typeRef != null && typeRef.Children.Count == 1) { if (typeRef.Children[typeRef.Children.Keys[0]] is RecordDefinitionNode) { var recNode = typeRef.Children[typeRef.Children.Keys[0]] as RecordDefinitionNode; VariableDef recField; if (recNode.MemberDictionary.TryGetValue(exprText, out recField)) { res = recField; break; } else { recField = recNode.MemberDictionary.Where(x => x.Value.LocationIndex < index) .OrderByDescending(x => x.Value.LocationIndex) .Select(x => x.Value) .FirstOrDefault(); if (recField != null) { typeRef = recField.Type; } else { break; } } } else if (typeRef.Children[typeRef.Children.Keys[0]] is TypeReference) { typeRef = typeRef.Children[typeRef.Children.Keys[0]] as TypeReference; } else { break; } } } } // try an imported module if (ast != null && ast.Body is IModuleResult && ast.ProjectEntry != null && ast.ProjectEntry != null) { if ((ast.Body as IModuleResult).FglImports.Contains(dotPiece)) { // need to get the ast for the other project entry var refProjKVP = (ast.ProjectEntry as IGeneroProjectEntry).ParentProject.ReferencedProjects.Values.FirstOrDefault( x => { var fn = Path.GetFileNameWithoutExtension(x.Directory); return(fn?.Equals(dotPiece, StringComparison.OrdinalIgnoreCase) ?? false); }); if (refProjKVP is IAnalysisResult) { definingProject = refProjKVP; res = refProjKVP as IAnalysisResult; continue; } IAnalysisResult sysImportMod; // check the system imports if (SystemImportModules.TryGetValue(dotPiece, out sysImportMod)) { res = sysImportMod; continue; } } } if (!lookForFunctions) { // try include files var foundInclude = false; if (ast?.ProjectEntry != null) { foreach (var includeFile in ast.ProjectEntry.GetIncludedFiles()) { if (includeFile.Analysis?.Body is IModuleResult) { var mod = includeFile.Analysis.Body as IModuleResult; if ((getTypes && (mod.Types.TryGetValue(dotPiece, out res) || mod.GlobalTypes.TryGetValue(dotPiece, out res))) || (getConstants && (mod.Constants.TryGetValue(dotPiece, out res) || mod.GlobalConstants.TryGetValue(dotPiece, out res)))) { foundInclude = true; break; } } } } if (foundInclude) { continue; } if (ast?._databaseProvider != null) { res = ast._databaseProvider.GetTable(dotPiece); if (res != null) { continue; } } } // Only do a public function search if the dotPiece is the whole text we're searching for // I.e. no namespaces if (lookForFunctions && dotPiece == exprText) { if (searchInFunctionProvider == FunctionProviderSearchMode.Search) { if (res == null && ast?._functionProvider != null) { // check for the function name in the function provider var funcs = ast._functionProvider.GetFunction(dotPiece); if (funcs != null) { res = funcs.FirstOrDefault(); if (res != null) { continue; } } } } else if (searchInFunctionProvider == FunctionProviderSearchMode.Deferred) { isDeferredFunction = true; } } if (res == null) { break; } } } return(res); }
/// <summary> /// Gets information about the available signatures for the given expression. /// </summary> /// <param name="exprText">The expression to get signatures for.</param> /// <param name="index">The 0-based absolute index into the file.</param> public override IEnumerable <IFunctionResult> GetSignaturesByIndex(string exprText, int index, IReverseTokenizer revTokenizer, IFunctionInformationProvider functionProvider) { _functionProvider = functionProvider; // First see if we're in the process of defining a function List <MemberResult> dummyList; if (TryFunctionDefContext(index, revTokenizer, out dummyList)) { return(null); } /* * Need to check for: * 1) Functions within the current module * 2) Functions within the current project * 3) Public functions */ if (_body is IModuleResult) { _body.SetNamespace(null); // check for module vars, types, and constants (and globals defined in this module) IModuleResult mod = _body as IModuleResult; // check for module functions IFunctionResult funcRes; if (mod.Functions.TryGetValue(exprText, out funcRes)) { return(new IFunctionResult[1] { funcRes }); } } if (_projEntry != null && _projEntry is IGeneroProjectEntry) { IGeneroProjectEntry genProj = _projEntry as IGeneroProjectEntry; if (genProj.ParentProject != null && !genProj.FilePath.ToLower().EndsWith(".inc")) { foreach (var projEntry in genProj.ParentProject.ProjectEntries.Where(x => x.Value != genProj)) { if (projEntry.Value.Analysis != null && projEntry.Value.Analysis.Body != null) { projEntry.Value.Analysis.Body.SetNamespace(null); IModuleResult modRes = projEntry.Value.Analysis.Body as IModuleResult; if (modRes != null) { // check project functions IFunctionResult funcRes; if (modRes.Functions.TryGetValue(exprText, out funcRes)) { if (funcRes.AccessModifier == AccessModifier.Public) { return new IFunctionResult[1] { funcRes } } ; } } } } } } // Check for class methods IGeneroProject dummyProj; IProjectEntry dummyProjEntry; bool dummyDef; IAnalysisResult member = GetValueByIndex(exprText, index, _functionProvider, _databaseProvider, _programFileProvider, true, out dummyDef, out dummyProj, out dummyProjEntry); if (member is IFunctionResult) { return(new IFunctionResult[1] { member as IFunctionResult }); } else if (member is VariableDef && (member as VariableDef).Type != null) { var typeRef = (member as VariableDef).Type; if (typeRef.ResolvedType != null && typeRef.ResolvedType is TypeDefinitionNode) { var tdn = typeRef.ResolvedType as TypeDefinitionNode; if (tdn.TypeRef != null && tdn.TypeRef is FunctionTypeReference) { return(new IFunctionResult[1] { tdn.TypeRef as FunctionTypeReference }); } } } if (_functionProvider != null) { // check for the function name in the function provider var func = _functionProvider.GetFunction(exprText); if (func != null) { return(func); } } return(null); }
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); }
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); }
public static bool TryParseNode(Genero4glParser parser, out ConstructControlBlock 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 ConstructControlBlock(); bool result = true; node.StartIndex = parser.Token.Span.Start; 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(); if (parser.PeekToken(TokenKind.FieldKeyword)) { parser.NextToken(); node.Type = ConstructControlBlockType.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(); } } else if (parser.PeekToken(TokenKind.ConstructKeyword)) { parser.NextToken(); node.Type = ConstructControlBlockType.Construct; } else { parser.ReportSyntaxError("Unexpected token found in construct control block."); result = false; } break; } case TokenKind.OnKeyword: { parser.NextToken(); switch (parser.PeekToken().Kind) { case TokenKind.IdleKeyword: parser.NextToken(); node.Type = ConstructControlBlockType.Idle; // get the idle seconds ExpressionNode idleExpr; if (FglExpressionNode.TryGetExpressionNode(parser, out idleExpr)) { node.IdleSeconds = idleExpr; } else { parser.ReportSyntaxError("Invalid idle-seconds found in construct statement."); } break; case TokenKind.ActionKeyword: parser.NextToken(); node.Type = ConstructControlBlockType.Action; // get the action name FglNameExpression actionName; if (FglNameExpression.TryParseNode(parser, out actionName)) { node.ActionName = actionName; } else { parser.ReportSyntaxError("Invalid action-name found in construct statement."); } 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 construct statement."); } } break; case TokenKind.KeyKeyword: parser.NextToken(); node.Type = ConstructControlBlockType.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 construct control block."); } } else { parser.ReportSyntaxError("Expected left-paren in construct control block."); } break; default: parser.ReportSyntaxError("Unexpected token found in input control block."); //result = false; break; } break; } default: result = false; break; } if (result && node.StartIndex >= 0) { // get the dialog statements FglStatement inputStmt; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (ConstructDialogStatementFactory.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 == ConstructControlBlockType.None && node.Children.Count == 0) { result = false; } } return(result); }
public static bool TryParseNode(Genero4glParser parser, out IfStatement 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, ExpressionParsingOptions expressionOptions = null, HashSet <TokenKind> endKeywords = null) { node = null; bool result = false; if (parser.PeekToken(TokenKind.IfKeyword)) { result = true; node = new IfStatement(); parser.NextToken(); node.StartIndex = parser.Token.Span.Start; ExpressionNode conditionExpr; if (!FglExpressionNode.TryGetExpressionNode(parser, out conditionExpr, new List <TokenKind> { TokenKind.ThenKeyword }, expressionOptions)) { parser.ReportSyntaxError("An if statement must have a condition expression."); } else { node.ConditionExpression = conditionExpr; } if (parser.PeekToken(TokenKind.ThenKeyword)) { parser.NextToken(); node.DecoratorEnd = parser.Token.Span.End; HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.IfKeyword); IfBlockContentsNode ifBlock; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); if (IfBlockContentsNode.TryParseNode(parser, out ifBlock, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, expressionOptions, newEndKeywords)) { if (ifBlock != null) { node.Children.Add(ifBlock.StartIndex, ifBlock); } } if (parser.PeekToken(TokenKind.ElseKeyword)) { parser.NextToken(); ElseBlockContentsNode elseBlock; if (ElseBlockContentsNode.TryParseNode(parser, out elseBlock, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, expressionOptions, newEndKeywords)) { if (elseBlock != null) { node.Children.Add(elseBlock.StartIndex, elseBlock); // Add the span of "else" to the additional decorators node.AdditionalDecoratorRanges.Add(elseBlock.StartIndex, elseBlock.StartIndex + 4); } } } prepStatementBinders.RemoveAt(0); if (!(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.IfKeyword, 2))) { parser.ReportSyntaxError("An if statement must be terminated with \"end if\"."); } else { parser.NextToken(); // advance to the 'end' token parser.NextToken(); // advance to the 'if' token node.EndIndex = parser.Token.Span.End; } } else { parser.ReportSyntaxError("An if statement must have a \"then\" keyword prior to containing code."); } } 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); }
public static bool TryParseNode(Genero4glParser parser, out CreateStatement node, IModuleResult containingModule) { node = null; bool result = true; if (parser.PeekToken(TokenKind.CreateKeyword)) { parser.NextToken(); switch (parser.PeekToken().Kind) { case TokenKind.SequenceKeyword: CreateSequenceStatement sequenceNode; result = CreateSequenceStatement.TryParseNode(parser, out sequenceNode); node = sequenceNode; break; case TokenKind.TableKeyword: case TokenKind.TempKeyword: CreateTableStatement tableNode; result = CreateTableStatement.TryParseNode(parser, out tableNode, containingModule); node = tableNode; break; default: result = false; break; } } return(result); }
public static bool TryParseNode(Genero4glParser parser, out DisplayControlBlock node, IModuleResult containingModule, bool allowNonControlBlocks, 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 DisplayControlBlock(); bool result = true; node.KeyNameList = new List <VirtualKey>(); bool isDragAndDrop = false; 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.DisplayKeyword)) { parser.NextToken(); node.Type = DisplayControlBlockType.Display; } else if (parser.PeekToken(TokenKind.RowKeyword)) { parser.NextToken(); node.Type = DisplayControlBlockType.Row; } else { parser.ReportSyntaxError("Unexpected keyword found in display control block."); result = false; } break; } case TokenKind.OnKeyword: { parser.NextToken(); node.StartIndex = parser.Token.Span.Start; switch (parser.PeekToken().Kind) { case TokenKind.IdleKeyword: parser.NextToken(); node.Type = DisplayControlBlockType.Idle; // get the idle seconds ExpressionNode idleExpr; if (FglExpressionNode.TryGetExpressionNode(parser, out idleExpr)) { node.IdleSeconds = idleExpr; } else { parser.ReportSyntaxError("Invalid idle-seconds found in display array statement."); } break; case TokenKind.TimerKeyword: parser.NextToken(); node.Type = DisplayControlBlockType.Timer; // get the timer seconds ExpressionNode timerExpr; if (FglExpressionNode.TryGetExpressionNode(parser, out timerExpr)) { node.TimerSeconds = timerExpr; } else { parser.ReportSyntaxError("Invalid timer-seconds found in display array statement."); } break; case TokenKind.ActionKeyword: parser.NextToken(); node.Type = DisplayControlBlockType.Action; // get the action name FglNameExpression actionName; if (FglNameExpression.TryParseNode(parser, out actionName)) { node.ActionName = actionName; } else { parser.ReportSyntaxError("Invalid action-name found in display array statement."); } GetActionAttributesDisplayArray(parser); break; case TokenKind.KeyKeyword: parser.NextToken(); node.Type = DisplayControlBlockType.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 display array block."); } } else { parser.ReportSyntaxError("Expected left-paren in display array block."); } break; case TokenKind.AppendKeyword: node.Type = DisplayControlBlockType.Append; parser.NextToken(); GetActionAttributesListmodTriggers(parser); break; case TokenKind.InsertKeyword: node.Type = DisplayControlBlockType.Insert; parser.NextToken(); GetActionAttributesListmodTriggers(parser); break; case TokenKind.UpdateKeyword: node.Type = DisplayControlBlockType.Update; parser.NextToken(); GetActionAttributesListmodTriggers(parser); break; case TokenKind.DeleteKeyword: node.Type = DisplayControlBlockType.Delete; parser.NextToken(); GetActionAttributesListmodTriggers(parser); break; case TokenKind.ExpandKeyword: node.Type = DisplayControlBlockType.Expand; parser.NextToken(); if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); FglNameExpression rowInd; if (FglNameExpression.TryParseNode(parser, out rowInd)) { node.RowIndex = rowInd; } else { parser.ReportSyntaxError("Invalid row-index found in display array statement."); } if (parser.PeekToken(TokenKind.RightParenthesis)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expected right-paren in display array statement."); } } else { parser.ReportSyntaxError("Expected left-paren in display array statement."); } break; case TokenKind.CollapseKeyword: node.Type = DisplayControlBlockType.Collapse; parser.NextToken(); if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); FglNameExpression rowInd1; if (FglNameExpression.TryParseNode(parser, out rowInd1)) { node.RowIndex = rowInd1; } else { parser.ReportSyntaxError("Invalid row-index found in display array statement."); } if (parser.PeekToken(TokenKind.RightParenthesis)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expected right-paren in display array statement."); } } else { parser.ReportSyntaxError("Expected left-paren in display array statement."); } break; case TokenKind.Drag_EnterKeyword: node.Type = DisplayControlBlockType.DragEnter; parser.NextToken(); isDragAndDrop = true; break; case TokenKind.Drag_FinishKeyword: case TokenKind.Drag_FinishedKeyword: node.Type = DisplayControlBlockType.DragFinish; parser.NextToken(); isDragAndDrop = true; break; case TokenKind.Drag_OverKeyword: node.Type = DisplayControlBlockType.DragOver; parser.NextToken(); isDragAndDrop = true; break; case TokenKind.Drag_StartKeyword: node.Type = DisplayControlBlockType.DragStart; parser.NextToken(); isDragAndDrop = true; break; case TokenKind.DropKeyword: node.Type = DisplayControlBlockType.Drop; parser.NextToken(); isDragAndDrop = true; break; default: parser.ReportSyntaxError("Unexpected token found in input control block."); result = false; break; } break; } default: if (!allowNonControlBlocks) { result = false; } else { node.StartIndex = parser.Token.Span.Start; } break; } if (result && node.StartIndex >= 0) { node.DecoratorEnd = parser.Token.Span.End; if (isDragAndDrop) { if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); FglNameExpression keyName; if (FglNameExpression.TryParseNode(parser, out keyName)) { node.DragAndDropObject = keyName; } else { parser.ReportSyntaxError("Invalid drag-and-drop object name found in display array statement."); } if (parser.PeekToken(TokenKind.RightParenthesis)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expected right-paren in input control block."); } } else { parser.ReportSyntaxError("Expected left-paren in input control block."); } } // get the dialog statements FglStatement dispStmt; prepStatementBinders.Insert(0, node.BindPrepareCursorFromIdentifier); while (DisplayStatementFactory.TryGetStatement(parser, out dispStmt, isArray, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, endKeywords) && dispStmt != null) { node.Children.Add(dispStmt.StartIndex, dispStmt); node.EndIndex = dispStmt.EndIndex; } prepStatementBinders.RemoveAt(0); if (node.Type == DisplayControlBlockType.None && node.Children.Count == 0) { result = false; } } return(result); }
public static bool TryParseNode(Genero4glParser parser, out TryCatchStatement defNode, 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) { defNode = null; bool result = false; if (parser.PeekToken(TokenKind.TryKeyword)) { result = true; defNode = new TryCatchStatement(); parser.NextToken(); defNode.StartIndex = parser.Token.Span.Start; defNode.DecoratorEnd = parser.Token.Span.End; HashSet <TokenKind> newEndKeywords = new HashSet <TokenKind>(); if (endKeywords != null) { newEndKeywords.AddRange(endKeywords); } newEndKeywords.Add(TokenKind.TryKeyword); prepStatementBinders.Insert(0, defNode.BindPrepareCursorFromIdentifier); TryBlock tryBlock; if (TryBlock.TryParseNode(parser, out tryBlock, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, newEndKeywords) && tryBlock != null) { defNode.Children.Add(tryBlock.StartIndex, tryBlock); } if (parser.PeekToken(TokenKind.CatchKeyword)) { parser.NextToken(); CatchBlock catchBlock; if (CatchBlock.TryParseNode(parser, out catchBlock, containingModule, prepStatementBinders, returnStatementBinder, limitedScopeVariableAdder, validExitKeywords, contextStatementFactories, newEndKeywords) && catchBlock != null) { defNode.Children.Add(catchBlock.StartIndex, catchBlock); // add the catch block to the additional decorators defNode.AdditionalDecoratorRanges.Add(catchBlock.StartIndex, catchBlock.StartIndex + 5); } } prepStatementBinders.RemoveAt(0); if (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.TryKeyword, 2)) { parser.NextToken(); parser.NextToken(); } else { parser.ReportSyntaxError("Invalid end of try-catch block found."); } defNode.EndIndex = parser.Token.Span.End; } return(result); }