]> ocean-lang.org Git - ocean/blobdiff - csrc/indent_test.mdc
indent_test: integrate into Makefile scheme nicely.
[ocean] / csrc / indent_test.mdc
diff --git a/csrc/indent_test.mdc b/csrc/indent_test.mdc
new file mode 100644 (file)
index 0000000..792e152
--- /dev/null
@@ -0,0 +1,285 @@
+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.
+
+# File: indent_test.mk
+       myCFLAGS := -Wall -g -fplan9-extensions
+       CFLAGS := $(filter-out $(myCFLAGS),$(CFLAGS)) $(myCFLAGS)
+       LDLIBS:= libparser.o libscanner.o libmdcode.o -licuuc
+
+       all :: itest
+       itest.c itest.h : indent_test.mdc parsergen libparser.o libscanner.o libmdcode.o
+               ./parsergen -o itest --LALR --tag indent indent_test.mdc
+       indent_test.mk: indent_test.mdc md2c
+               ./md2c indent_test.mdc
+       itest: itest.c
+
+       tests:: itest itest.code
+               ./itest itest.code
+
+# indent: header
+
+ ./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;
+       };
+
+# indent: code
+       #include <unistd.h>
+       #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_statement(struct statement *s)
+       {
+               if (!s)
+                       return;
+               free_statement(s->next);
+               free_expression(s->expr);
+               free_statement(s->thenpart);
+               free_statement(s->elsepart);
+               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);
+               while (s) {
+                       struct section *t = s->next;
+                       code_free(s->code);
+                       free(s);
+                       s = t;
+               }
+               exit(0);
+       }
+
+
+# indent: grammar
+
+~~~~~~
+
+Program -> Statementlist ${ print_statement($1, 0); }$
+
+OptNL -> NEWLINE
+       |
+
+$*statement
+       Statementlist ->  Statements ${ $0 = $<1; }$
+
+       Statements -> Statements Statement ${
+                               {
+                                       struct statement **s;
+                                       $0 = $<1;
+                                       s = &$0;
+                                       while (*s)
+                                               s = &(*s)->next;
+                                       *s = $<2;
+                               }
+                               }$
+                       | Statement ${ $0 = $<1; }$
+                       | ERROR ${ printf("statement ERROR\n"); $0 = NULL; }$
+
+       Open -> {
+               | NEWLINE {
+       Close -> }
+               | NEWLINE }
+       Block -> Open Statementlist Close ${ $0 = $<2; }$
+               | Open SimpleStatements } ${ $0 = $<2; }$
+               | : Statementlist ${ $0 = $2; $2 = NULL; }$
+
+       SimpleStatements -> SimpleStatements ; SimpleStatement ${
+                       {
+                               struct statement **s;
+                               $0 = $<1;
+                               s = &$0;
+                               while (*s)
+                                       s = &(*s)->next;
+                               *s = $<3;
+                       }
+                       }$
+               | SimpleStatement ${ $0 = $<1; }$
+               | SimpleStatements ; ${ $0 = $<1; }$
+
+       SimpleStatement -> Factor = Expression ${
+                       $0 = calloc(1, sizeof(struct statement));
+                       $0->expr = calloc(1, sizeof(struct expression));
+                       $0->expr->left = $<1;
+                       $0->expr->op = $2.txt;
+                       $0->expr->right = $<3;
+                       }$
+       Statement -> SimpleStatements NEWLINE ${
+                       $0 = $<1;
+                       }$
+               | IfStatement ${ $0 = $<1; }$
+               | Statement NEWLINE ${ $0 = $<1; }$
+
+       IfStatement -> if Expression Block OptNL ${
+                               $0 = calloc(1, sizeof(struct statement));
+                               $0->expr = $<2;
+                               $0->thenpart = $<3;
+                               }$
+               | if Expression : SimpleStatements ${
+                               $0 = calloc(1, sizeof(struct statement));
+                               $0->expr = $<2;
+                               $0->thenpart = $<4;
+                               }$
+               | if Expression Block OptNL else Block ${
+                               $0 = calloc(1, sizeof(struct statement));
+                               $0->expr = $<2;
+                               $0->thenpart = $<3;
+                               $0->elsepart = $<6;
+                               }$
+               | if Expression Block OptNL else : SimpleStatements ${
+                               $0 = calloc(1, sizeof(struct statement));
+                               $0->expr = $<2;
+                               $0->thenpart = $<3;
+                               $0->elsepart = $<7;
+                               }$
+               | if Expression Block OptNL else IfStatement ${
+                               $0 = calloc(1, sizeof(struct statement));
+                               $0->expr = $<2;
+                               $0->thenpart = $<3;
+                               $0->elsepart = $<6;
+                               }$
+
+$*expression
+       Expression -> Expression + Term ${
+                               $0 = calloc(1, sizeof(struct expression));
+                               $0->op = $2.txt;
+                               $0->left = $<1;
+                               $0->right = $<3;
+                       }$
+                   | Expression - Term ${
+                               $0 = calloc(1, sizeof(struct expression));
+                               $0->op = $2.txt;
+                               $0->left = $<1;
+                               $0->right = $<3;
+                       }$
+                   | Term ${ $0 = $1; $1 = NULL; }$
+       Term -> Term * Factor ${
+                               $0 = calloc(1, sizeof(struct expression));
+                               $0->op = $2.txt;
+                               $0->left = $<1;
+                               $0->right = $<3;
+                       }$
+             | Term / Factor ${
+                               $0 = calloc(1, sizeof(struct expression));
+                               $0->op = $2.txt;
+                               $0->left = $<1;
+                               $0->right = $<3;
+                       }$
+             | Factor ${ $0 = $1; $1 = NULL; }$
+       Factor -> IDENTIFIER ${
+                               $0 = calloc(1, sizeof(struct expression));
+                               $0->op = $1.txt;
+                       }$
+~~~~~~
+
+# File: itest.code
+
+       # test code
+       ~~~~~~
+       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
+       if true: yes = no; no = yes;
+
+       if false {
+               print = OK
+       } else {
+               print = not_OK
+       }
+
+       if a:
+               if b:
+                       c= d
+       x = y
+