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