private static Ast.BlockStatement ParseBlock( TokenStream Stream, ParseContext Context) { var r = new Ast.BlockStatement(Stream.Next()); Stream.Advance(); //Skip the opening brace. while (Stream.Next().Type != TokenType.CloseBrace) r.Statements.Add(ParseStatement(Stream, Context)); Stream.Advance(); //Skip the closing brace. return r; }
public static List<Declaration> Build( TokenStream Stream, ParseContext Context, Func<String,ErrorStrategy> OnError, bool PrepareInitializer = true) { var r = new List<Declaration>(); while (!Stream.AtEnd()) { try { if (Stream.Next().Type != TokenType.Identifier) throw new CompileError("[036] Expected identifier", Stream); if (Stream.Next().Value.ToUpper() == "MACRO" || Stream.Next().Value.ToUpper() == "FUNCTION") { var declaration = ParseMacroDeclaration(Stream, Context); declaration.OwnerContextID = Context.ID; Context.PendingEmission.Add(declaration); } else if (Stream.Next().Value.ToUpper() == "TEST") { var declaration = ParseMacroDeclaration(Stream, Context); declaration.Type = DeclarationType.Test; declaration.OwnerContextID = Context.ID; r.Add(declaration); Context.PendingEmission.Add(declaration); } else if (Stream.Next().Value.ToUpper() == "RULE") { var declaration = ParseRuleDeclaration(Stream, Context); declaration.OwnerContextID = Context.ID; var rulebook = Context.Rules.FindMatchingRulebook(declaration.Terms); if (rulebook == null) { rulebook = new Rulebook { DeclarationTerms = new List<DeclarationTerm>( declaration.Terms.Select(t => t.GenericClone())) }; rulebook.ResultTypeName = declaration.ReturnTypeName; Context.Rules.Rulebooks.Add(rulebook); } //if (Declaration.AreTermTypesCompatible(rulebook.DeclarationTerms, declaration.Terms) == false) // throw new CompileError("[037] Term types are not compatible with existing rulebook", Stream); if (declaration.ReturnTypeName.ToUpper() != rulebook.ResultTypeName.ToUpper()) throw new CompileError("Rule return type not compatible with existing rulebook", Stream); rulebook.Rules.Add(declaration); Context.PendingEmission.Add(declaration); } else if (Stream.Next().Value.ToUpper() == "TYPE") { var type = ParseTypeDeclaration(Stream, Context); if (Context.ActiveScope.FindType(type.Name) != null) throw new CompileError("[038] Type already defined", Stream); Context.ActiveScope.Types.Add(type); } else if (Stream.Next().Value.ToUpper() == "GLOBAL") { var variable = ParseGlobalDeclaration(Stream, Context); variable.StorageMethod = VariableStorageMethod.Static; Context.ActiveScope.Variables.Add(variable); } else if (Stream.Next().Value.ToUpper() == "INCLUDE") { Stream.Advance(); if (Stream.Next().Type != TokenType.String) throw new CompileError("Expected string", Stream); var filename = Stream.Next().Value; Stream.Advance(); if (Context.FileLoader == null) throw new CompileError("Inclusion not enabled", Stream); var file = Context.FileLoader.LoadFile(filename, Stream.CurrentFile); var newStream = new TokenStream(new StringIterator(file.Data), Context); newStream.CurrentFile = file; r.AddRange(Build(newStream, Context, OnError, false)); } else if (Stream.Next().Value.ToUpper() == "DEFAULT") { Stream.Advance(); if (Stream.Next().Value.ToUpper() != "OF") throw new CompileError("Expected 'OF'", Stream); Stream.Advance(); if (Stream.Next().Value.ToUpper() != "RULE") throw new CompileError("Expected 'RULE'", Stream); var declaration = ParseRuleDeclaration(Stream, Context); foreach (var term in declaration.Terms) if (!String.IsNullOrEmpty(term.DeclaredTypeName) && term.DeclaredTypeName != "GENERIC") throw new CompileError("Don't declare types for default rules."); declaration.OwnerContextID = Context.ID; var rulebook = Context.Rules.FindMatchingRulebook(declaration.Terms); if (rulebook == null) { rulebook = new Rulebook { DeclarationTerms = declaration.Terms }; rulebook.ResultTypeName = declaration.ReturnTypeName; Context.Rules.Rulebooks.Add(rulebook); } //if (Declaration.AreTermTypesCompatible(rulebook.DeclarationTerms, declaration.Terms) == false) // throw new CompileError("[037] Term types are not compatible with existing rulebook", Stream); if (declaration.ReturnTypeName.ToUpper() != rulebook.ResultTypeName.ToUpper()) throw new CompileError("Rule return type not compatible with existing rulebook", Stream); if (rulebook.DefaultValue != null) throw new CompileError("Rulebook already has a default value", Stream); rulebook.DefaultValue = declaration; Context.PendingEmission.Add(declaration); } else throw new CompileError("[039] Unknown declaration type", Stream); } catch (Exception e) { if (OnError(e.Message) == ErrorStrategy.Abort) return r; Stream.Advance(); //Prevent an error from causing an infinite loop } } if (PrepareInitializer) { Context.InitializationFunction = Declaration.Parse("test initialize-globals : void"); var body = new Ast.BlockStatement(new Token()); body.Statements = Context.Initialization; Context.InitializationFunction.Body.Body = body; Context.PendingEmission.Add(Context.InitializationFunction); } return r; }