/* 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" } /* 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; ModuleDeclaration { struct idf *id; } : MODULE IDENT { open_scope(CLOSEDSCOPE, 0); id = dot.TOK_IDF; } priority? ';' import(1)* export? block IDENT { close_scope(); match_id(id, dot.TOK_IDF); } ; priority: '[' ConstExpression ']' ; export { struct id_list *ExportList; int QUALflag = 0; } : EXPORT [ QUALIFIED { QUALflag = 1; } ]? IdentList(&ExportList) ';' { Export(ExportList, QUALflag); 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 { struct def *df; struct idf *id; } : DEFINITION { state = DEFINITION; } MODULE IDENT { id = dot.TOK_IDF; df = define(id, CurrentScope, D_MODULE); open_scope(CLOSEDSCOPE, 0); df->mod_scope = CurrentScope; } ';' import(0)* /* export? New Modula-2 does not have export lists in definition modules. */ definition* END IDENT '.' { close_scope(); match_id(id, dot.TOK_IDF); } ; definition { struct def *df; struct type *tp; } : CONST [ ConstantDeclaration ';' ]* | TYPE [ IDENT [ '=' type(&tp) | /* empty */ /* Here, the exported type has a hidden implementation. The export is said to be opaque. It is restricted to pointer types. */ ] ';' ]* | VAR [ VariableDeclaration ';' ]* | ProcedureHeading(&df, D_PROCHEAD) ';' ; ProgramModule { struct idf *id; } : MODULE { if (state != IMPLEMENTATION) state = PROGRAM; } IDENT { if (state == IMPLEMENTATION) { /* ???? Read definition module, Look for current identifier, and find out its scope number */ } id = dot.TOK_IDF; open_scope(CLOSEDSCOPE, 0); } priority? ';' import(0)* block IDENT { close_scope(); match_id(id, dot.TOK_IDF); } '.' ; Module: DefinitionModule | [ IMPLEMENTATION { state = IMPLEMENTATION; } ]? ProgramModule ; CompilationUnit: Module ;