public static bool TryParseNode(Genero4glParser parser, out ModuleNode defNode) { defNode = new ModuleNode(); if (!string.IsNullOrWhiteSpace(parser.Filename)) { defNode.ProgramName = Path.GetFileName(Path.GetDirectoryName(parser.Filename)); } NodesProcessed processed = NodesProcessed.None; while (!parser.PeekToken(TokenKind.EndOfFile)) { if (CheckForPreprocessorNode(parser, defNode)) { continue; } CompilerOptionsNode compOptionsNode; if (CompilerOptionsNode.TryParseNode(parser, out compOptionsNode) && compOptionsNode != null) { if (processed == NodesProcessed.None) { defNode.Children.Add(compOptionsNode.StartIndex, compOptionsNode); } else { parser.ReportSyntaxError("Compiler options statement found in incorrect position."); } } if (processed == NodesProcessed.None) { processed = NodesProcessed.CompilerOption; } if (CheckForPreprocessorNode(parser, defNode)) { continue; } ImportModuleNode importNode; if (ImportModuleNode.TryParseNode(parser, out importNode) && importNode != null) { if (processed == NodesProcessed.CompilerOption) { if (!defNode.Children.ContainsKey(importNode.StartIndex)) { defNode.Children.Add(importNode.StartIndex, importNode); if (!string.IsNullOrWhiteSpace(importNode.ImportName)) { if (importNode.ImportType == ImportModuleType.C) { defNode.CExtensionImports.Add(importNode.ImportName); } else if (importNode.ImportType == ImportModuleType.Java) { defNode.JavaImports.Add(importNode.ImportName); } else { defNode.FglImports.Add(importNode.ImportName); } } } continue; } else { parser.ReportSyntaxError("Import statement found in incorrect position."); } } if (processed == NodesProcessed.CompilerOption) { processed = NodesProcessed.Imports; } if (CheckForPreprocessorNode(parser, defNode)) { continue; } SchemaSpecificationNode schemaNode; if (SchemaSpecificationNode.TryParseDefine(parser, out schemaNode) && schemaNode != null) { if (processed == NodesProcessed.Imports) { if (!defNode.Children.ContainsKey(schemaNode.StartIndex)) { defNode.Children.Add(schemaNode.StartIndex, schemaNode); } } else { parser.ReportSyntaxError("Schema statement found in incorrect position."); } } if (processed == NodesProcessed.Imports) { processed = NodesProcessed.SchemaSpec; } if (CheckForPreprocessorNode(parser, defNode)) { continue; } GlobalsNode globalNode; if (GlobalsNode.TryParseNode(parser, out globalNode) && globalNode != null) { if (processed == NodesProcessed.SchemaSpec || processed == NodesProcessed.MemberDefinitions) { defNode.Children.Add(globalNode.StartIndex, globalNode); foreach (var cGlobKVP in globalNode.Constants) { if (!defNode.GlobalConstants.ContainsKey(cGlobKVP.Key)) { defNode.GlobalConstants.Add(cGlobKVP); } else { parser.ReportSyntaxError(cGlobKVP.Value.LocationIndex, cGlobKVP.Value.LocationIndex + cGlobKVP.Value.Name.Length, string.Format("Global constant {0} defined more than once.", cGlobKVP.Key), Severity.Error); } } foreach (var tGlobKVP in globalNode.Types) { if (!defNode.GlobalTypes.ContainsKey(tGlobKVP.Key)) { defNode.GlobalTypes.Add(tGlobKVP); } else { parser.ReportSyntaxError(tGlobKVP.Value.LocationIndex, tGlobKVP.Value.LocationIndex + tGlobKVP.Value.Name.Length, string.Format("Global type {0} defined more than once.", tGlobKVP.Key), Severity.Error); } } foreach (var vGlobKVP in globalNode.Variables) { if (!defNode.GlobalVariables.ContainsKey(vGlobKVP.Key)) { defNode.GlobalVariables.Add(vGlobKVP); } else { parser.ReportSyntaxError(vGlobKVP.Value.LocationIndex, vGlobKVP.Value.LocationIndex + vGlobKVP.Value.Name.Length, string.Format("Global variable {0} defined more than once.", vGlobKVP.Key), Severity.Error); } } continue; } else { parser.ReportSyntaxError("Globals statement found in incorrect position."); } } if (processed == NodesProcessed.SchemaSpec) { processed = NodesProcessed.MemberDefinitions; } if (CheckForPreprocessorNode(parser, defNode)) { continue; } bool matchedBreakSequence = false; ConstantDefNode constNode; List <List <TokenKind> > breakSequences = new List <List <TokenKind> >() { new List <TokenKind> { TokenKind.GlobalsKeyword }, new List <TokenKind> { TokenKind.PublicKeyword }, new List <TokenKind> { TokenKind.PrivateKeyword }, new List <TokenKind> { TokenKind.ConstantKeyword }, new List <TokenKind> { TokenKind.DefineKeyword }, new List <TokenKind> { TokenKind.TypeKeyword }, new List <TokenKind> { TokenKind.FunctionKeyword }, new List <TokenKind> { TokenKind.MainKeyword }, new List <TokenKind> { TokenKind.ReportKeyword } }; if (ConstantDefNode.TryParseNode(parser, out constNode, out matchedBreakSequence, breakSequences) && constNode != null) { if (processed == NodesProcessed.SchemaSpec || processed == NodesProcessed.MemberDefinitions) { defNode.Children.Add(constNode.StartIndex, constNode); foreach (var def in constNode.GetDefinitions()) { def.Scope = "module constant"; if (!defNode.Constants.ContainsKey(def.Name)) { defNode.Constants.Add(def.Name, def); } else { parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Module constant {0} defined more than once.", def.Name), Severity.Error); } } continue; } else { parser.ReportSyntaxError("Constant definition found in incorrect position."); } } if (processed == NodesProcessed.SchemaSpec) { processed = NodesProcessed.MemberDefinitions; } if (CheckForPreprocessorNode(parser, defNode)) { continue; } TypeDefNode typeNode; if (TypeDefNode.TryParseNode(parser, out typeNode, out matchedBreakSequence, breakSequences) && typeNode != null) { if (processed == NodesProcessed.SchemaSpec || processed == NodesProcessed.MemberDefinitions) { if (!defNode.Children.ContainsKey(typeNode.StartIndex)) { defNode.Children.Add(typeNode.StartIndex, typeNode); } foreach (var def in typeNode.GetDefinitions()) { def.Scope = "module type"; if (!defNode.Types.ContainsKey(def.Name)) { defNode.Types.Add(def.Name, def); } else { parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Module type {0} defined more than once.", def.Name), Severity.Error); } } continue; } else { parser.ReportSyntaxError("Type definition found in incorrect position."); } } if (processed == NodesProcessed.SchemaSpec) { processed = NodesProcessed.MemberDefinitions; } if (CheckForPreprocessorNode(parser, defNode)) { continue; } DefineNode defineNode; if (DefineNode.TryParseDefine(parser, out defineNode, out matchedBreakSequence, breakSequences) && defineNode != null) { if (processed == NodesProcessed.SchemaSpec || processed == NodesProcessed.MemberDefinitions) { defNode.Children.Add(defineNode.StartIndex, defineNode); foreach (var def in defineNode.GetDefinitions()) { foreach (var vardef in def.VariableDefinitions) { vardef.Scope = "module variable"; vardef.SetIsPublic(defineNode.AccessModifier == AccessModifier.Public); if (!defNode.Variables.ContainsKey(vardef.Name)) { defNode.Variables.Add(vardef.Name, vardef); } else { parser.ReportSyntaxError(vardef.LocationIndex, vardef.LocationIndex + vardef.Name.Length, string.Format("Module variable {0} defined more than once.", vardef.Name), Severity.Error); } } } continue; } else { parser.ReportSyntaxError("Variable definition found in incorrect position."); } } if (processed == NodesProcessed.SchemaSpec) { processed = NodesProcessed.MemberDefinitions; } if (CheckForPreprocessorNode(parser, defNode)) { continue; } MainBlockNode mainBlock; if (MainBlockNode.TryParseNode(parser, out mainBlock, defNode) && mainBlock != null) { if (processed == NodesProcessed.MemberDefinitions) { defNode.Children.Add(mainBlock.StartIndex, mainBlock); defNode.Functions.Add(mainBlock.Name, mainBlock); foreach (var cursor in mainBlock.Children.Values.Where(x => x is PrepareStatement || x is DeclareStatement)) { IAnalysisResult curRes = cursor as IAnalysisResult; if (!defNode.Cursors.ContainsKey(curRes.Name)) { defNode.Cursors.Add(curRes.Name, curRes); } } } else { parser.ReportSyntaxError("Main block found in incorrect position."); } } if (processed == NodesProcessed.MemberDefinitions) { processed = NodesProcessed.Main; } if (CheckForPreprocessorNode(parser, defNode)) { continue; } FunctionBlockNode funcNode; ReportBlockNode repNode; DeclarativeDialogBlock dialogNode; int dummy; if (FunctionBlockNode.TryParseNode(parser, out funcNode, out dummy, defNode) && funcNode != null) { defNode.Children.Add(funcNode.StartIndex, funcNode); funcNode.Scope = "function"; if (string.IsNullOrWhiteSpace(funcNode.Name)) { parser.ReportSyntaxError(funcNode.LocationIndex, funcNode.LocationIndex, "Invalid function definition found."); } else if (!defNode.Functions.ContainsKey(funcNode.Name)) { defNode.Functions.Add(funcNode.Name, funcNode); } else { parser.ReportSyntaxError(funcNode.LocationIndex, funcNode.LocationIndex + funcNode.Name.Length, string.Format("Function {0} defined more than once.", funcNode.Name), Severity.Error); } } else if (ReportBlockNode.TryParseNode(parser, out repNode, defNode) && repNode != null) { defNode.Children.Add(repNode.StartIndex, repNode); repNode.Scope = "report"; if (string.IsNullOrWhiteSpace(repNode.Name)) { parser.ReportSyntaxError(repNode.LocationIndex, repNode.LocationIndex, "Invalid report definition found."); } else if (!defNode.Functions.ContainsKey(repNode.Name)) { defNode.Functions.Add(repNode.Name, repNode); } else { parser.ReportSyntaxError(repNode.LocationIndex, repNode.LocationIndex + repNode.Name.Length, string.Format("Report {0} defined more than once.", repNode.Name), Severity.Error); } } else if (DeclarativeDialogBlock.TryParseNode(parser, out dialogNode, defNode) && dialogNode != null) { defNode.Children.Add(dialogNode.StartIndex, dialogNode); dialogNode.Scope = "dialog"; if (string.IsNullOrWhiteSpace(dialogNode.Name)) { parser.ReportSyntaxError(dialogNode.LocationIndex, dialogNode.LocationIndex, "Invalid declarative dialog definition found."); } else if (!defNode.Functions.ContainsKey(dialogNode.Name)) { defNode.Functions.Add(dialogNode.Name, dialogNode); } else { parser.ReportSyntaxError(dialogNode.LocationIndex, dialogNode.LocationIndex + dialogNode.Name.Length, string.Format("Declarative dialog {0} defined more than once.", dialogNode.Name), Severity.Error); } } else { parser.NextToken(); } } if (defNode.Children.Count > 0) { defNode.StartIndex = defNode.Children[defNode.Children.Keys[0]].StartIndex; defNode.EndIndex = defNode.Children[defNode.Children.Keys[defNode.Children.Count - 1]].EndIndex; defNode.IsComplete = true; } return(true); }
public static bool TryParseNode(Genero4glParser parser, out FunctionBlockNode defNode, out int bufferPosition, IModuleResult containingModule, bool abbreviatedParse = false, bool advanceOnEnd = true) { bufferPosition = 0; defNode = 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.FunctionKeyword, lookAheadBy)) { result = true; defNode = new FunctionBlockNode(); if (accMod.HasValue) { parser.NextToken(); defNode.AccessModifier = accMod.Value; defNode.StartIndex = parser.Token.Span.Start; } else { defNode.AccessModifier = AccessModifier.Public; } parser.NextToken(); // move past the Function keyword if (!accMod.HasValue) { defNode.StartIndex = parser.Token.Span.Start; } // get the name if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { parser.NextToken(); defNode.Name = parser.Token.Token.Value.ToString(); defNode.LocationIndex = parser.Token.Span.Start; defNode.DecoratorEnd = parser.Token.Span.End; } else { parser.ReportSyntaxError("A function must have a name."); } if (!parser.PeekToken(TokenKind.LeftParenthesis)) { parser.ReportSyntaxError("A function must specify zero or more parameters in the form: ([param1][,...])"); } else { parser.NextToken(); } bool paramsParsed = false; if (parser.LanguageVersion >= GeneroLanguageVersion.V310) { while (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { var paramName = parser.PeekTokenWithSpan(); string errMsg; if (!defNode.AddArgument(paramName, out errMsg)) { parser.ReportSyntaxError(errMsg); } // try parsing the parameters as variable definitions VariableDefinitionNode varDefNode = null; if (VariableDefinitionNode.TryParseNode(parser, out varDefNode, defNode.BindArgument, false, false)) { defNode.Children.Add(varDefNode.StartIndex, varDefNode); foreach (var vardef in varDefNode.VariableDefinitions) { vardef.Scope = "local variable"; if (!defNode.Variables.ContainsKey(vardef.Name)) { defNode.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); } } paramsParsed = true; } if (parser.PeekToken(TokenKind.Comma)) { parser.NextToken(); } } } if (!paramsParsed) { // get the parameters while (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { parser.NextToken(); string errMsg; if (!defNode.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 function must specify zero or more parameters in the form: ([param1][,...])"); } else { parser.NextToken(); } if (parser.LanguageVersion >= GeneroLanguageVersion.V310) { ReturnsStatement returnsStatement; if (ReturnsStatement.TryParseNode(parser, out returnsStatement)) { defNode._explicitReturns = new List <TypeReference>(); foreach (var ret in returnsStatement.ReturnTypes) { defNode._explicitReturns.Add(ret); } } } List <List <TokenKind> > breakSequences = new List <List <TokenKind> >(Genero4glAst.ValidStatementKeywords .Where(x => x != TokenKind.EndKeyword && x != TokenKind.FunctionKeyword) .Select(x => new List <TokenKind> { x })) { new List <TokenKind> { TokenKind.EndKeyword, TokenKind.FunctionKeyword } }; List <TokenKind> validExits = new List <TokenKind> { TokenKind.ProgramKeyword }; HashSet <TokenKind> endKeywords = new HashSet <TokenKind> { TokenKind.FunctionKeyword }; // try to parse one or more declaration statements while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.FunctionKeyword, 2))) { DefineNode defineNode; TypeDefNode typeNode; ConstantDefNode constNode; bool matchedBreakSequence = false; switch (parser.PeekToken().Kind) { case TokenKind.TypeKeyword: { if (TypeDefNode.TryParseNode(parser, out typeNode, out matchedBreakSequence, breakSequences) && typeNode != null) { defNode.Children.Add(typeNode.StartIndex, typeNode); foreach (var def in typeNode.GetDefinitions()) { def.Scope = "local type"; if (!defNode.Types.ContainsKey(def.Name)) { defNode.Types.Add(def.Name, def); } else { parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Type {0} defined more than once.", def.Name), Severity.Error); } } } break; } case TokenKind.ConstantKeyword: { if (ConstantDefNode.TryParseNode(parser, out constNode, out matchedBreakSequence, breakSequences) && constNode != null) { defNode.Children.Add(constNode.StartIndex, constNode); foreach (var def in constNode.GetDefinitions()) { def.Scope = "local constant"; if (!defNode.Constants.ContainsKey(def.Name)) { defNode.Constants.Add(def.Name, def); } else { parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Constant {0} defined more than once.", def.Name), Severity.Error); } } } break; } case TokenKind.DefineKeyword: { if (DefineNode.TryParseDefine(parser, out defineNode, out matchedBreakSequence, breakSequences, defNode.BindArgument) && defineNode != null) { defNode.Children.Add(defineNode.StartIndex, defineNode); foreach (var def in defineNode.GetDefinitions()) { foreach (var vardef in def.VariableDefinitions) { vardef.Scope = "local variable"; if (!defNode.Variables.ContainsKey(vardef.Name)) { defNode.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); } } } } break; } default: { FglStatement statement; List <Func <PrepareStatement, bool> > prepBinders = new List <Func <PrepareStatement, bool> >(); prepBinders.Add(defNode.BindPrepareCursorFromIdentifier); if (parser.StatementFactory.TryParseNode(parser, out statement, containingModule, prepBinders, defNode.StoreReturnStatement, defNode.AddLimitedScopeVariable, abbreviatedParse, validExits, null, null, endKeywords)) { AstNode4gl stmtNode = statement as AstNode4gl; if (stmtNode != null && !defNode.Children.ContainsKey(stmtNode.StartIndex)) { defNode.Children.Add(stmtNode.StartIndex, stmtNode); } continue; } break; } } if (parser.PeekToken(TokenKind.EndOfFile) || (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.FunctionKeyword, 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(); } } if (!parser.PeekToken(TokenKind.EndOfFile)) { parser.NextToken(); if (parser.PeekToken(TokenKind.FunctionKeyword)) { var tokSpan = parser.PeekTokenWithSpan(); bufferPosition = tokSpan.BufferPosition + tokSpan.Span.Length; if (advanceOnEnd) { parser.NextToken(); } defNode.EndIndex = parser.Token.Span.End; defNode.IsComplete = true; } else { parser.ReportSyntaxError(parser.Token.Span.Start, parser.Token.Span.End, "Invalid end of function definition."); } } else { parser.ReportSyntaxError("Unexpected end of function definition"); } } return(result); }
public static bool TryParseNode(Genero4glParser parser, out GlobalsNode defNode) { defNode = null; bool result = false; if (parser.PeekToken(TokenKind.GlobalsKeyword)) { result = true; parser.NextToken(); defNode = new GlobalsNode(); defNode.StartIndex = parser.Token.Span.Start; var tok = parser.PeekToken(); if (Tokenizer.GetTokenInfo(tok).Category == TokenCategory.StringLiteral) { parser.NextToken(); defNode.GlobalsFilename = parser.Token.Token.Value.ToString(); } else { List <List <TokenKind> > breakSequences = new List <List <TokenKind> >() { new List <TokenKind> { TokenKind.EndKeyword, TokenKind.GlobalsKeyword }, new List <TokenKind> { TokenKind.ConstantKeyword }, new List <TokenKind> { TokenKind.DefineKeyword }, new List <TokenKind> { TokenKind.TypeKeyword } }; // try to parse one or more declaration statements while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.GlobalsKeyword, 2))) { DefineNode defineNode; TypeDefNode typeNode; ConstantDefNode constNode; bool matchedBreakSequence = false; switch (parser.PeekToken().Kind) { case TokenKind.TypeKeyword: { var bsList = new List <List <TokenKind> >(breakSequences); if (TypeDefNode.TryParseNode(parser, out typeNode, out matchedBreakSequence, breakSequences) && typeNode != null) { defNode.Children.Add(typeNode.StartIndex, typeNode); foreach (var def in typeNode.GetDefinitions()) { def.Scope = "global type"; if (!defNode.Types.ContainsKey(def.Name)) { defNode.Types.Add(def.Name, def); } else { parser.ReportSyntaxError(string.Format("Global type {0} is defined more than once.", def.Name), Severity.Error); } } } break; } case TokenKind.ConstantKeyword: { if (ConstantDefNode.TryParseNode(parser, out constNode, out matchedBreakSequence, breakSequences) && constNode != null) { defNode.Children.Add(constNode.StartIndex, constNode); foreach (var def in constNode.GetDefinitions()) { def.Scope = "global constant"; if (!defNode.Constants.ContainsKey(def.Name)) { defNode.Constants.Add(def.Name, def); } else { parser.ReportSyntaxError(string.Format("Global constant {0} is defined more than once.", def.Name), Severity.Error); } } } break; } case TokenKind.DefineKeyword: { if (DefineNode.TryParseDefine(parser, out defineNode, out matchedBreakSequence, breakSequences) && defineNode != null) { defNode.Children.Add(defineNode.StartIndex, defineNode); foreach (var def in defineNode.GetDefinitions()) { foreach (var vardef in def.VariableDefinitions) { vardef.Scope = "global variable"; if (!defNode.Variables.ContainsKey(vardef.Name)) { defNode.Variables.Add(vardef.Name, vardef); } else { parser.ReportSyntaxError(vardef.LocationIndex, (vardef.LocationIndex + vardef.Name.Length), string.Format("Global variable {0} is defined more than once.", vardef.Name), Severity.Error); } } } } 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(); } } if (!parser.PeekToken(TokenKind.EndOfFile)) { parser.NextToken(); if (parser.PeekToken(TokenKind.GlobalsKeyword)) { parser.NextToken(); defNode.EndIndex = parser.Token.Span.End; defNode.IsComplete = true; } else { parser.ReportSyntaxError(parser.Token.Span.Start, parser.Token.Span.End, "Invalid end of globals definition."); } } else { parser.ReportSyntaxError("Unexpected end of globals definition"); } } } return(result); }
public static bool TryParseNode(Genero4glParser parser, out ReportBlockNode defNode, IModuleResult containingModule) { defNode = 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.ReportKeyword, lookAheadBy)) { result = true; defNode = new ReportBlockNode(); if (accMod.HasValue) { parser.NextToken(); defNode.AccessModifier = accMod.Value; } else { defNode.AccessModifier = AccessModifier.Public; } parser.NextToken(); // move past the Function keyword defNode.StartIndex = parser.Token.Span.Start; defNode.OrderVarNames = new List <FglNameExpression>(); // get the name if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { parser.NextToken(); defNode.Name = parser.Token.Token.Value.ToString(); defNode.LocationIndex = parser.Token.Span.Start; defNode.DecoratorEnd = parser.Token.Span.End; } else { parser.ReportSyntaxError("A report must have a name."); } if (!parser.PeekToken(TokenKind.LeftParenthesis)) { parser.ReportSyntaxError("A report 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 (!defNode.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 report must specify zero or more parameters in the form: ([param1][,...])"); } else { parser.NextToken(); } List <List <TokenKind> > breakSequences = new List <List <TokenKind> >(Genero4glAst.ValidStatementKeywords .Where(x => x != TokenKind.EndKeyword && x != TokenKind.ReportKeyword) .Select(x => new List <TokenKind> { x })) { new List <TokenKind> { TokenKind.EndKeyword, TokenKind.ReportKeyword }, new List <TokenKind> { TokenKind.OutputKeyword }, new List <TokenKind> { TokenKind.OrderKeyword }, new List <TokenKind> { TokenKind.FormatKeyword } }; while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ReportKeyword, 2))) { DefineNode defineNode; TypeDefNode typeNode; ConstantDefNode constNode; bool matchedBreakSequence = false; bool inDefSection = true; switch (parser.PeekToken().Kind) { case TokenKind.TypeKeyword: { if (TypeDefNode.TryParseNode(parser, out typeNode, out matchedBreakSequence, breakSequences) && typeNode != null) { defNode.Children.Add(typeNode.StartIndex, typeNode); foreach (var def in typeNode.GetDefinitions()) { def.Scope = "local type"; if (!defNode.Types.ContainsKey(def.Name)) { defNode.Types.Add(def.Name, def); } else { parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Type {0} defined more than once.", def.Name), Severity.Error); } } } break; } case TokenKind.ConstantKeyword: { if (ConstantDefNode.TryParseNode(parser, out constNode, out matchedBreakSequence, breakSequences) && constNode != null) { defNode.Children.Add(constNode.StartIndex, constNode); foreach (var def in constNode.GetDefinitions()) { def.Scope = "local constant"; if (!defNode.Constants.ContainsKey(def.Name)) { defNode.Constants.Add(def.Name, def); } else { parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Constant {0} defined more than once.", def.Name), Severity.Error); } } } break; } case TokenKind.DefineKeyword: { if (DefineNode.TryParseDefine(parser, out defineNode, out matchedBreakSequence, breakSequences, defNode.BindArgument) && defineNode != null) { defNode.Children.Add(defineNode.StartIndex, defineNode); foreach (var def in defineNode.GetDefinitions()) { foreach (var vardef in def.VariableDefinitions) { vardef.Scope = "local variable"; if (!defNode.Variables.ContainsKey(vardef.Name)) { defNode.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); } } } } break; } default: inDefSection = false; break; } if (!inDefSection) { break; } } if (parser.PeekToken(TokenKind.OutputKeyword)) { parser.NextToken(); bool isValid = true; ExpressionNode expr; while (isValid) { if (parser.PeekToken(TokenKind.ReportKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.ToKeyword)) { parser.NextToken(); switch (parser.PeekToken().Kind) { case TokenKind.ScreenKeyword: case TokenKind.PrinterKeyword: parser.NextToken(); break; case TokenKind.FileKeyword: parser.NextToken(); if (FglExpressionNode.TryGetExpressionNode(parser, out expr)) { defNode.OutputFilename = expr; } else { parser.ReportSyntaxError("Invalid filename found in report."); } break; case TokenKind.PipeKeyword: parser.NextToken(); if (FglExpressionNode.TryGetExpressionNode(parser, out expr)) { defNode.OutputProgram = expr; } else { parser.ReportSyntaxError("Invalid program name found in report."); } if (parser.PeekToken(TokenKind.InKeyword)) { parser.NextToken(); if ((parser.PeekToken(TokenKind.FormKeyword) || parser.PeekToken(TokenKind.LineKeyword)) && parser.PeekToken(TokenKind.ModeKeyword, 2)) { parser.NextToken(); parser.NextToken(); } else { parser.ReportSyntaxError("Expected \"form mode\" or \"line mode\" in report."); } } break; default: if (FglExpressionNode.TryGetExpressionNode(parser, out expr)) { defNode.OutputFilename = expr; } else { parser.ReportSyntaxError("Invalid filename found in report."); } break; } } else { parser.ReportSyntaxError("Expected \"to\" keyword in report."); } } switch (parser.PeekToken().Kind) { case TokenKind.WithKeyword: parser.NextToken(); break; case TokenKind.LeftKeyword: parser.NextToken(); if (parser.PeekToken(TokenKind.MarginKeyword)) { parser.NextToken(); if (FglExpressionNode.TryGetExpressionNode(parser, out expr)) { defNode.MarginLeft = expr; } else { parser.ReportSyntaxError("Invalid margin value found in report."); } } else { parser.ReportSyntaxError("Expected \"margin\" keyword in report."); } break; case TokenKind.RightKeyword: parser.NextToken(); if (parser.PeekToken(TokenKind.MarginKeyword)) { parser.NextToken(); if (FglExpressionNode.TryGetExpressionNode(parser, out expr)) { defNode.MarginRight = expr; } else { parser.ReportSyntaxError("Invalid margin value found in report."); } } else { parser.ReportSyntaxError("Expected \"margin\" keyword in report."); } break; case TokenKind.BottomKeyword: parser.NextToken(); if (parser.PeekToken(TokenKind.MarginKeyword)) { parser.NextToken(); if (FglExpressionNode.TryGetExpressionNode(parser, out expr)) { defNode.MarginBottom = expr; } else { parser.ReportSyntaxError("Invalid margin value found in report."); } } else { parser.ReportSyntaxError("Expected \"margin\" keyword in report."); } break; case TokenKind.PageKeyword: parser.NextToken(); if (parser.PeekToken(TokenKind.LengthKeyword)) { parser.NextToken(); if (FglExpressionNode.TryGetExpressionNode(parser, out expr)) { defNode.PageLength = expr; } else { parser.ReportSyntaxError("Invalid page length value found in report."); } } else { parser.ReportSyntaxError("Expected \"length\" keyword in report."); } break; case TokenKind.TopKeyword: parser.NextToken(); if (parser.PeekToken(TokenKind.OfKeyword) && parser.PeekToken(TokenKind.PageKeyword, 2)) { parser.NextToken(); parser.NextToken(); if (FglExpressionNode.TryGetExpressionNode(parser, out expr)) { defNode.TopOfPage = expr; } else { parser.ReportSyntaxError("Invalid top of page value found in report."); } } else if (parser.PeekToken(TokenKind.MarginKeyword)) { parser.NextToken(); if (FglExpressionNode.TryGetExpressionNode(parser, out expr)) { defNode.MarginTop = expr; } else { parser.ReportSyntaxError("Invalid margin value found in report."); } } else { parser.ReportSyntaxError("Invalid token found in report."); } break; default: isValid = false; parser.ReportSyntaxError("Invalid token found in output section of report."); break; } if (parser.PeekToken(TokenKind.OrderKeyword) || parser.PeekToken(TokenKind.FormatKeyword) || parser.PeekToken(TokenKind.EndOfFile) || (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ReportKeyword, 2))) { break; } } } if (parser.PeekToken(TokenKind.OrderKeyword)) { parser.NextToken(); if (parser.PeekToken(TokenKind.ExternalKeyword)) { parser.NextToken(); } if (parser.PeekToken(TokenKind.ByKeyword)) { parser.NextToken(); } else { parser.ReportSyntaxError("Expected \"by\" keyword in order section of report."); } // collect report variables FglNameExpression varName; while (FglNameExpression.TryParseNode(parser, out varName)) { defNode.OrderVarNames.Add(varName); if (parser.PeekToken(TokenKind.AscKeyword) || parser.PeekToken(TokenKind.DescKeyword)) { parser.NextToken(); } if (parser.PeekToken(TokenKind.Comma)) { parser.NextToken(); } else { break; } } } List <TokenKind> validExits = new List <TokenKind> { TokenKind.ProgramKeyword, TokenKind.ReportKeyword }; ReportFormatSection rfs; while (ReportFormatSection.TryParseNode(parser, out rfs, containingModule, defNode, null, defNode.StoreReturnStatement, defNode.AddLimitedScopeVariable, validExits) && rfs != null) { defNode.Children.Add(rfs.StartIndex, rfs); if (parser.PeekToken(TokenKind.EndOfFile) || (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.ReportKeyword, 2))) { break; } } if (!parser.PeekToken(TokenKind.EndOfFile)) { parser.NextToken(); if (parser.PeekToken(TokenKind.ReportKeyword)) { parser.NextToken(); defNode.EndIndex = parser.Token.Span.End; defNode.IsComplete = true; defNode.AddLimitedScopeVariable(Genero4glAst.PagenoVariable, defNode.StartIndex, defNode.EndIndex); } else { parser.ReportSyntaxError(parser.Token.Span.Start, parser.Token.Span.End, "Invalid end of report definition."); } } else { parser.ReportSyntaxError("Unexpected end of report definition"); } } return(result); }
public static bool TryParseNode(Genero4glParser parser, out MainBlockNode defNode, IModuleResult containingModule) { defNode = null; bool result = false; if (parser.PeekToken(TokenKind.MainKeyword)) { result = true; defNode = new MainBlockNode(); parser.NextToken(); defNode.Name = parser.Token.Token.Value.ToString(); defNode.StartIndex = parser.Token.Span.Start; defNode.DecoratorEnd = defNode.StartIndex + 4; defNode.AccessModifier = AccessModifier.Private; List <List <TokenKind> > breakSequences = new List <List <TokenKind> >(Genero4glAst.ValidStatementKeywords .Where(x => x != TokenKind.EndKeyword && x != TokenKind.MainKeyword) .Select(x => new List <TokenKind> { x })) { new List <TokenKind> { TokenKind.EndKeyword, TokenKind.MainKeyword } }; List <TokenKind> validExits = new List <TokenKind> { TokenKind.ProgramKeyword }; HashSet <TokenKind> endKeywords = new HashSet <TokenKind> { TokenKind.MainKeyword }; bool fglStatement = false; // try to parse one or more declaration statements while (!parser.PeekToken(TokenKind.EndOfFile) && !(parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.MainKeyword, 2))) { fglStatement = false; DefineNode defineNode; TypeDefNode typeNode; ConstantDefNode constNode; bool matchedBreakSequence = false; switch (parser.PeekToken().Kind) { case TokenKind.TypeKeyword: { if (TypeDefNode.TryParseNode(parser, out typeNode, out matchedBreakSequence, breakSequences) && typeNode != null) { defNode.Children.Add(typeNode.StartIndex, typeNode); foreach (var def in typeNode.GetDefinitions()) { def.Scope = "local type"; if (!defNode.Types.ContainsKey(def.Name)) { defNode.Types.Add(def.Name, def); } else { parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Type {0} defined more than once.", def.Name), Severity.Error); } } } break; } case TokenKind.ConstantKeyword: { if (ConstantDefNode.TryParseNode(parser, out constNode, out matchedBreakSequence, breakSequences) && constNode != null) { defNode.Children.Add(constNode.StartIndex, constNode); foreach (var def in constNode.GetDefinitions()) { def.Scope = "local constant"; if (!defNode.Constants.ContainsKey(def.Name)) { defNode.Constants.Add(def.Name, def); } else { parser.ReportSyntaxError(def.LocationIndex, def.LocationIndex + def.Name.Length, string.Format("Constant {0} defined more than once.", def.Name), Severity.Error); } } } break; } case TokenKind.DefineKeyword: { if (DefineNode.TryParseDefine(parser, out defineNode, out matchedBreakSequence, breakSequences) && defineNode != null) { defNode.Children.Add(defineNode.StartIndex, defineNode); foreach (var def in defineNode.GetDefinitions()) { foreach (var vardef in def.VariableDefinitions) { vardef.Scope = "local variable"; if (!defNode.Variables.ContainsKey(vardef.Name)) { defNode.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); } } } } break; } default: { FglStatement statement; List <Func <PrepareStatement, bool> > prepBinders = new List <Func <PrepareStatement, bool> >(); prepBinders.Add(defNode.BindPrepareCursorFromIdentifier); if (parser.StatementFactory.TryParseNode(parser, out statement, containingModule, prepBinders, defNode.StoreReturnStatement, defNode.AddLimitedScopeVariable, false, validExits, null, null, endKeywords) && statement != null) { AstNode4gl stmtNode = statement as AstNode4gl; defNode.Children.Add(stmtNode.StartIndex, stmtNode); fglStatement = true; } break; } } if (parser.PeekToken(TokenKind.EndOfFile) || (parser.PeekToken(TokenKind.EndKeyword) && parser.PeekToken(TokenKind.MainKeyword, 2))) { break; } // if a break sequence was matched, we don't want to advance the token if (!matchedBreakSequence && !fglStatement) { // TODO: not sure whether to break or keep going...for right now, let's keep going until we hit the end keyword parser.NextToken(); } } if (!parser.PeekToken(TokenKind.EndOfFile)) { parser.NextToken(); if (parser.PeekToken(TokenKind.MainKeyword)) { parser.NextToken(); defNode.EndIndex = parser.Token.Span.End; defNode.IsComplete = true; } else { parser.ReportSyntaxError(parser.Token.Span.Start, parser.Token.Span.End, "Invalid end of main definition."); } } else { parser.ReportSyntaxError("Unexpected end of main definition"); } } return(result); }