]> ocean-lang.org Git - ocean/blob - csrc/indent_test.mdc
scanner: change the meaning of ignoring comment tokens.
[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: 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  ./parsergen -o itest --LALR indent_test.cgm
32  cc -o itest itest.c lib*.o -licuuc -lgmp
33  ./itest itest.code
34
35         struct expression {
36                 struct text op;
37                 struct expression *left, *right;
38         };
39         struct statement {
40                 struct statement *next;
41                 struct expression *expr;
42                 struct statement *thenpart;
43                 struct statement *elsepart;
44         };
45
46 # indent: code
47         #include <unistd.h>
48         #include <stdlib.h>
49         #include <fcntl.h>
50         #include <sys/mman.h>
51         #include <stdio.h>
52         #include "mdcode.h"
53         #include "scanner.h"
54         #include "parser.h"
55         #include "itest.h"
56
57         static void free_expression(struct expression *e)
58         {
59                 if (!e)
60                         return;
61                 free_expression(e->left);
62                 free_expression(e->right);
63                 free(e);
64         }
65
66         static void free_statement(struct statement *s)
67         {
68                 if (!s)
69                         return;
70                 free_statement(s->next);
71                 free_expression(s->expr);
72                 free_statement(s->thenpart);
73                 free_statement(s->elsepart);
74                 free(s);
75         }
76
77         static void print_expression(struct expression *e)
78         {
79                 if (e->left && e->right) printf("(");
80                 if (e->left)
81                         print_expression(e->left);
82                 if (e->op.len)
83                         printf("%.*s", e->op.len, e->op.txt);
84                 if (e->right)
85                         print_expression(e->right);
86                 if (e->left && e->right) printf(")");
87         }
88
89         static void print_statement(struct statement *s, int depth)
90         {
91                 if (!s)
92                         return;
93                 if (!s->thenpart) {
94                         printf("%*.s", depth, "");
95                         print_expression(s->expr);
96                         printf(";\n");
97                 } else {
98                         printf("%*.sif ", depth, "");
99                         print_expression(s->expr);
100                         printf(":\n");
101                         print_statement(s->thenpart, depth+4);
102                         if (s->elsepart) {
103                                 printf("%*.selse:\n", depth, "");
104                                 print_statement(s->elsepart, depth+4);
105                         }
106                 }
107                 print_statement(s->next, depth);
108         }
109
110         int main(int argc, char *argv[])
111         {
112                 int fd = open(argv[1], O_RDONLY);
113                 int len = lseek(fd, 0, 2);
114                 char *file = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
115                 struct section *s = code_extract(file, file+len, NULL);
116                 struct token_config config = {
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 $*statement
138         Newlines -> NEWLINE
139                 | Newlines NEWLINE
140         Statementlist ->  Statements ${ $0 = $<1; }$
141                 | Newlines Statements ${ $0 = $<2; }$
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                 | Newlines {
158         Close -> }
159                 | Newlines }
160         Block -> Open Statementlist Close ${ $0 = $<2; }$
161                 | Open SimpleStatements } ${ $0 = $<2; }$
162                 | : SimpleStatements ${ $0 = $<2; }$
163                 | : StatementBlock ${ $0 = $<2; }$
164         StatementBlock -> Statementlist $$OUT ${ $0 = $<1; }$
165
166         SimpleStatements -> SimpleStatements ; SimpleStatement ${
167                         {
168                                 struct statement **s;
169                                 $0 = $<1;
170                                 s = &$0;
171                                 while (*s)
172                                         s = &(*s)->next;
173                                 *s = $<3;
174                         }
175                         }$
176                 | SimpleStatement ${ $0 = $<1; }$
177                 | SimpleStatements ; ${ $0 = $<1; }$
178
179         SimpleStatement -> Factor = Expression ${
180                         $0 = calloc(1, sizeof(struct statement));
181                         $0->expr = calloc(1, sizeof(struct expression));
182                         $0->expr->left = $<1;
183                         $0->expr->op = $2.txt;
184                         $0->expr->right = $<3;
185                         }$
186         SSline -> SimpleStatements NEWLINE ${ $0 = $<1; }$
187         Statement -> SSline ${ $0 = $<1; }$
188                 | IfStatement $$NEWLINE ${ $0 = $<1; }$
189                 | Statement NEWLINE ${ $0 = $<1; }$
190
191         $RIGHT else
192
193         IfHead -> if Expression Block ${
194                                 $0 = calloc(1, sizeof(struct statement));
195                                 $0->expr = $<2;
196                                 $0->thenpart = $<3;
197                                 }$
198                 | IfHead NEWLINE ${ $0 = $<1; }$
199
200         IfStatement -> IfHead $$else ${ $0 = $<1; }$
201                 | IfHead else Block ${
202                         $0 = $<1;
203                         $0->elsepart = $<3;
204                         }$
205                 | IfHead else IfStatement ${
206                         $0 = $<1;
207                         $0->elsepart = $<3;
208                         }$
209
210 $*expression
211         Expression -> Expression + Term ${
212                                 $0 = calloc(1, sizeof(struct expression));
213                                 $0->op = $2.txt;
214                                 $0->left = $<1;
215                                 $0->right = $<3;
216                         }$
217                     | Expression - Term ${
218                                 $0 = calloc(1, sizeof(struct expression));
219                                 $0->op = $2.txt;
220                                 $0->left = $<1;
221                                 $0->right = $<3;
222                         }$
223                     | Term ${ $0 = $<1; }$
224         Term -> Term * Factor ${
225                                 $0 = calloc(1, sizeof(struct expression));
226                                 $0->op = $2.txt;
227                                 $0->left = $<1;
228                                 $0->right = $<3;
229                         }$
230               | Term / Factor ${
231                                 $0 = calloc(1, sizeof(struct expression));
232                                 $0->op = $2.txt;
233                                 $0->left = $<1;
234                                 $0->right = $<3;
235                         }$
236               | Factor ${ $0 = $<1; }$
237         Factor -> IDENTIFIER ${
238                                 $0 = calloc(1, sizeof(struct expression));
239                                 $0->op = $1.txt;
240                         }$
241 ~~~~~~
242
243 # File: itest.code
244
245         # test code
246         ~~~~~~
247         hello = yes; mister = no;
248         there = x;
249         all = y;
250         if cond + cond2 :
251                 hello = x;
252                 hello2 = x;
253
254                 sum = val +
255                  val;
256
257                 if condX:
258                  foo = x *
259                     x +
260                     y
261                     / two;
262          else if cond2:
263                 there1 =x
264                 there1a=x
265         there2=x
266         there3=x;
267         all = y;
268         if true {yes=x;} else : no=x
269         if true: yes = no; no = yes;
270         if false: yes=ok; else: no=ok
271
272         if false {
273                 print = OK
274         } else {
275                 print = not_OK
276         }
277
278         if a:
279                 if b:
280                         c= d
281         x = y
282
283 # File: itest.out
284         (hello=yes);
285         (mister=no);
286         (there=x);
287         (all=y);
288         if (cond+cond2):
289             (hello=x);
290             (hello2=x);
291             (sum=(val+val));
292             if condX:
293                 (foo=((x*x)+(y/two)));
294         else:
295             if cond2:
296                 (there1=x);
297                 (there1a=x);
298         (there2=x);
299         (there3=x);
300         (all=y);
301         if true:
302             (yes=x);
303         else:
304             (no=x);
305         if true:
306             (yes=no);
307             (no=yes);
308         if false:
309             (yes=ok);
310         else:
311             (no=ok);
312         if false:
313             (print=OK);
314         else:
315             (print=not_OK);
316         if a:
317             if b:
318                 (c=d);
319         (x=y);