/* Program: Modula-2 grammar in LL(1) form Version: Mon Feb 24 14:29:39 MET 1986 */ /* 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. */ { #include "idf.h" #include "idlist.h" static char *RcsId = "$Header$"; } %lexical LLlex; %start CompUnit, CompilationUnit; ModuleDeclaration: MODULE IDENT priority? ';' import* export? block IDENT ; priority: '[' ConstExpression ']' ; export { struct id_list *ExportList; } : EXPORT QUALIFIED? IdentList(&ExportList) ';' ; import { struct id_list *ImportList; } : [ FROM IDENT ]? 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. */ ; DefinitionModule: DEFINITION { #ifdef DEBUG debug("Definition module"); #endif DEBUG } MODULE IDENT ';' import* /* export? New Modula-2 does not have export lists in definition modules. */ definition* END IDENT '.' ; definition: CONST [ ConstantDeclaration ';' ]* | TYPE [ IDENT [ '=' type | /* 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 ';' ; ProgramModule: MODULE { #ifdef DEBUG debug("Program module"); #endif DEBUG } IDENT priority? ';' import* block IDENT '.' ; Module: DefinitionModule | IMPLEMENTATION? ProgramModule ; CompilationUnit: Module ;