]> ocean-lang.org Git - ocean/commitdiff
Add test parser for indent and linebreak handling.
authorNeilBrown <neilb@suse.de>
Sun, 4 May 2014 11:55:29 +0000 (21:55 +1000)
committerNeilBrown <neilb@suse.de>
Sun, 4 May 2014 11:55:29 +0000 (21:55 +1000)
Signed-off-by: NeilBrown <neilb@suse.de>
csrc/indent_test.cgm [new file with mode: 0644]
csrc/itest.code [new file with mode: 0644]

diff --git a/csrc/indent_test.cgm b/csrc/indent_test.cgm
new file mode 100644 (file)
index 0000000..2851fe2
--- /dev/null
@@ -0,0 +1,223 @@
+
+# header
+
+This parser is primarily for testing indent and linebreak handling.
+It reads a very simple code fragment with if/else statements and
+simple assignments with expressions, and then prints out the same
+with complete bracketing and indenting.
+
+ ./parsergen -o itest --LALR indent_test.cgm
+ cc -o itest itest.c lib*.o -licuuc -lgmp
+ ./itest itest.code
+
+       struct expression {
+               struct text op;
+               struct expression *left, *right;
+       };
+       struct statement {
+               struct statement *next;
+               struct expression *expr;
+               struct statement *thenpart;
+               struct statement *elsepart;
+       };
+
+       struct expr {
+               struct expression *e;
+       };
+       struct stmt {
+               struct statement *s;
+       };
+
+# code
+       #include <stdlib.h>
+       #include <fcntl.h>
+       #include <sys/mman.h>
+       #include <stdio.h>
+       #include "mdcode.h"
+       #include "scanner.h"
+       #include "parser.h"
+       #include "itest.h"
+
+       static void free_expression(struct expression *e)
+       {
+               if (!e)
+                       return;
+               free_expression(e->left);
+               free_expression(e->right);
+               free(e);
+       }
+       static void free_expr(struct expr *e)
+       {
+               free_expression(e->e);
+               free(e);
+       }
+       static void free_statement(struct statement *s)
+       {
+               if (!s)
+                       return;
+               free_statement(s->next);
+               free_statement(s->thenpart);
+               free_statement(s->elsepart);
+               free(s);
+       }
+
+       static void free_stmt(struct stmt *s)
+       {
+               free_statement(s->s);
+               free(s);
+       }
+
+       static void print_expression(struct expression *e)
+       {
+               if (e->left && e->right) printf("(");
+               if (e->left)
+                       print_expression(e->left);
+               if (e->op.len)
+                       printf("%.*s", e->op.len, e->op.txt);
+               if (e->right)
+                       print_expression(e->right);
+               if (e->left && e->right) printf(")");
+       }
+
+       static void print_statement(struct statement *s, int depth)
+       {
+               if (!s)
+                       return;
+               if (!s->thenpart) {
+                       printf("%*.s", depth, "");
+                       print_expression(s->expr);
+                       printf(";\n");
+               } else {
+                       printf("%*.sif ", depth, "");
+                       print_expression(s->expr);
+                       printf(":\n");
+                       print_statement(s->thenpart, depth+4);
+                       if (s->elsepart) {
+                               printf("%*.selse:\n", depth, "");
+                               print_statement(s->elsepart, depth+4);
+                       }
+               }
+               print_statement(s->next, depth);
+       }
+
+       int main(int argc, char *argv[])
+       {
+               int fd = open(argv[1], O_RDONLY);
+               int len = lseek(fd, 0, 2);
+               char *file = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+               struct section *s = code_extract(file, file+len, NULL);
+               struct token_config config = {
+                       .ignored = (1 << TK_line_comment)
+                                | (1 << TK_block_comment),
+                       .number_chars = ".,_+-",
+                       .word_start = "",
+                       .word_cont = "",
+               };
+               parse_itest(s->code, &config, argc > 2 ? stderr : NULL);
+               exit(0);
+       }
+
+
+# grammar
+
+~~~~~~
+
+Program -> Statementlist ${ print_statement($1.s, 0); }$
+
+OptNL -> NEWLINE
+       |
+OptSemi -> NEWLINE
+       | ;
+
+$stmt
+       Statementlist -> Statements ${ $0.s = $1.s; $1.s = NULL; }$
+       Statements -> Statements Statement ${
+                               {
+                                       struct statement **s;
+                                       $0 = $1;
+                                       s = &($0.s);
+                                       while (*s)
+                                               s = &(*s)->next;
+                                       if (body[2])
+                                               *s = $2.s;
+                                       if (body[0])
+                                               $1.s = NULL;
+                                       if (body[2])
+                                               $2.s = NULL;
+                               }
+                               }$
+                       | Statements OptSemi ${ $0.s = $1.s; $1.s = NULL; }$
+                       | ${ $0.s = NULL; }$
+                       | ERROR ${ printf("statement ERROR\n"); $0.s = NULL; }$
+
+       Block -> OptNL { Statementlist } OptNL ${ $0 = $3; $3.s = NULL; }$
+               | : Statementlist ${ $0 = $2; $2.s = NULL; }$
+
+       Statement -> Factor = Expression OptSemi ${
+                       $0.s = calloc(1, sizeof(struct statement));
+                       $0.s->expr = calloc(1, sizeof(struct expression));
+                       $0.s->expr->left = $1.e; $1.e = NULL;
+                       $0.s->expr->op = $2.txt;
+                       $0.s->expr->right = $3.e; $3.e = NULL;
+                       }$
+               | if Expression Block OptNL ${
+                               $0.s = calloc(1, sizeof(struct statement));
+                               $0.s->expr = $2.e; $2.e = NULL;
+                               $0.s->thenpart = $3.s;
+                               $3.s = NULL;
+                               }$
+               | if Expression Statement ${
+                               $0.s = calloc(1, sizeof(struct statement));
+                               $0.s->expr = $2.e; $2.e = NULL;
+                               $0.s->thenpart = $3.s;
+                               $3.s = NULL;
+                               }$
+               | if Expression Block OptNL else Block ${
+                               $0.s = calloc(1, sizeof(struct statement));
+                               $0.s->expr = $2.e; $2.e = NULL;
+                               $0.s->thenpart = $3.s;
+                               $3.s = NULL;
+                               $0.s->elsepart = $6.s;
+                               $6.s = NULL;
+                               }$
+               | if Expression Block OptNL else Statement ${
+                               $0.s = calloc(1, sizeof(struct statement));
+                               $0.s->expr = $2.e; $2.e = NULL;
+                               $0.s->thenpart = $3.s;
+                               $3.s = NULL;
+                               $0.s->elsepart = $6.s;
+                               $6.s = NULL;
+                               }$
+
+$expr
+       Expression -> Expression + Term ${
+                               $0.e = calloc(1, sizeof(struct expression));
+                               $0.e->op = $2.txt;
+                               $0.e->left = $1.e; $1.e = NULL;
+                               $0.e->right = $3.e; $3.e= NULL;
+                       }$
+                   | Expression - Term ${
+                               $0.e = calloc(1, sizeof(struct expression));
+                               $0.e->op = $2.txt;
+                               $0.e->left = $1.e; $1.e = NULL;
+                               $0.e->right = $3.e; $3.e= NULL;
+                       }$
+                   | Term ${ $0.e = $1.e; $1.e = NULL; }$
+       Term -> Term * Factor ${
+                               $0.e = calloc(1, sizeof(struct expression));
+                               $0.e->op = $2.txt;
+                               $0.e->left = $1.e; $1.e = NULL;
+                               $0.e->right = $3.e; $3.e= NULL;
+                       }$
+             | Term / Factor ${
+                               $0.e = calloc(1, sizeof(struct expression));
+                               $0.e->op = $2.txt;
+                               $0.e->left = $1.e; $1.e = NULL;
+                               $0.e->right = $3.e; $3.e= NULL;
+                       }$
+             | Factor ${ $0.e = $1.e; $1.e = NULL; }$
+       Factor -> IDENTIFIER ${
+                               $0.e = calloc(1, sizeof(struct expression));
+                               $0.e->op = $1.txt;
+                       }$
+
diff --git a/csrc/itest.code b/csrc/itest.code
new file mode 100644 (file)
index 0000000..9ce8305
--- /dev/null
@@ -0,0 +1,26 @@
+
+# stuff
+
+       hello = yes; mister = no;
+       there = x;
+       all = y;
+       if cond + cond2 :
+               hello = x;
+               hello2 = x;
+
+               sum = val +
+                val;
+
+               if condX:
+                foo = x *
+                    x +
+                    y
+                    / two;
+       else if cond2:
+               there1 =x
+               there1a=x
+       there2=x
+       there3=x;
+       all = y;
+       if true {yes=x;} else no=x;
+