/* O V E R A L L S T R U C T U R E */ { static char *RcsId = "$Header$"; #include #include #include #include "idf.h" #include "misc.h" #include "main.h" #include "LLlex.h" #include "scope.h" #include "def.h" #include "type.h" #include "debug.h" } /* The grammar as given by Wirth is already almost LL(1); the main problem is that the full form of a qualified designator may be: [ module_ident '.' ]* IDENT [ '.' field_ident ]* which is quite confusing to an LL(1) parser. Rather than resorting to context-sensitive techniques, I have decided to render this as: IDENT [ '.' IDENT ]* on the grounds that it is quite natural to consider the first IDENT to be the name of the object and regard the others as field identifiers. */ %lexical LLlex; %start CompUnit, CompilationUnit; %start DefModule, DefinitionModule; ModuleDeclaration { struct idf *id; struct def *df; } : MODULE IDENT { id = dot.TOK_IDF; df = define(id, CurrentScope, D_MODULE); open_scope(CLOSEDSCOPE, 0); df->mod_scope = CurrentScope->sc_scope; } priority? ';' import(1)* export(0)? block IDENT { close_scope(); match_id(id, dot.TOK_IDF); } ; priority: '[' ConstExpression ']' ; export(int def;) { struct id_list *ExportList; int QUALflag = 0; } : EXPORT [ QUALIFIED { QUALflag = 1; } ]? IdentList(&ExportList) ';' { if (!def) Export(ExportList, QUALflag); else warning("export list in definition module ignored"); FreeIdList(ExportList); } ; import(int local;) { struct id_list *ImportList; struct idf *id = 0; } : [ FROM IDENT { id = dot.TOK_IDF; } ]? IMPORT IdentList(&ImportList) ';' /* When parsing a global module, this is the place where we must read already compiled definition modules. If the FROM clause is present, the identifier in it is a module name, otherwise the names in the import list are module names. */ { Import(ImportList, id, local); FreeIdList(ImportList); } ; DefinitionModule { register struct def *df; struct idf *id; } : DEFINITION { state = DEFINITION; } MODULE IDENT { id = dot.TOK_IDF; df = define(id, GlobalScope, D_MODULE); open_scope(CLOSEDSCOPE, 0); df->mod_scope = CurrentScope->sc_scope; DO_DEBUG(debug(1, "Definition module \"%s\"", id->id_text)); } ';' import(0)* export(1)? /* New Modula-2 does not have export lists in definition modules. */ definition* END IDENT '.' { df = CurrentScope->sc_def; while (df) { /* Make all definitions "QUALIFIED EXPORT" */ df->df_flags |= D_QEXPORTED; df = df->df_nextinscope; } close_scope(); match_id(id, dot.TOK_IDF); } ; definition { struct def *df; struct type *tp; } : CONST [ ConstantDeclaration ';' ]* | TYPE [ IDENT { df = define(dot.TOK_IDF, CurrentScope, D_TYPE); } [ '=' type(&tp) | /* empty */ /* Here, the exported type has a hidden implementation. The export is said to be opaque. It is restricted to pointer types. */ { df->df_kind = D_HIDDEN; } ] ';' ]* | VAR [ VariableDeclaration ';' ]* | ProcedureHeading(&df, D_PROCHEAD) ';' ; ProgramModule { struct idf *id; struct def *df, *GetDefinitionModule(); int scope = 0; } : MODULE { if (state != IMPLEMENTATION) state = PROGRAM; } IDENT { id = dot.TOK_IDF; if (state == IMPLEMENTATION) { df = GetDefinitionModule(id); scope = df->mod_scope; } open_scope(CLOSEDSCOPE, scope); } priority? ';' import(0)* block IDENT { close_scope(); match_id(id, dot.TOK_IDF); } '.' ; Module: DefinitionModule | [ IMPLEMENTATION { state = IMPLEMENTATION; } ]? ProgramModule ; CompilationUnit: Module ;