protected void ParseProgram() { string programName = "program"; if (Accept(Token.KwProgram)) { if (Accept(Token.Identifier)) { programName = _lexeme; } else { AddErrorAtTokenStart("Expecting program name."); } Expect(Token.ChrSemicolon); } _context.Emitter.BeginProgram(programName, _context.Importer.ImportedAssemblies); List <Tuple <Variable, FilePosition> > globals = new List <Tuple <Variable, FilePosition> >(); if (Accept(Token.KwVar)) { ParseVariableList(globals, isArgumentList: false); foreach (Tuple <Variable, FilePosition> globalDecl in globals) { Variable global = globalDecl.Item1; if (ValidateName(globalDecl.Item2, global.Name, global: true)) { Symbol globalSymbol = _symbolTable.Add(global.Name, global.Type, StorageClass.Global); _context.Emitter.DeclareGlobal(globalSymbol); } } } FilePosition blockBegin = _lexer.TokenStartPosition; while (!Accept(Token.KwBegin)) { if (Accept(Token.Eof)) { AddErrorAtLastParsedPosition("Unexpected end of file looking for main block."); return; } else if (Accept(Token.KwFunction)) { ParseMethod(isFunction: true); } else if (Accept(Token.KwProcedure)) { ParseMethod(isFunction: false); } else if (Accept(Token.KwVar)) { AddErrorAtTokenStart("Global variables must be declared before the first function or procedure."); List <Tuple <Variable, FilePosition> > unused = new List <Tuple <Variable, FilePosition> >(); ParseVariableList(unused, isArgumentList: false); } else if (!Accept(Token.ChrSemicolon)) { AddErrorAtTokenStart("Expecting 'function', 'procedure', or 'begin'."); SkipToNextEnd(); } blockBegin = _lexer.TokenStartPosition; } // We are now at the main block IrisType mainMethod = Procedure.Create(new Variable[0]); Symbol mainSymbol = _symbolTable.OpenMethod("$.main", mainMethod); MethodGenerator.BeginMethod(mainSymbol.Name, IrisType.Void, new Variable[0], new Variable[0], true, _context.FilePath); MethodGenerator.EmitNonCodeLineInfo(blockBegin.Expand(5 /* Length of "begin" */)); // Initialize global variables if needed foreach (Tuple <Variable, FilePosition> globalDecl in globals) { InitializeVariableIfNeeded(blockBegin, globalDecl.Item1); } ParseStatements(Token.KwEnd); MethodGenerator.EndMethod(); Accept(Token.ChrPeriod); Expect(Token.Eof); _context.Emitter.EndProgram(); }