From: NeilBrown Date: Sun, 4 May 2014 11:55:29 +0000 (+1000) Subject: Add test parser for indent and linebreak handling. X-Git-Tag: workingparser~56 X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=commitdiff_plain;h=4dac6c87ae5de1cb03eb7e337f0aff65510a34b4 Add test parser for indent and linebreak handling. Signed-off-by: NeilBrown --- diff --git a/csrc/indent_test.cgm b/csrc/indent_test.cgm new file mode 100644 index 0000000..2851fe2 --- /dev/null +++ b/csrc/indent_test.cgm @@ -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 + #include + #include + #include + #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 index 0000000..9ce8305 --- /dev/null +++ b/csrc/itest.code @@ -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; +