Pristine Ack-5.5
[Ack-5.5.git] / lang / m2 / m2mm / program.g
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  *
5  * Author: Ceriel J.H. Jacobs
6  */
7
8 /* O V E R A L L   S T R U C T U R E */
9
10 /* stripped down version of the one in the Modula-2 compiler */
11
12 /* $Id: program.g,v 1.5 1994/06/24 12:45:31 ceriel Exp $ */
13
14 /*
15         The grammar as given by Wirth is already almost LL(1); the
16         main problem is that the full form of a qualified designator
17         may be:
18                 [ module_ident '.' ]* IDENT [ '.' field_ident ]*
19         which is quite confusing to an LL(1) parser. Rather than
20         resorting to context-sensitive techniques, I have decided
21         to render this as:
22                 IDENT [ '.' IDENT ]*
23         on the grounds that it is quite natural to consider the first
24         IDENT to be the name of the object and regard the others as
25         field identifiers.
26 */
27
28 {
29 #include        "main.h"
30 #include        "idf.h"
31 #include        "f_info.h"
32 #include        "LLlex.h"
33 #include        <alloc.h>
34
35 struct lnk *
36 new_lnk()
37 {
38         static struct lnk *p;
39         static int cnt;
40
41         if (cnt-- <= 0) {
42                 p = (struct lnk *)Malloc(50*sizeof(struct lnk));
43                 cnt = 49;
44         }
45         p->lnk_next = 0;
46         p->lnk_imp = 0;
47         return p++;
48 }
49 }
50
51 %lexical LLlex;
52
53 %start  CompUnit, CompilationUnit;
54 %start  DefModule, DefinitionModule;
55
56 ModuleDeclaration :
57         MODULE IDENT priority ';' import((struct lnk **) 0)* export?
58         block IDENT
59 ;
60
61 priority:
62         [
63                 '[' ConstExpression ']'
64         |
65                 /* empty */
66         ]
67 ;
68
69 export :
70         EXPORT
71         [
72                 QUALIFIED
73         |
74                 /* empty */
75         ]
76         IdentList ';'
77 ;
78
79 import(register struct lnk **p;)
80 {
81         register struct idf *fromid = 0;
82         struct idf *id;
83 }
84 :
85                                 { if (p) while (*p) p = &((*p)->lnk_next); }
86         [ FROM
87           identifier(&id)       { fromid = id;
88                                   if (p) {
89                                         if (AddToList(fromid->id_text, ".def")) {
90                                                 *p = new_lnk();
91                                                 (*p)->lnk_imp = fromid;
92                                         }
93                                   }
94                                 }
95         ]?
96         IMPORT 
97         identifier(&id)         { if (! fromid && p) {
98                                         if (AddToList(id->id_text, ".def")) {
99                                                 *p = new_lnk();
100                                                 (*p)->lnk_imp = id;
101                                                 p = &((*p)->lnk_next);
102                                         }
103                                   }
104                                 }
105         [
106                 ',' identifier(&id)
107                                 { if (! fromid && p) {
108                                         if (AddToList(id->id_text, ".def")) {
109                                                 *p = new_lnk();
110                                                 (*p)->lnk_imp = id;
111                                                 p = &((*p)->lnk_next);
112                                         }
113                                   }
114                                 }
115         ]*
116         ';'
117         /*
118            When parsing a global module, this is the place where we must
119            read already compiled definition modules.
120            If the FROM clause is present, the identifier in it is a module
121            name, otherwise the names in the import list are module names.
122         */
123 ;
124
125 DefinitionModule
126 {
127         struct idf *id;
128         extern char *strrindex();
129 }
130 :
131         DEFINITION
132         MODULE identifier(&id)
133                         { if (! ForeignFlag) {
134                                 AddToList(id->id_text, ".mod");
135                           }
136                           if (! id->id_type) {
137                                 id->id_type = DEFINITION;
138                           }
139                           else if (id->id_type != IMPLEMENTATION) {
140                                 error("multiple declaration for module %s",
141                                         id->id_text);
142                           }
143                           if (! id->id_dir) {
144                                 id->id_dir = WorkingDir;
145                           }
146                           else if (strcmp(id->id_dir, WorkingDir)) {
147                                 Gerror("definition and implementation of module %s reside in different directories", id->id_text);
148                           }
149                           id->id_def = strrindex(FileName, '/');
150                           if (! id->id_def) id->id_def = FileName;
151                           else (id->id_def)++;
152                           CurrentArg->a_idf = id;
153                         }
154         ';'
155         import(&(id->id_defimports))* 
156         [
157                 export
158         |
159                 /* empty */
160         ]
161         definition* END IDENT
162         '.'
163 ;
164
165 definition :
166         CONST [ %persistent ConstantDeclaration ';' ]*
167 |
168         TYPE
169         [ %persistent
170           IDENT
171           [ '=' type
172           | /* empty */
173             /*
174                Here, the exported type has a hidden implementation.
175                The export is said to be opaque.
176                It is restricted to pointer types.
177             */
178           ]
179           ';'
180         ]*
181 |
182         VAR [ %persistent VariableDeclaration ';' ]*
183 |
184         ProcedureHeading
185         ';'
186 ;
187
188 ProgramModule
189 {
190         struct idf *id;
191 }
192 :
193         MODULE
194         identifier(&id) { if (! id->id_type) {
195                                 id->id_type = state;
196                           }
197                           else if (id->id_type != DEFINITION ||
198                                    state != IMPLEMENTATION) {
199                                 error("multiple declaration for module %s",
200                                         id->id_text);
201                           }
202                           if (! id->id_dir) {
203                                 id->id_dir = WorkingDir;
204                           }
205                           else if (strcmp(id->id_dir, WorkingDir)) {
206                                 Gerror("definition and implementation of module %s reside in different directories", id->id_text);
207                           }
208                           CurrentArg->a_idf = id;
209                         }
210         priority
211         ';' import(&(id->id_modimports))*
212         block IDENT
213         '.'
214 ;
215
216 Module:
217         DEFINITION
218                                 { fatal("Definition module in .mod file"); }
219 |       %default
220         [
221                 IMPLEMENTATION  { state = IMPLEMENTATION; }
222         |
223                 /* empty */     { state = PROGRAM; }
224         ]
225         ProgramModule
226 ;
227
228 CompilationUnit:
229         Module
230 ;
231
232 identifier(struct idf **id;):
233         IDENT
234                                 { extern char idfbuf[];
235                                   *id = str2idf(idfbuf, 1);
236                                 }
237 ;