]> ocean-lang.org Git - ocean/blob - csrc/indent_test.mdc
ident_test: declare precedence for 'else'
[ocean] / csrc / indent_test.mdc
1 This parser is primarily for testing indent and linebreak handling.
2 It reads a very simple code fragment with if/else statements and
3 simple assignments with expressions, and then prints out the same
4 with complete bracketing and indenting.
5
6 # File: indent_test.mk
7         myCFLAGS := -Wall -g -fplan9-extensions
8         CFLAGS := $(filter-out $(myCFLAGS),$(CFLAGS)) $(myCFLAGS)
9         myLDLIBS:= libparser.o libscanner.o libmdcode.o -licuuc
10         LDLIBS := $(filter-out $(myLDLIBS),$(LDLIBS)) $(myLDLIBS)
11
12         all :: itest
13         itest.c itest.h : indent_test.mdc parsergen libparser.o libscanner.o libmdcode.o
14                 ./parsergen -o itest --LALR --tag indent indent_test.mdc
15         indent_test.mk: indent_test.mdc md2c
16                 ./md2c indent_test.mdc
17         itest: itest.c
18
19         doitest: itest itest.code
20                 ./itest itest.code
21         checkitest: itest itest.code
22                 @grep -v '^#' itest.out > .tmp.out
23                 @./itest itest.code | diff -u - .tmp.out || echo itest FAILED
24         demos :: doitest
25         tests :: checkitest
26
27 # indent: header
28
29  ./parsergen -o itest --LALR indent_test.cgm
30  cc -o itest itest.c lib*.o -licuuc -lgmp
31  ./itest itest.code
32
33         struct expression {
34                 struct text op;
35                 struct expression *left, *right;
36         };
37         struct statement {
38                 struct statement *next;
39                 struct expression *expr;
40                 struct statement *thenpart;
41                 struct statement *elsepart;
42         };
43
44 # indent: code
45         #include <unistd.h>
46         #include <stdlib.h>
47         #include <fcntl.h>
48         #include <sys/mman.h>
49         #include <stdio.h>
50         #include "mdcode.h"
51         #include "scanner.h"
52         #include "parser.h"
53         #include "itest.h"
54
55         static void free_expression(struct expression *e)
56         {
57                 if (!e)
58                         return;
59                 free_expression(e->left);
60                 free_expression(e->right);
61                 free(e);
62         }
63
64         static void free_statement(struct statement *s)
65         {
66                 if (!s)
67                         return;
68                 free_statement(s->next);
69                 free_expression(s->expr);
70                 free_statement(s->thenpart);
71                 free_statement(s->elsepart);
72                 free(s);
73         }
74
75         static void print_expression(struct expression *e)
76         {
77                 if (e->left && e->right) printf("(");
78                 if (e->left)
79                         print_expression(e->left);
80                 if (e->op.len)
81                         printf("%.*s", e->op.len, e->op.txt);
82                 if (e->right)
83                         print_expression(e->right);
84                 if (e->left && e->right) printf(")");
85         }
86
87         static void print_statement(struct statement *s, int depth)
88         {
89                 if (!s)
90                         return;
91                 if (!s->thenpart) {
92                         printf("%*.s", depth, "");
93                         print_expression(s->expr);
94                         printf(";\n");
95                 } else {
96                         printf("%*.sif ", depth, "");
97                         print_expression(s->expr);
98                         printf(":\n");
99                         print_statement(s->thenpart, depth+4);
100                         if (s->elsepart) {
101                                 printf("%*.selse:\n", depth, "");
102                                 print_statement(s->elsepart, depth+4);
103                         }
104                 }
105                 print_statement(s->next, depth);
106         }
107
108         int main(int argc, char *argv[])
109         {
110                 int fd = open(argv[1], O_RDONLY);
111                 int len = lseek(fd, 0, 2);
112                 char *file = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
113                 struct section *s = code_extract(file, file+len, NULL);
114                 struct token_config config = {
115                         .ignored = (1 << TK_line_comment)
116                                  | (1 << TK_block_comment),
117                         .number_chars = ".,_+-",
118                         .word_start = "",
119                         .word_cont = "",
120                 };
121                 parse_itest(s->code, &config, argc > 2 ? stderr : NULL);
122                 while (s) {
123                         struct section *t = s->next;
124                         code_free(s->code);
125                         free(s);
126                         s = t;
127                 }
128                 exit(0);
129         }
130
131 # indent: grammar
132
133 ~~~~~~
134
135 Program -> Statementlist ${ print_statement($1, 0); }$
136
137 OptNL -> NEWLINE
138         |
139
140 $*statement
141         Statementlist ->  Statements ${ $0 = $<1; }$
142
143         Statements -> Statements Statement ${
144                                 {
145                                         struct statement **s;
146                                         $0 = $<1;
147                                         s = &$0;
148                                         while (*s)
149                                                 s = &(*s)->next;
150                                         *s = $<2;
151                                 }
152                                 }$
153                         | Statement ${ $0 = $<1; }$
154                         | ERROR ${ printf("statement ERROR\n"); $0 = NULL; }$
155
156         Open -> {
157                 | NEWLINE {
158         Close -> }
159                 | NEWLINE }
160         Block -> Open Statementlist Close ${ $0 = $<2; }$
161                 | Open SimpleStatements } ${ $0 = $<2; }$
162                 | : Statementlist ${ $0 = $<2; }$
163
164         SimpleStatements -> SimpleStatements ; SimpleStatement ${
165                         {
166                                 struct statement **s;
167                                 $0 = $<1;
168                                 s = &$0;
169                                 while (*s)
170                                         s = &(*s)->next;
171                                 *s = $<3;
172                         }
173                         }$
174                 | SimpleStatement ${ $0 = $<1; }$
175                 | SimpleStatements ; ${ $0 = $<1; }$
176
177         SimpleStatement -> Factor = Expression ${
178                         $0 = calloc(1, sizeof(struct statement));
179                         $0->expr = calloc(1, sizeof(struct expression));
180                         $0->expr->left = $<1;
181                         $0->expr->op = $2.txt;
182                         $0->expr->right = $<3;
183                         }$
184         Statement -> SimpleStatements NEWLINE ${
185                         $0 = $<1;
186                         }$
187                 | IfStatement ${ $0 = $<1; }$
188                 | Statement NEWLINE ${ $0 = $<1; }$
189
190         $RIGHT else
191
192         IfStatement -> if Expression Block OptNL $$else ${
193                                 $0 = calloc(1, sizeof(struct statement));
194                                 $0->expr = $<2;
195                                 $0->thenpart = $<3;
196                                 }$
197                 | if Expression : SimpleStatements $$else ${
198                                 $0 = calloc(1, sizeof(struct statement));
199                                 $0->expr = $<2;
200                                 $0->thenpart = $<4;
201                                 }$
202                 | if Expression Block OptNL else Block ${
203                                 $0 = calloc(1, sizeof(struct statement));
204                                 $0->expr = $<2;
205                                 $0->thenpart = $<3;
206                                 $0->elsepart = $<6;
207                                 }$
208                 | if Expression Block OptNL else : SimpleStatements ${
209                                 $0 = calloc(1, sizeof(struct statement));
210                                 $0->expr = $<2;
211                                 $0->thenpart = $<3;
212                                 $0->elsepart = $<7;
213                                 }$
214                 | if Expression Block OptNL else IfStatement ${
215                                 $0 = calloc(1, sizeof(struct statement));
216                                 $0->expr = $<2;
217                                 $0->thenpart = $<3;
218                                 $0->elsepart = $<6;
219                                 }$
220
221 $*expression
222         Expression -> Expression + Term ${
223                                 $0 = calloc(1, sizeof(struct expression));
224                                 $0->op = $2.txt;
225                                 $0->left = $<1;
226                                 $0->right = $<3;
227                         }$
228                     | Expression - Term ${
229                                 $0 = calloc(1, sizeof(struct expression));
230                                 $0->op = $2.txt;
231                                 $0->left = $<1;
232                                 $0->right = $<3;
233                         }$
234                     | Term ${ $0 = $<1; }$
235         Term -> Term * Factor ${
236                                 $0 = calloc(1, sizeof(struct expression));
237                                 $0->op = $2.txt;
238                                 $0->left = $<1;
239                                 $0->right = $<3;
240                         }$
241               | Term / Factor ${
242                                 $0 = calloc(1, sizeof(struct expression));
243                                 $0->op = $2.txt;
244                                 $0->left = $<1;
245                                 $0->right = $<3;
246                         }$
247               | Factor ${ $0 = $<1; }$
248         Factor -> IDENTIFIER ${
249                                 $0 = calloc(1, sizeof(struct expression));
250                                 $0->op = $1.txt;
251                         }$
252 ~~~~~~
253
254 # File: itest.code
255
256         # test code
257         ~~~~~~
258         hello = yes; mister = no;
259         there = x;
260         all = y;
261         if cond + cond2 :
262                 hello = x;
263                 hello2 = x;
264
265                 sum = val +
266                  val;
267
268                 if condX:
269                  foo = x *
270                     x +
271                     y
272                     / two;
273          else if cond2:
274                 there1 =x
275                 there1a=x
276         there2=x
277         there3=x;
278         all = y;
279         if true {yes=x;} else : no=x
280         if true: yes = no; no = yes;
281
282         if false {
283                 print = OK
284         } else {
285                 print = not_OK
286         }
287
288         if a:
289                 if b:
290                         c= d
291         x = y
292
293 # File: itest.out
294         (hello=yes);
295         (mister=no);
296         (there=x);
297         (all=y);
298         if (cond+cond2):
299             (hello=x);
300             (hello2=x);
301             (sum=(val+val));
302             if condX:
303                 (foo=((x*x)+(y/two)));
304         else:
305             if cond2:
306                 (there1=x);
307                 (there1a=x);
308         (there2=x);
309         (there3=x);
310         (all=y);
311         if true:
312             (yes=x);
313         else:
314             (no=x);
315         if true:
316             (yes=no);
317             (no=yes);
318         if false:
319             (print=OK);
320         else:
321             (print=not_OK);
322         if a:
323             if b:
324                 (c=d);
325         (x=y);