os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

commit 432f9068d89aac5deba79d82a90c767064911ddb
parent e2f55c2356725ddc5ba42ae36bca6deffdc15c47
Author: erai <erai@omiltem.net>
Date:   Sun, 15 Sep 2024 02:15:11 -0400

use peg parser for the second stage parser

Diffstat:
Mbootstrap.sh | 2+-
Mbufio.c | 2++
Mbuild.sh | 28++++++++++++++--------------
Mcc1.c | 316++++++++++++++++++++-----------------------------------------------------------
Mcc3.peg | 165++++++++++++++++++++++++++++++++++++++-----------------------------------------
Adecl.c | 168+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rcc3.c -> dump.c | 0
Mlex1.c | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Mlib.c | 162+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Anode.c | 206+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mparse1.c | 729++++++++++++++++++++++++++++++++++++-------------------------------------------
Aparse2.c | 915+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpeg.c | 30+++++++++---------------------
Mpeglib.c | 73+++++++++++++++++++++++++++++++++++++++++++++----------------------------
Mtype.c | 16++++++++--------
Mwatch.sh | 2+-
16 files changed, 2106 insertions(+), 829 deletions(-)

diff --git a/bootstrap.sh b/bootstrap.sh @@ -1,7 +1,7 @@ #!/bin/sh LIBS="bufio.c lib.c alloc.c syscall.c" -SOURCES="cc1.c type.c parse1.c lex1.c as.c" +SOURCES="cc1.c type.c parse1.c lex1.c as.c decl.c node.c" gcc -Wall -Wextra -Wno-unused -pedantic -std=c99 ./cc0.c -o cc0 diff --git a/bufio.c b/bufio.c @@ -26,6 +26,8 @@ fopen(fd: int, a: *alloc): *file { } fclose(f: *file): void { + fflush(f); + if (close(f.fd) != 0) { die("write failed"); } diff --git a/build.sh b/build.sh @@ -2,7 +2,7 @@ LIBS="bufio.c lib.c alloc.c syscall.c" CRYPTO="ed25519.c sha512.c sha256.c chacha20.c poly1305.c" -CC="cc1.c type.c parse1.c lex1.c as.c" +CC="cc1.c type.c parse1.c lex1.c as.c decl.c node.c" PEG="peg.c peglib.c parsepeg.c" BOOT="pxe.asm" SSHD="chacha20.c poly1305.c sha256.c sha512.c ed25519.c sshd.c" @@ -18,20 +18,20 @@ ALL="${LIBS} ${CC} ${PEG} ${BOOT} ${SSHD} ${KERNEL} ${SHELL} ${BIN}" cmp parsepeg.c parsepeg2.c || echo peg mismatch ./peg -o parse3.c cc3.peg -./cc1 -o cc3 bufio.c lib.c alloc.c syscall.c peglib.c cc3.c parse3.c +./cc2 -o cc3 bufio.c lib.c alloc.c syscall.c peglib.c parse2.c parse3.c as.c type.c decl.c node.c cc1.c -./cc2 ${LIBS} echo.c -o echo -./cc2 ${LIBS} cmp.c -o cmp -./cc2 ${LIBS} rm.c -o rm -./cc2 ${LIBS} mv.c -o mv -./cc2 ${LIBS} mkdir.c -o mkdir -./cc2 ${LIBS} ls.c -o ls -./cc2 ${LIBS} cat.c -o cat -./cc2 ${LIBS} xxd.c -o xxd -./cc2 ${LIBS} cpio.c -o cpio -./cc2 ${LIBS} sh.c -o sh -./cc2 ${LIBS} ${CRYPTO} sshd.c -o sshd +./cc3 ${LIBS} echo.c -o echo +./cc3 ${LIBS} cmp.c -o cmp +./cc3 ${LIBS} rm.c -o rm +./cc3 ${LIBS} mv.c -o mv +./cc3 ${LIBS} mkdir.c -o mkdir +./cc3 ${LIBS} ls.c -o ls +./cc3 ${LIBS} cat.c -o cat +./cc3 ${LIBS} xxd.c -o xxd +./cc3 ${LIBS} cpio.c -o cpio +./cc3 ${LIBS} sh.c -o sh +./cc3 ${LIBS} ${CRYPTO} sshd.c -o sshd for name in ${ALL}; do echo ${name}; done | ./cpio -o > initramfs -./cc2 kernel.c -o kernel +./cc3 kernel.c -o kernel diff --git a/cc1.c b/cc1.c @@ -1,52 +1,14 @@ -struct decl { - name: *byte; - member_name: *byte; - p: *decl; - l: *decl; - r: *decl; - - func_defined: int; - func_type: *type; - func_label: *label; - func_def: *node; - - struct_defined: int; - struct_size: int; - struct_layout_done: int; - struct_def: *node; - - member_defined: int; - member_type: *type; - member_offset: int; - member_def: *node; - - enum_defined: int; - enum_value: int; - enum_def: *node; - - var_defined: int; - var_type: *type; - var_offset: int; - var_def: *node; - - goto_defined: int; - goto_label: *label; -} - struct compiler { // Allocator a: *alloc; - // Lexer - in: *file; - nc: int; + // Parser + p: *parser; + + // Context filename: *byte; lineno: int; colno: int; - tt: int; - token: *byte; - tlen: int; - tmax: int; // Assembler as: *assembler; @@ -55,7 +17,7 @@ struct compiler { decls: *decl; } -show_context(c: *compiler) { +cshow_context(c: *compiler) { fdputs(2, "on "); if (c.filename) { fdputs(2, c.filename); @@ -68,7 +30,7 @@ show_context(c: *compiler) { } cdie(c: *compiler, msg: *byte) { - show_context(c); + cshow_context(c); fdputs(2, "cdie: "); fdputs(2, msg); fdputs(2, "\n"); @@ -82,15 +44,11 @@ comp_setup(a: *alloc): *compiler { c.a = a; - c.in = 0: *file; - c.nc = 0; + c.p = setup_parser(a); + c.filename = 0:*byte; - c.lineno = 1; - c.colno = 1; - c.tlen = 0; - c.tmax = 4096; - c.token = alloc(c.a, c.tmax); - c.tt = 0; + c.lineno = 0; + c.colno = 0; c.as = setup_assembler(a); @@ -463,7 +421,7 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { c.filename = n.filename; c.lineno = n.lineno; - c.colno = 0; + c.colno = n.colno; kind = n.kind; if (kind == N_STR) { @@ -1105,7 +1063,7 @@ compile_stmt(c: *compiler, d: *decl, n: *node, top: *label, out: *label) { c.filename = n.filename; c.lineno = n.lineno; - c.colno = 0; + c.colno = n.colno; kind = n.kind; if (kind == N_CONDLIST) { @@ -1187,139 +1145,6 @@ compile_stmt(c: *compiler, d: *decl, n: *node, top: *label, out: *label) { } } -find(c: *compiler, name: *byte, member_name: *byte, make: int): *decl { - var p: *decl; - var d: *decl; - var link: **decl; - var dir: int; - - p = 0: *decl; - link = &c.decls; - loop { - d = *link; - if (!d) { - break; - } - - dir = strcmp(name, d.name); - - if (dir == 0) { - if (!member_name && !d.member_name) { - dir = 0; - } else if (!member_name) { - dir = -1; - } else if (!d.member_name) { - dir = 1; - } else { - dir = strcmp(member_name, d.member_name); - } - } - - if (dir < 0) { - p = d; - link = &d.l; - } else if (dir > 0) { - p = d; - link = &d.r; - } else { - return d; - } - } - - - if (!make) { - return 0:*decl; - } - - d = alloc(c.a, sizeof(*d)): *decl; - - d.name = name; - d.member_name = member_name; - - d.p = p; - d.l = 0:*decl; - d.r = 0:*decl; - - d.func_defined = 0; - d.func_type = 0:*type; - d.func_label = mklabel(c.as); - d.func_def = 0:*node; - - d.struct_defined = 0; - d.struct_size = 0; - d.struct_layout_done = 0; - d.struct_def = 0:*node; - - d.member_defined = 0; - d.member_type = 0:*type; - d.member_offset = 0; - d.member_def = 0:*node; - - d.enum_defined = 0; - d.enum_value = 0; - d.enum_def = 0:*node; - - d.var_defined = 0; - d.var_type = 0:*type; - d.var_offset = 0; - d.var_def = 0:*node; - - d.goto_defined = 0; - d.goto_label = mklabel(c.as); - - *link = d; - - return d; -} - -// Find the first declaration -first_decl(c: *compiler): *decl { - var d: *decl; - - d = c.decls; - if (!d) { - return 0:*decl; - } - - loop { - if (!d.l) { - return d; - } - - d = d.l; - } -} - -next_decl(c: *compiler, d: *decl): *decl { - if (!d) { - return 0:*decl; - } - - if (d.r) { - d = d.r; - - loop { - if (!d.l) { - return d; - } - - d = d.l; - } - } - - loop { - if (!d.p) { - return 0:*decl; - } - - if (d.p.l == d) { - return d.p; - } - - d = d.p; - } -} - emit_ssr(c: *compiler) { var d: *decl; var v: *decl; @@ -1553,57 +1378,8 @@ emit_isr(c: *compiler) { as_op(c.as, OP_IRETQ); } -main(argc: int, argv: **byte, envp: **byte) { - var a: alloc; - var c: *compiler; - var p: *node; +emit_builtin(c: *compiler) { var d: *decl; - var start: *label; - var kstart: *label; - var i: int; - - setup_alloc(&a); - - c = comp_setup(&a); - - i = 1; - loop { - if (i >= argc) { - break; - } - - if (!strcmp(argv[i], "-o")) { - i = i + 1; - if (i >= argc) { - die("invalid -o at end of argument list"); - } - open_output(c.as, argv[i]); - i = i + 1; - continue; - } - - if (!strcmp(argv[i], "-C")) { - i = i + 1; - if (i >= argc) { - die("invalid -C at end of argument list"); - } - //open_coutput(c.as, argv[i]); - i = i + 1; - continue; - } - - if (argv[i][0] == '-':byte) { - die("invalid argument"); - } - - open_source(c, argv[i]); - p = parse_program(c, p); - close_source(c); - - i = i + 1; - } - - compile(c, p); d = find(c, "syscall", 0:*byte, 1); if (d.func_defined && !d.func_label.fixed) { @@ -2156,6 +1932,72 @@ main(argc: int, argv: **byte, envp: **byte) { // iretq as_op(c.as, OP_IRETQ); } +} + +main(argc: int, argv: **byte, envp: **byte) { + var a: alloc; + var c: *compiler; + var p: *node; + var d: *decl; + var start: *label; + var kstart: *label; + var i: int; + var show: int; + + setup_alloc(&a); + + c = comp_setup(&a); + + show = 0; + + i = 1; + loop { + if (i >= argc) { + break; + } + + if (!strcmp(argv[i], "-o")) { + i = i + 1; + if (i >= argc) { + die("invalid -o at end of argument list"); + } + open_output(c.as, argv[i]); + i = i + 1; + continue; + } + + if (!strcmp(argv[i], "-fdump")) { + i = i + 1; + show = 1; + continue; + } + + if (!strcmp(argv[i], "-C")) { + i = i + 1; + if (i >= argc) { + die("invalid -C at end of argument list"); + } + //open_coutput(c.as, argv[i]); + i = i + 1; + continue; + } + + if (argv[i][0] == '-':byte) { + die("invalid argument"); + } + + p = concat_program(p, parse(c.p, argv[i])); + + i = i + 1; + } + + if show { + show_node(p); + } + + compile(c, p); + + emit_builtin(c); start = 0: *label; d = find(c, "_start", 0:*byte, 0); diff --git a/cc3.peg b/cc3.peg @@ -1,44 +1,31 @@ grammar <- sp (enum_decl / struct_decl / func_decl)* !. -enum_def <- ident sp ('=' sp expr)? -enum_decl <- enum sp '{' sp (enum_def (',' sp enum_def)*)? (',' sp)? '}' sp - -struct_def <- ident sp ':' sp type ';' sp -struct_decl <- struct sp ident sp '{' sp struct_def* '}' sp - -func_decl <- ident sp func_type (';' / '{' sp stmt* '}') sp - -type <- ident sp - / byte sp - / int sp - / void sp - / func sp func_type - / '*' sp type - / '(' sp type ')' sp - -func_type <- '(' sp - ( ident sp ':' sp type (',' sp ident sp ':' sp type)* )? - ( ',' sp )? - ')' sp (':' sp type)? - -stmt <- if_stmt - / loop_stmt - / break_stmt - / continue_stmt - / return_stmt - / var_stmt - / label_stmt - / goto_stmt - / assign_stmt - / expr_stmt - / empty_stmt - / compound_stmt - -if_stmt <- if sp expr '{' sp stmt* '}' sp - (else sp if sp expr '{' sp stmt* '}' sp)* - (else sp '{' sp stmt* '}' sp)? - -loop_stmt <- loop sp '{' sp stmt* '}' sp +enum_item <- ident sp ('=' sp expr)? +enum_decl <- enum sp '{' sp (enum_item (',' sp enum_item)*)? (',' sp)? '}' sp + +member_decl <- ident sp ':' sp type ';' sp +struct_decl <- struct sp ident sp '{' sp member_decl* '}' sp + +func_decl <- ident sp func_type (';' sp / compound_stmt) + +type <- ident sp / byte sp / int sp / void sp + / func sp func_type / ptr_type / '(' sp type ')' sp + +ptr_type <- '*' sp type + +arg_decl <- ident sp ':' sp type +func_type <- '(' sp ( arg_decl (',' sp arg_decl)* )? ( ',' sp )? ')' sp + (':' sp type)? + +stmt <- if_stmt / loop_stmt / break_stmt / continue_stmt + / return_stmt / var_stmt / label_stmt / goto_stmt + / assign_stmt / expr_stmt / empty_stmt / compound_stmt + +elif_stmt <- else sp if sp expr compound_stmt +else_stmt <- else sp compound_stmt +if_stmt <- if sp expr compound_stmt elif_stmt* else_stmt? + +loop_stmt <- loop sp compound_stmt sp break_stmt <- break sp ';' sp @@ -62,52 +49,60 @@ compound_stmt <- '{' sp stmt* '}' sp expr <- bool_expr -bool_expr <- comp_expr (('&&' / '||') sp comp_expr)* - -comp_expr <- add_expr (('<=' / '>=' / '<' / '>' / '==' / '!=') sp add_expr)? - -add_expr <- mul_expr (('+' / '-' / '|' !'|' / '^') sp add_expr)* - -mul_expr <- shift_expr (('*' / '/' / '%' / '&' !'&') sp mul_expr)* - -shift_expr <- unary_expr (('<<' / '>>') sp shift_expr)* - -unary_expr <- (('&' !'&' / '*' / '+' / '-' / '~' / '!') sp)* post_expr - -post_expr <- primary ( '[' sp expr ']' sp - / '(' sp ( expr (',' sp expr)* )? (',' sp)? ')' sp - / '.' sp ident sp - / ':' sp type )* - -primary <- ident sp - / hexadecimal sp - / decimal sp - / string sp - / character sp - / '(' sp expr ')' sp - / sizeof sp '(' sp expr ')' sp - -hexadecimal <- '0x'[0-9a-fA-F]+ -decimal <- [0-9]+ - -string <- ["] ([\\] . / !["] .)* ["] -character <- ['] ([\\] . / !['] .) ['] - -reserved <- return - / break - / sizeof - / if - / else - / loop - / continue - / goto - / var - / enum - / struct - / byte - / int - / void - / func +band_op <- '&&' +bor_op <- '||' +bool_expr <- comp_expr ((band_op / bor_op) sp comp_expr)* + +le_op <- '<=' +ge_op <- '>=' +lt_op <- '<' !'=' !'<' +gt_op <- '>' !'=' !'>' +eq_op <- '==' +ne_op <- '!=' +comp_expr <- add_expr ((le_op / ge_op / lt_op / gt_op / eq_op / ne_op) sp add_expr)? + +add_op <- '+' +sub_op <- '-' +or_op <- '|' !'|' +xor_op <- '^' +add_expr <- mul_expr ((add_op / sub_op / or_op / xor_op) sp mul_expr)* + +mul_op <- '*' +div_op <- '/' !'/' +mod_op <- '%' +and_op <- '&' !'&' +mul_expr <- shift_expr ((mul_op / div_op / mod_op / and_op) sp shift_expr)* + +lsh_op <- '<<' +rsh_op <- '>>' +shift_expr <- unary_expr ((lsh_op / rsh_op) sp unary_expr)* + +ref_op <- '&' !'&' +deref_op <- '*' +pos_op <- '+' +neg_op <- '-' +not_op <- '~' +bnot_op <- '!' !'=' +unary_expr <- ((ref_op / deref_op / pos_op / neg_op / not_op / bnot_op) sp)* post_expr + +index_expr <- '[' sp expr ']' sp +call_expr <- '(' sp ( expr (',' sp expr)* )? (',' sp)? ')' sp +member_expr <- '.' sp ident sp +cast_expr <- ':' sp type +post_expr <- primary (index_expr / call_expr / member_expr / cast_expr)* + +primary <- ident sp / hex sp / dec sp / str sp / char sp + / sizeof_expr / '(' sp expr ')' sp + +sizeof_expr <- sizeof sp '(' sp expr ')' sp + +hex <- '0x'[0-9a-fA-F]+ +dec <- [0-9]+ +str <- ["] ([\\] . / !["] .)* ["] +char <- ['] ([\\] . / !['] .)+ ['] + +reserved <- return / break / sizeof / if / else / loop / continue / goto + / var / enum / struct / byte / int / void / func return <- 'return' ![a-zA-Z0-9_] break <- 'break' ![a-zA-Z0-9_] diff --git a/decl.c b/decl.c @@ -0,0 +1,168 @@ +struct decl { + name: *byte; + member_name: *byte; + p: *decl; + l: *decl; + r: *decl; + + func_defined: int; + func_type: *type; + func_label: *label; + func_def: *node; + + struct_defined: int; + struct_size: int; + struct_layout_done: int; + struct_def: *node; + + member_defined: int; + member_type: *type; + member_offset: int; + member_def: *node; + + enum_defined: int; + enum_value: int; + enum_def: *node; + + var_defined: int; + var_type: *type; + var_offset: int; + var_def: *node; + + goto_defined: int; + goto_label: *label; +} + +find(c: *compiler, name: *byte, member_name: *byte, make: int): *decl { + var p: *decl; + var d: *decl; + var link: **decl; + var dir: int; + + p = 0: *decl; + link = &c.decls; + loop { + d = *link; + if (!d) { + break; + } + + dir = strcmp(name, d.name); + + if (dir == 0) { + if (!member_name && !d.member_name) { + dir = 0; + } else if (!member_name) { + dir = -1; + } else if (!d.member_name) { + dir = 1; + } else { + dir = strcmp(member_name, d.member_name); + } + } + + if (dir < 0) { + p = d; + link = &d.l; + } else if (dir > 0) { + p = d; + link = &d.r; + } else { + return d; + } + } + + + if (!make) { + return 0:*decl; + } + + d = alloc(c.a, sizeof(*d)): *decl; + + d.name = name; + d.member_name = member_name; + + d.p = p; + d.l = 0:*decl; + d.r = 0:*decl; + + d.func_defined = 0; + d.func_type = 0:*type; + d.func_label = mklabel(c.as); + d.func_def = 0:*node; + + d.struct_defined = 0; + d.struct_size = 0; + d.struct_layout_done = 0; + d.struct_def = 0:*node; + + d.member_defined = 0; + d.member_type = 0:*type; + d.member_offset = 0; + d.member_def = 0:*node; + + d.enum_defined = 0; + d.enum_value = 0; + d.enum_def = 0:*node; + + d.var_defined = 0; + d.var_type = 0:*type; + d.var_offset = 0; + d.var_def = 0:*node; + + d.goto_defined = 0; + d.goto_label = mklabel(c.as); + + *link = d; + + return d; +} + +// Find the first declaration +first_decl(c: *compiler): *decl { + var d: *decl; + + d = c.decls; + if (!d) { + return 0:*decl; + } + + loop { + if (!d.l) { + return d; + } + + d = d.l; + } +} + +next_decl(c: *compiler, d: *decl): *decl { + if (!d) { + return 0:*decl; + } + + if (d.r) { + d = d.r; + + loop { + if (!d.l) { + return d; + } + + d = d.l; + } + } + + loop { + if (!d.p) { + return 0:*decl; + } + + if (d.p.l == d) { + return d.p; + } + + d = d.p; + } +} + diff --git a/cc3.c b/dump.c diff --git a/lex1.c b/lex1.c @@ -1,3 +1,16 @@ +struct lexer { + a: *alloc; + in: *file; + nc: int; + filename: *byte; + lineno: int; + colno: int; + tt: int; + token: *byte; + tlen: int; + tmax: int; +} + enum { T_EOF, T_IDENT, @@ -38,7 +51,47 @@ enum { T_MOD, } -open_source(c: *compiler, filename: *byte) { +setup_lexer(a: *alloc): *lexer { + var c: *lexer; + + c = alloc(a, sizeof(*c)):*lexer; + + c.a = a; + + c.in = 0: *file; + c.nc = 0; + c.filename = 0:*byte; + c.lineno = 1; + c.colno = 1; + c.tlen = 0; + c.tmax = 4096; + c.token = alloc(c.a, c.tmax); + c.tt = 0; + + return c; +} + +lshow_context(c: *lexer) { + fdputs(2, "on "); + if (c.filename) { + fdputs(2, c.filename); + } + fdputs(2, ":"); + fdputd(2, c.lineno); + fdputs(2, ":"); + fdputd(2, c.colno); + fdputs(2, "\n"); +} + +ldie(c: *lexer, msg: *byte) { + lshow_context(c); + fdputs(2, "cdie: "); + fdputs(2, msg); + fdputs(2, "\n"); + exit(1); +} + +open_source(c: *lexer, filename: *byte) { var fd: int; c.filename = filename; @@ -50,7 +103,7 @@ open_source(c: *compiler, filename: *byte) { fd = open(filename, 0, 0); if (fd < 0) { - cdie(c, "failed to open file"); + ldie(c, "failed to open file"); } c.in = fopen(fd, c.a); @@ -59,14 +112,14 @@ open_source(c: *compiler, filename: *byte) { feed(c); } -close_source(c: *compiler) { +close_source(c: *lexer) { if (c.in) { fclose(c.in); } c.in = 0: *file; } -feedc(c: *compiler) { +feedc(c: *lexer) { c.nc = fgetc(c.in); if (c.nc == '\n') { c.lineno = c.lineno + 1; @@ -75,17 +128,17 @@ feedc(c: *compiler) { c.colno = c.colno + 1; } -tappend(c: *compiler) { +tappend(c: *lexer) { c.token[c.tlen] = c.nc:byte; c.tlen = c.tlen + 1; if (c.tlen == c.tmax) { - cdie(c, "identifier too long"); + ldie(c, "identifier too long"); } c.token[c.tlen] = 0:byte; feedc(c); } -feed(c: *compiler) { +feed(c: *lexer) { c.tlen = 0; c.token[0] = 0:byte; @@ -244,11 +297,11 @@ feed(c: *compiler) { c.tt = T_MOD; feedc(c); } else { - cdie(c, "invalid char"); + ldie(c, "invalid char"); } } -feed_ident(c: *compiler) { +feed_ident(c: *lexer) { c.tt = T_IDENT; loop { if (!((c.nc >= 'a' && c.nc <= 'z') || @@ -261,25 +314,9 @@ feed_ident(c: *compiler) { } } -hexdig(c: *compiler): int { - if (c.nc >= '0' && c.nc <= '9') { - return c.nc - '0'; - } - - if (c.nc >= 'A' && c.nc <= 'F') { - return (c.nc - 'F') + 10; - } - - if (c.nc >= 'a' && c.nc <= 'f') { - return (c.nc - 'a') + 10; - } - - cdie(c, "invalid hex digit"); - return 0; -} - -feed_escape(c: *compiler) { +feed_escape(c: *lexer) { var hex: int; + var ok: int; // backslash feedc(c); @@ -292,18 +329,24 @@ feed_escape(c: *compiler) { c.nc = '\n'; } else if (c.nc == 'x') { c.nc = fgetc(c.in); - hex = hexdig(c) * 16; + hex = hexdig(c.nc, &ok) * 16; + if !ok { + ldie(c, "invalid escape"); + } c.nc = fgetc(c.in); - hex = hex + hexdig(c); + hex = hex + hexdig(c.nc, &ok); + if !ok { + ldie(c, "invalid escape"); + } c.nc = hex; } else if (c.nc != '\\' && c.nc != '\'' && c.nc != '"') { - cdie(c, "invalid escape"); + ldie(c, "invalid escape"); } } -feed_str(c: *compiler) { +feed_str(c: *lexer) { c.tt = T_STR; // quote @@ -316,11 +359,11 @@ feed_str(c: *compiler) { } if (c.nc == -1 || c.nc == 0 || c.nc == '\n') { - cdie(c, "invalid char in string"); + ldie(c, "invalid char in string"); } if (c.tlen == c.tmax) { - cdie(c, "string too long"); + ldie(c, "string too long"); } if (c.nc == '\\') { @@ -331,14 +374,14 @@ feed_str(c: *compiler) { } } -feed_char(c: *compiler) { +feed_char(c: *lexer) { c.tt = T_CHAR; // quote feedc(c); if (c.nc == 0 || c.nc == -1 || c.nc == '\'' || c.nc == '\n') { - cdie(c, "invalid char"); + ldie(c, "invalid char"); } if (c.nc == '\\') { @@ -348,13 +391,13 @@ feed_char(c: *compiler) { tappend(c); if (c.nc != '\'') { - cdie(c, "expected '"); + ldie(c, "expected '"); } feedc(c); } -feed_hex(c: *compiler) { +feed_hex(c: *lexer) { c.tt = T_HEX; loop { @@ -368,11 +411,11 @@ feed_hex(c: *compiler) { } if (c.tlen == 0) { - cdie(c, "expected hex"); + ldie(c, "expected hex"); } } -feed_num(c: *compiler) { +feed_num(c: *lexer) { c.tt = T_NUM; if (c.nc == '0') { diff --git a/lib.c b/lib.c @@ -494,3 +494,165 @@ readall(fd: int, len: *int, a: *alloc): *byte { return buf; } + +hex2int(s: *byte, len: int, ok: *int): int { + var i: int; + var x: int; + var d: int; + x = 0; + i = 0; + loop { + if i == len { + break; + } + + d = s[i]:int; + + if d >= '0' && d <= '9' { + d = d - '0'; + } else if d >= 'a' && d <= 'f' { + d = d - 'a' + 10; + } else if d >= 'A' && d <= 'F' { + d = d - 'A' + 10; + } else { + *ok = 0; + return 0; + } + + x = x * 16; + x = x + d; + i = i + 1; + + if x > 0x7fffffff { + *ok = 0; + return 0; + } + } + + *ok = 1; + return x; +} + +dec2int(s: *byte, len: int, ok: *int): int { + var x: int; + var d: int; + var i: int; + + x = 0; + i = 0; + loop { + if i == len { + break; + } + + d = s[i]:int; + if d >= '0' && d <= '9' { + d = d - '0'; + } else { + *ok = 0; + return 0; + } + + x = x * 10; + + x = x + d; + i = i + 1; + + if x > 0x7fffffff { + *ok = 0; + return 0; + } + } + + *ok = 1; + return x; +} + +hexdig(ch: int, ok: *int): int { + if ch >= '0' && ch <= '9' { + *ok = 1; + return ch - '0'; + } else if ch >= 'A' && ch <= 'F' { + *ok = 1; + return ch - 'F' + 10; + } else if ch >= 'a' && ch <= 'f' { + *ok = 1; + return ch - 'a' + 10; + } else { + *ok = 0; + return 0; + } +} + + +unescape(s: *byte, i: *int, len: int, ok: *int): int { + var ch: int; + var hex: int; + + *ok = 1; + + if *i >= len { + *ok = 0; + return 0; + } + + ch = s[*i]:int; + *i = *i + 1; + + if ch != '\\' { + return ch; + } + + if *i >= len { + *ok = 0; + return 0; + } + + ch = s[*i]:int; + *i = *i + 1; + + if ch == 't' { + return '\t'; + } else if ch == 'r' { + return '\r'; + } else if ch == 'n' { + return '\n'; + } else if ch == '\\' { + return '\\'; + } else if ch == '\'' { + return '\''; + } else if ch == '\"' { + return '\"'; + } else if ch == 'x' { + if *i >= len { + *ok = 0; + return 0; + } + + ch = s[*i]:int; + *i = *i + 1; + + hex = hexdig(ch, ok) * 16; + if !*ok { + return 0; + } + + if *i >= len { + *ok = 0; + return 0; + } + + ch = s[*i]:int; + *i = *i + 1; + + hex = hex | hexdig(ch, ok); + if !*ok { + return 0; + } + + return hex; + } else { + *ok = 0; + return 0; + } +} diff --git a/node.c b/node.c @@ -0,0 +1,206 @@ +struct node { + kind: int; + a: *node; + b: *node; + filename: *byte; + lineno: int; + colno: int; + n: int; + s: *byte; + t: *type; +} + +enum { + N_IDENT, + N_NUM, + N_CHAR, + N_STR, + N_STMTLIST, + N_EXPRLIST, + N_CALL, + N_DOT, + N_ARGLIST, + N_FUNC, + N_ARGDECL, + N_FUNCDECL, + N_PROGRAM, + N_FUNCTYPE, + N_PTRTYPE, + N_STRUCT, + N_MEMBERDECL, + N_MEMBERLIST, + N_CONDLIST, + N_COND, + N_ENUM, + N_ENUMITEM, + N_ENUMLIST, + N_LOOP, + N_BREAK, + N_CONTINUE, + N_RETURN, + N_VARDECL, + N_LABEL, + N_GOTO, + N_ASSIGN, + N_SIZEOF, + N_REF, + N_DEREF, + N_CAST, + N_INDEX, + N_LT, + N_GT, + N_LE, + N_GE, + N_EQ, + N_NE, + N_ADD, + N_SUB, + N_MUL, + N_LSH, + N_RSH, + N_BNOT, + N_BOR, + N_BAND, + N_AND, + N_OR, + N_XOR, + N_NOT, + N_POS, + N_NEG, + N_DIV, + N_MOD, +} + +mknode(c: *parser, kind: int, a: *node, b: *node): *node { + var ret: *node; + ret = alloc(c.a, sizeof(*ret)):*node; + ret.kind = kind; + ret.a = a; + ret.b = b; + ret.filename = 0:*byte; + ret.lineno = 0; + ret.colno = 0; + ret.n = 0; + ret.s = 0:*byte; + ret.t = 0:*type; + fillpos(c, ret); + return ret; +} + +mknode0(c: *parser, kind: int): *node { + return mknode(c, kind, 0:*node, 0:*node); +} + +mknode1(c: *parser, kind: int, a: *node): *node { + return mknode(c, kind, a, 0:*node); +} + +concat_program(a: *node, b: *node): *node { + var ret: *node; + + if !a { + return b; + } + + if !b { + return a; + } + + ret = a; + loop { + if !a.b { + break; + } + + a = a.b; + } + + a.b = b; + + return ret; +} + +node_to_str(kind: int): *byte { + if kind == N_IDENT { return "N_IDENT"; } + if kind == N_NUM { return "N_NUM"; } + if kind == N_CHAR { return "N_CHAR"; } + if kind == N_STR { return "N_STR"; } + if kind == N_STMTLIST { return "N_STMTLIST"; } + if kind == N_EXPRLIST { return "N_EXPRLIST"; } + if kind == N_CALL { return "N_CALL"; } + if kind == N_DOT { return "N_DOT"; } + if kind == N_ARGLIST { return "N_ARGLIST"; } + if kind == N_FUNC { return "N_FUNC"; } + if kind == N_ARGDECL { return "N_ARGDECL"; } + if kind == N_FUNCDECL { return "N_FUNCDECL"; } + if kind == N_PROGRAM { return "N_PROGRAM"; } + if kind == N_FUNCTYPE { return "N_FUNCTYPE"; } + if kind == N_PTRTYPE { return "N_PTRTYPE"; } + if kind == N_STRUCT { return "N_STRUCT"; } + if kind == N_MEMBERDECL { return "N_MEMBERDECL"; } + if kind == N_MEMBERLIST { return "N_MEMBERLIST"; } + if kind == N_CONDLIST { return "N_CONDLIST"; } + if kind == N_COND { return "N_COND"; } + if kind == N_ENUM { return "N_ENUM"; } + if kind == N_ENUMITEM { return "N_ENUMITEM"; } + if kind == N_ENUMLIST { return "N_ENUMLIST"; } + if kind == N_LOOP { return "N_LOOP"; } + if kind == N_BREAK { return "N_BREAK"; } + if kind == N_CONTINUE { return "N_CONTINUE"; } + if kind == N_RETURN { return "N_RETURN"; } + if kind == N_VARDECL { return "N_VARDECL"; } + if kind == N_LABEL { return "N_LABEL"; } + if kind == N_GOTO { return "N_GOTO"; } + if kind == N_ASSIGN { return "N_ASSIGN"; } + if kind == N_SIZEOF { return "N_SIZEOF"; } + if kind == N_REF { return "N_REF"; } + if kind == N_DEREF { return "N_DEREF"; } + if kind == N_CAST { return "N_CAST"; } + if kind == N_INDEX { return "N_INDEX"; } + if kind == N_LT { return "N_LT"; } + if kind == N_GT { return "N_GT"; } + if kind == N_LE { return "N_LE"; } + if kind == N_GE { return "N_GE"; } + if kind == N_EQ { return "N_EQ"; } + if kind == N_NE { return "N_NE"; } + if kind == N_ADD { return "N_ADD"; } + if kind == N_SUB { return "N_SUB"; } + if kind == N_MUL { return "N_MUL"; } + if kind == N_LSH { return "N_LSH"; } + if kind == N_RSH { return "N_RSH"; } + if kind == N_BNOT { return "N_BNOT"; } + if kind == N_BOR { return "N_BOR"; } + if kind == N_BAND { return "N_BAND"; } + if kind == N_AND { return "N_AND"; } + if kind == N_OR { return "N_OR"; } + if kind == N_XOR { return "N_XOR"; } + if kind == N_NOT { return "N_NOT"; } + if kind == N_POS { return "N_POS"; } + if kind == N_NEG { return "N_NEG"; } + if kind == N_DIV { return "N_DIV"; } + if kind == N_MOD { return "N_MOD"; } + return "(invalid)"; +} + +show_node(n: *node) { + if !n { + return; + } + fdputc(2, '('); + fdputs(2, node_to_str(n.kind)); + if n.s { + fdputc(2, ' '); + fdputc(2, '"'); + fdputs(2, n.s); + fdputc(2, '"'); + } + if n.a { + fdputc(2, ' '); + show_node(n.a); + } + if n.b { + fdputc(2, ' '); + show_node(n.b); + } + fdputc(2, ')'); +} diff --git a/parse1.c b/parse1.c @@ -1,135 +1,60 @@ -struct node { - kind: int; - a: *node; - b: *node; - filename: *byte; - lineno: int; - colno: int; - n: int; - s: *byte; - t: *type; +struct parser { + a: *alloc; + l: *lexer; } -enum { - N_IDENT, - N_NUM, - N_CHAR, - N_STR, - N_STMTLIST, - N_EXPRLIST, - N_CALL, - N_DOT, - N_ARGLIST, - N_FUNC, - N_ARGDECL, - N_FUNCDECL, - N_PROGRAM, - N_FUNCTYPE, - N_PTRTYPE, - N_STRUCT, - N_MEMBERDECL, - N_MEMBERLIST, - N_CONDLIST, - N_COND, - N_ENUM, - N_ENUMITEM, - N_ENUMLIST, - N_LOOP, - N_BREAK, - N_CONTINUE, - N_RETURN, - N_VARDECL, - N_LABEL, - N_GOTO, - N_ASSIGN, - N_SIZEOF, - N_REF, - N_DEREF, - N_CAST, - N_INDEX, - N_LT, - N_GT, - N_LE, - N_GE, - N_EQ, - N_NE, - N_ADD, - N_SUB, - N_MUL, - N_LSH, - N_RSH, - N_BNOT, - N_BOR, - N_BAND, - N_AND, - N_OR, - N_XOR, - N_NOT, - N_POS, - N_NEG, - N_DIV, - N_MOD, +pdie(c: *parser, msg: *byte) { + ldie(c.l, msg); } -mknode(c: *compiler, kind: int, a: *node, b: *node): *node { - var ret: *node; - ret = alloc(c.a, sizeof(*ret)):*node; - ret.kind = kind; - ret.a = a; - ret.b = b; - ret.filename = c.filename; - ret.lineno = c.lineno; - ret.colno = c.colno; - ret.n = 0; - ret.s = 0:*byte; - ret.t = 0:*type; - return ret; -} +setup_parser(a: *alloc): *parser { + var c: *parser; -mknode0(c: *compiler, kind: int): *node { - return mknode(c, kind, 0:*node, 0:*node); -} + c = alloc(a, sizeof(*c)):*parser; + + c.a = a; -mknode1(c: *compiler, kind: int, a: *node): *node { - return mknode(c, kind, a, 0:*node); + c.l = setup_lexer(a); + + return c; } // Copy the current token -intern(c: *compiler): *byte { +intern(c: *parser): *byte { var ret: *byte; var i: int; - ret = alloc(c.a, c.tlen + 1); + ret = alloc(c.a, c.l.tlen + 1); i = 0; loop { - if (i == c.tlen) { + if (i == c.l.tlen) { ret[i] = 0:byte; return ret; } - ret[i] = c.token[i]; + ret[i] = c.l.token[i]; i = i + 1; } } // ident := IDENT -parse_ident(c: *compiler): *node { +parse_ident(c: *parser): *node { var n: *node; - if (c.tt != T_IDENT) { + if (c.l.tt != T_IDENT) { return 0:*node; } n = mknode0(c, N_IDENT); n.s = intern(c); - feed(c); + feed(c.l); return n; } -parse_hex(c: *compiler): *node { +parse_hex(c: *parser): *node { var n: *node; var x: int; var d: int; @@ -138,11 +63,11 @@ parse_hex(c: *compiler): *node { x = 0; i = 0; loop { - if (i == c.tlen) { + if (i == c.l.tlen) { break; } - d = c.token[i]:int; + d = c.l.token[i]:int; if (d >= '0' && d <= '9') { d = d - '0'; @@ -157,40 +82,40 @@ parse_hex(c: *compiler): *node { i = i + 1; if (x > 0x7fffffff) { - cdie(c, "overflow"); + pdie(c, "overflow"); } } n = mknode0(c, N_NUM); n.n = x; - feed(c); + feed(c.l); return n; } // num := NUM -parse_num(c: *compiler): *node { +parse_num(c: *parser): *node { var n: *node; var x: int; var d: int; var i: int; - if (c.tt == T_HEX) { + if (c.l.tt == T_HEX) { return parse_hex(c); } - if (c.tt != T_NUM) { + if (c.l.tt != T_NUM) { return 0:*node; } x = 0; i = 0; loop { - if (i == c.tlen) { + if (i == c.l.tlen) { break; } - d = (c.token[i]:int) - '0'; + d = (c.l.token[i]:int) - '0'; x = x * 10; @@ -198,43 +123,43 @@ parse_num(c: *compiler): *node { i = i + 1; if (x > 0x7fffffff) { - cdie(c, "overflow"); + pdie(c, "overflow"); } } n = mknode0(c, N_NUM); n.n = x; - feed(c); + feed(c.l); return n; } // chr := CHAR -parse_chr(c: *compiler): *node { +parse_chr(c: *parser): *node { var n: *node; - if (c.tt != T_CHAR) { + if (c.l.tt != T_CHAR) { return 0:*node; } n = mknode0(c, N_CHAR); - n.n = c.token[0]:int; - feed(c); + n.n = c.l.token[0]:int; + feed(c.l); return n; } // str := STR -parse_str(c: *compiler): *node { +parse_str(c: *parser): *node { var n: *node; - if (c.tt != T_STR) { + if (c.l.tt != T_STR) { return 0:*node; } n = mknode0(c, N_STR); n.s = intern(c); - feed(c); + feed(c.l); return n; } @@ -244,7 +169,7 @@ parse_str(c: *compiler): *node { // | str // | chr // | '(' expr ')' -parse_primary(c: *compiler): *node { +parse_primary(c: *parser): *node { var n: *node; n = parse_ident(c); @@ -267,18 +192,18 @@ parse_primary(c: *compiler): *node { return n; } - if (c.tt == T_LPAR) { - feed(c); + if (c.l.tt == T_LPAR) { + feed(c.l); n = parse_expr(c); if (!n) { - cdie(c, "expected expr"); + pdie(c, "expected expr"); } - if (c.tt != T_RPAR) { - cdie(c, "expected )"); + if (c.l.tt != T_RPAR) { + pdie(c, "expected )"); } - feed(c); + feed(c.l); return n; } @@ -288,7 +213,7 @@ parse_primary(c: *compiler): *node { // expr_list := expr // | expr ',' expr_list -parse_expr_list(c: *compiler): *node { +parse_expr_list(c: *parser): *node { var n: *node; var e: *node; var a: *node; @@ -302,14 +227,14 @@ parse_expr_list(c: *compiler): *node { n = e; loop { - if (c.tt != T_COMMA) { + if (c.l.tt != T_COMMA) { return n; } - feed(c); + feed(c.l); a = parse_expr(c); if (!a) { - cdie(c, "expected expr"); + pdie(c, "expected expr"); } e.b = mknode1(c, N_EXPRLIST, a); @@ -323,27 +248,27 @@ parse_expr_list(c: *compiler): *node { // | post_expr '(' expr_list ')' // | post_expr '.' ident // | post_expr ':' type -parse_post_expr(c: *compiler): *node { +parse_post_expr(c: *parser): *node { var n: *node; var b: *node; - if (c.tt == T_IDENT && !strcmp(c.token, "sizeof")) { - feed(c); + if (c.l.tt == T_IDENT && !strcmp(c.l.token, "sizeof")) { + feed(c.l); - if (c.tt != T_LPAR) { - cdie(c, "expected ("); + if (c.l.tt != T_LPAR) { + pdie(c, "expected ("); } - feed(c); + feed(c.l); n = parse_expr(c); if (!n) { - cdie(c, "expected expr"); + pdie(c, "expected expr"); } - if (c.tt != T_RPAR) { - cdie(c, "expected )"); + if (c.l.tt != T_RPAR) { + pdie(c, "expected )"); } - feed(c); + feed(c.l); return mknode1(c, N_SIZEOF, n); } @@ -354,43 +279,43 @@ parse_post_expr(c: *compiler): *node { } loop { - if (c.tt == T_LSQ) { - feed(c); + if (c.l.tt == T_LSQ) { + feed(c.l); b = parse_expr(c); - if (c.tt != T_RSQ) { - cdie(c, "expected ]"); + if (c.l.tt != T_RSQ) { + pdie(c, "expected ]"); } - feed(c); + feed(c.l); n = mknode(c, N_INDEX, n, b); - } else if (c.tt == T_LPAR) { - feed(c); + } else if (c.l.tt == T_LPAR) { + feed(c.l); b = parse_expr_list(c); - if (c.tt != T_RPAR) { - cdie(c, "expected )"); + if (c.l.tt != T_RPAR) { + pdie(c, "expected )"); } - feed(c); + feed(c.l); n = mknode(c, N_CALL, n, b); - } else if (c.tt == T_DOT) { - feed(c); + } else if (c.l.tt == T_DOT) { + feed(c.l); b = parse_ident(c); if (!b) { - cdie(c, "expected ident"); + pdie(c, "expected ident"); } n = mknode(c, N_DOT, n, b); - } else if (c.tt == T_COLON) { - feed(c); + } else if (c.l.tt == T_COLON) { + feed(c.l); b = parse_type(c); if (!b) { - cdie(c, "expected type"); + pdie(c, "expected type"); } n = mknode(c, N_CAST, n, b); @@ -407,70 +332,70 @@ parse_post_expr(c: *compiler): *node { // | '-' unary_expr // | '~' unary_expr // | '!' unary_expr -parse_unary_expr(c: *compiler): *node { +parse_unary_expr(c: *parser): *node { var n: *node; - if (c.tt == T_AMP) { - feed(c); + if (c.l.tt == T_AMP) { + feed(c.l); n = parse_unary_expr(c); if (!n) { - cdie(c, "expected unary_expr"); + pdie(c, "expected unary_expr"); } return mknode1(c, N_REF, n); } - if (c.tt == T_STAR) { - feed(c); + if (c.l.tt == T_STAR) { + feed(c.l); n = parse_unary_expr(c); if (!n) { - cdie(c, "expected unary_expr"); + pdie(c, "expected unary_expr"); } return mknode1(c, N_DEREF, n); } - if (c.tt == T_ADD) { - feed(c); + if (c.l.tt == T_ADD) { + feed(c.l); n = parse_unary_expr(c); if (!n) { - cdie(c, "expected unary_expr"); + pdie(c, "expected unary_expr"); } return mknode1(c, N_POS, n); } - if (c.tt == T_SUB) { - feed(c); + if (c.l.tt == T_SUB) { + feed(c.l); n = parse_unary_expr(c); if (!n) { - cdie(c, "expected unary_expr"); + pdie(c, "expected unary_expr"); } return mknode1(c, N_NEG, n); } - if (c.tt == T_NOT) { - feed(c); + if (c.l.tt == T_NOT) { + feed(c.l); n = parse_unary_expr(c); if (!n) { - cdie(c, "expected unary_expr"); + pdie(c, "expected unary_expr"); } return mknode1(c, N_NOT, n); } - if (c.tt == T_BANG) { - feed(c); + if (c.l.tt == T_BANG) { + feed(c.l); n = parse_unary_expr(c); if (!n) { - cdie(c, "expected unary_expr"); + pdie(c, "expected unary_expr"); } return mknode1(c, N_BNOT, n); @@ -483,7 +408,7 @@ parse_unary_expr(c: *compiler): *node { // shift_expr := unary_expr // | shift_expr '<<' unary_expr // | shift_expr '>>' unary_expr -parse_shift_expr(c: *compiler): *node { +parse_shift_expr(c: *parser): *node { var a: *node; var b: *node; @@ -493,21 +418,21 @@ parse_shift_expr(c: *compiler): *node { } loop { - if (c.tt == T_LSH) { - feed(c); + if (c.l.tt == T_LSH) { + feed(c.l); b = parse_unary_expr(c); if (!b) { - cdie(c, "expected unary_expr"); + pdie(c, "expected unary_expr"); } a = mknode(c, N_LSH, a, b); - } else if (c.tt == T_RSH) { - feed(c); + } else if (c.l.tt == T_RSH) { + feed(c.l); b = parse_unary_expr(c); if (!b) { - cdie(c, "expected unary_expr"); + pdie(c, "expected unary_expr"); } a = mknode(c, N_RSH, a, b); @@ -522,7 +447,7 @@ parse_shift_expr(c: *compiler): *node { // | mul_expr '/' shift_expr // | mul_expr '%' shift_expr // | mul_expr '&' shift_expr -parse_mul_expr(c: *compiler): *node { +parse_mul_expr(c: *parser): *node { var a: *node; var b: *node; @@ -532,39 +457,39 @@ parse_mul_expr(c: *compiler): *node { } loop { - if (c.tt == T_STAR) { - feed(c); + if (c.l.tt == T_STAR) { + feed(c.l); b = parse_shift_expr(c); if (!b) { - cdie(c, "expected shift_expr"); + pdie(c, "expected shift_expr"); } a = mknode(c, N_MUL, a, b); - } else if (c.tt == T_DIV) { - feed(c); + } else if (c.l.tt == T_DIV) { + feed(c.l); b = parse_shift_expr(c); if (!b) { - cdie(c, "expected shift_expr"); + pdie(c, "expected shift_expr"); } a = mknode(c, N_DIV, a, b); - } else if (c.tt == T_MOD) { - feed(c); + } else if (c.l.tt == T_MOD) { + feed(c.l); b = parse_shift_expr(c); if (!b) { - cdie(c, "expected shift_expr"); + pdie(c, "expected shift_expr"); } a = mknode(c, N_MOD, a, b); - } else if (c.tt == T_AMP) { - feed(c); + } else if (c.l.tt == T_AMP) { + feed(c.l); b = parse_shift_expr(c); if (!b) { - cdie(c, "expected shift_expr"); + pdie(c, "expected shift_expr"); } a = mknode(c, N_AND, a, b); @@ -579,7 +504,7 @@ parse_mul_expr(c: *compiler): *node { // | add_expr '-' mul_expr // | add_expr '|' mul_expr // | add_expr '^' mul_expr -parse_add_expr(c: *compiler): *node { +parse_add_expr(c: *parser): *node { var a: *node; var b: *node; @@ -589,39 +514,39 @@ parse_add_expr(c: *compiler): *node { } loop { - if (c.tt == T_ADD) { - feed(c); + if (c.l.tt == T_ADD) { + feed(c.l); b = parse_mul_expr(c); if (!b) { - cdie(c, "expected mul_expr"); + pdie(c, "expected mul_expr"); } a = mknode(c, N_ADD, a, b); - } else if (c.tt == T_SUB) { - feed(c); + } else if (c.l.tt == T_SUB) { + feed(c.l); b = parse_mul_expr(c); if (!b) { - cdie(c, "expected mul_expr"); + pdie(c, "expected mul_expr"); } a = mknode(c, N_SUB, a, b); - } else if (c.tt == T_OR) { - feed(c); + } else if (c.l.tt == T_OR) { + feed(c.l); b = parse_mul_expr(c); if (!b) { - cdie(c, "expected mul_expr"); + pdie(c, "expected mul_expr"); } a = mknode(c, N_OR, a, b); - } else if (c.tt == T_XOR) { - feed(c); + } else if (c.l.tt == T_XOR) { + feed(c.l); b = parse_mul_expr(c); if (!b) { - cdie(c, "expected mul_expr"); + pdie(c, "expected mul_expr"); } a = mknode(c, N_XOR, a, b); @@ -638,7 +563,7 @@ parse_add_expr(c: *compiler): *node { // | add_expr '>=' add_expr // | add_expr '==' add_expr // | add_expr '!=' add_expr -parse_comp_expr(c: *compiler): *node { +parse_comp_expr(c: *parser): *node { var a: *node; var b: *node; @@ -647,67 +572,67 @@ parse_comp_expr(c: *compiler): *node { return 0:*node; } - if (c.tt == T_LT) { - feed(c); + if (c.l.tt == T_LT) { + feed(c.l); b = parse_add_expr(c); if (!b) { - cdie(c, "expected add_expr"); + pdie(c, "expected add_expr"); } return mknode(c, N_LT, a, b); } - if (c.tt == T_GT) { - feed(c); + if (c.l.tt == T_GT) { + feed(c.l); b = parse_add_expr(c); if (!b) { - cdie(c, "expected add_expr"); + pdie(c, "expected add_expr"); } return mknode(c, N_GT, a, b); } - if (c.tt == T_LE) { - feed(c); + if (c.l.tt == T_LE) { + feed(c.l); b = parse_add_expr(c); if (!b) { - cdie(c, "expected add_expr"); + pdie(c, "expected add_expr"); } return mknode(c, N_LE, a, b); } - if (c.tt == T_GE) { - feed(c); + if (c.l.tt == T_GE) { + feed(c.l); b = parse_add_expr(c); if (!b) { - cdie(c, "expected add_expr"); + pdie(c, "expected add_expr"); } return mknode(c, N_GE, a, b); } - if (c.tt == T_EQ) { - feed(c); + if (c.l.tt == T_EQ) { + feed(c.l); b = parse_add_expr(c); if (!b) { - cdie(c, "expected add_expr"); + pdie(c, "expected add_expr"); } return mknode(c, N_EQ, a, b); } - if (c.tt == T_NE) { - feed(c); + if (c.l.tt == T_NE) { + feed(c.l); b = parse_add_expr(c); if (!b) { - cdie(c, "expected add_expr"); + pdie(c, "expected add_expr"); } return mknode(c, N_NE, a, b); @@ -719,7 +644,7 @@ parse_comp_expr(c: *compiler): *node { // bool_expr := bool_expr // | bool_expr '&&' comp_expr // | bool_expr '||' comp_expr -parse_bool_expr(c: *compiler): *node { +parse_bool_expr(c: *parser): *node { var a: *node; var b: *node; @@ -728,23 +653,23 @@ parse_bool_expr(c: *compiler): *node { return 0:*node; } - if (c.tt == T_BAND) { - feed(c); + if (c.l.tt == T_BAND) { + feed(c.l); b = parse_bool_expr(c); if (!b) { - cdie(c, "expected bool_expr"); + pdie(c, "expected bool_expr"); } return mknode(c, N_BAND, a, b); } - if (c.tt == T_BOR) { - feed(c); + if (c.l.tt == T_BOR) { + feed(c.l); b = parse_bool_expr(c); if (!b) { - cdie(c, "expected bool_expr"); + pdie(c, "expected bool_expr"); } return mknode(c, N_BOR, a, b); @@ -755,7 +680,7 @@ parse_bool_expr(c: *compiler): *node { // expr := bool_expr // | bool_expr '=' expr -parse_expr(c: *compiler): *node { +parse_expr(c: *parser): *node { var a: *node; var b: *node; @@ -764,12 +689,12 @@ parse_expr(c: *compiler): *node { return 0:*node; } - if (c.tt == T_ASSIGN) { - feed(c); + if (c.l.tt == T_ASSIGN) { + feed(c.l); b = parse_expr(c); if (!b) { - cdie(c, "expected expr"); + pdie(c, "expected expr"); } return mknode(c, N_ASSIGN, a, b); @@ -781,16 +706,16 @@ parse_expr(c: *compiler): *node { // if_stmt := 'if' expr '{' stmt_list '}' // | 'if' expr '{' stmt_list '}' 'else' if_stmt // | 'if' expr '{' stmt_list '}' 'else' '{' stmt_list '}' -parse_if_stmt(c: *compiler): *node { +parse_if_stmt(c: *parser): *node { var n: *node; var e: *node; var a: *node; var b: *node; - if (c.tt != T_IDENT || strcmp(c.token, "if")) { + if (c.l.tt != T_IDENT || strcmp(c.l.token, "if")) { return 0:*node; } - feed(c); + feed(c.l); n = mknode0(c, N_CONDLIST); e = n; @@ -798,47 +723,47 @@ parse_if_stmt(c: *compiler): *node { loop { a = parse_expr(c); if !a { - cdie(c, "expected expr"); + pdie(c, "expected expr"); } - if (c.tt != T_LBRA) { - cdie(c, "expected {"); + if (c.l.tt != T_LBRA) { + pdie(c, "expected {"); } - feed(c); + feed(c.l); b = parse_stmt_list(c); - if (c.tt != T_RBRA) { - cdie(c, "expected }"); + if (c.l.tt != T_RBRA) { + pdie(c, "expected }"); } - feed(c); + feed(c.l); e.a = mknode(c, N_COND, a, b); - if (c.tt != T_IDENT || strcmp(c.token, "else")) { + if (c.l.tt != T_IDENT || strcmp(c.l.token, "else")) { return n; } - feed(c); + feed(c.l); - if (c.tt == T_LBRA) { - feed(c); + if (c.l.tt == T_LBRA) { + feed(c.l); b = parse_stmt_list(c); - if (c.tt != T_RBRA) { - cdie(c, "expected }"); + if (c.l.tt != T_RBRA) { + pdie(c, "expected }"); } - feed(c); + feed(c.l); e.b = mknode1(c, N_CONDLIST, mknode(c, N_COND, 0:*node, b)); return n; } - if (c.tt != T_IDENT || strcmp(c.token, "if")) { - cdie(c, "expected if"); + if (c.l.tt != T_IDENT || strcmp(c.l.token, "if")) { + pdie(c, "expected if"); } - feed(c); + feed(c.l); e.b = mknode0(c, N_CONDLIST); e = e.b; @@ -846,58 +771,58 @@ parse_if_stmt(c: *compiler): *node { } // loop_stmt := 'loop' '{' stmt_list '}' -parse_loop_stmt(c: *compiler): *node { +parse_loop_stmt(c: *parser): *node { var a: *node; - if (c.tt != T_IDENT || strcmp(c.token, "loop")) { + if (c.l.tt != T_IDENT || strcmp(c.l.token, "loop")) { return 0:*node; } - feed(c); + feed(c.l); - if (c.tt != T_LBRA) { - cdie(c, "expected {"); + if (c.l.tt != T_LBRA) { + pdie(c, "expected {"); } - feed(c); + feed(c.l); a = parse_stmt_list(c); - if (c.tt != T_RBRA) { - cdie(c, "expected }"); + if (c.l.tt != T_RBRA) { + pdie(c, "expected }"); } - feed(c); + feed(c.l); return mknode1(c, N_LOOP, a); } // break_stmt := 'break' -parse_break_stmt(c: *compiler): *node { - if (c.tt != T_IDENT || strcmp(c.token, "break")) { +parse_break_stmt(c: *parser): *node { + if (c.l.tt != T_IDENT || strcmp(c.l.token, "break")) { return 0:*node; } - feed(c); + feed(c.l); return mknode0(c, N_BREAK); } // continue_stmt := 'continue' -parse_continue_stmt(c: *compiler): *node { - if (c.tt != T_IDENT || strcmp(c.token, "continue")) { +parse_continue_stmt(c: *parser): *node { + if (c.l.tt != T_IDENT || strcmp(c.l.token, "continue")) { return 0:*node; } - feed(c); + feed(c.l); return mknode0(c, N_CONTINUE); } // return_stmt := 'return' // | 'return' expr -parse_return_stmt(c: *compiler): *node { +parse_return_stmt(c: *parser): *node { var a: *node; - if (c.tt != T_IDENT || strcmp(c.token, "return")) { + if (c.l.tt != T_IDENT || strcmp(c.l.token, "return")) { return 0:*node; } - feed(c); + feed(c.l); a = parse_expr(c); @@ -905,7 +830,7 @@ parse_return_stmt(c: *compiler): *node { } // var_decl := ident ':' type -parse_var_decl(c: *compiler): *node { +parse_var_decl(c: *parser): *node { var n: *node; var a: *node; var b: *node; @@ -915,65 +840,65 @@ parse_var_decl(c: *compiler): *node { return 0:*node; } - if (c.tt != T_COLON) { - cdie(c, "expected :"); + if (c.l.tt != T_COLON) { + pdie(c, "expected :"); } - feed(c); + feed(c.l); b = parse_type(c); if (!b) { - cdie(c, "expected type"); + pdie(c, "expected type"); } return mknode(c, N_VARDECL, a, b); } // var_stmt := 'var' var_decl -parse_var_stmt(c: *compiler): *node { +parse_var_stmt(c: *parser): *node { var a: *node; - if (c.tt != T_IDENT || strcmp(c.token, "var")) { + if (c.l.tt != T_IDENT || strcmp(c.l.token, "var")) { return 0:*node; } - feed(c); + feed(c.l); a = parse_var_decl(c); if (!a) { - cdie(c, "expected var_decl"); + pdie(c, "expected var_decl"); } return a; } // label_stmt := ':' ident -parse_label_stmt(c: *compiler): *node { +parse_label_stmt(c: *parser): *node { var a: *node; - if (c.tt != T_COLON) { + if (c.l.tt != T_COLON) { return 0:*node; } - feed(c); + feed(c.l); a = parse_ident(c); if (!a) { - cdie(c, "expected ident"); + pdie(c, "expected ident"); } return mknode1(c, N_LABEL, a); } // goto_stmt := 'goto' ident -parse_goto_stmt(c: *compiler): *node { +parse_goto_stmt(c: *parser): *node { var a: *node; - if (c.tt != T_IDENT || strcmp(c.token, "goto")) { + if (c.l.tt != T_IDENT || strcmp(c.l.token, "goto")) { return 0:*node; } - feed(c); + feed(c.l); a = parse_ident(c); if (!a) { - cdie(c, "expected ident"); + pdie(c, "expected ident"); } return mknode1(c, N_GOTO, a); @@ -988,7 +913,7 @@ parse_goto_stmt(c: *compiler): *node { // | label_stmt ';' // | goto_stmt ';' // | expr ';' -parse_stmt(c: *compiler): *node { +parse_stmt(c: *parser): *node { var n: *node; n = parse_if_stmt(c); @@ -1003,70 +928,70 @@ parse_stmt(c: *compiler): *node { n = parse_break_stmt(c); if (n) { - if (c.tt != T_SEMI) { - cdie(c, "expected ;"); + if (c.l.tt != T_SEMI) { + pdie(c, "expected ;"); } - feed(c); + feed(c.l); return n; } n = parse_return_stmt(c); if (n) { - if (c.tt != T_SEMI) { - cdie(c, "expected ;"); + if (c.l.tt != T_SEMI) { + pdie(c, "expected ;"); } - feed(c); + feed(c.l); return n; } n = parse_continue_stmt(c); if (n) { - if (c.tt != T_SEMI) { - cdie(c, "expected ;"); + if (c.l.tt != T_SEMI) { + pdie(c, "expected ;"); } - feed(c); + feed(c.l); return n; } n = parse_var_stmt(c); if (n) { - if (c.tt != T_SEMI) { - cdie(c, "expected ;"); + if (c.l.tt != T_SEMI) { + pdie(c, "expected ;"); } - feed(c); + feed(c.l); return n; } n = parse_label_stmt(c); if (n) { - if (c.tt != T_SEMI) { - cdie(c, "expected ;"); + if (c.l.tt != T_SEMI) { + pdie(c, "expected ;"); } - feed(c); + feed(c.l); return n; } n = parse_goto_stmt(c); if (n) { - if (c.tt != T_SEMI) { - cdie(c, "expected ;"); + if (c.l.tt != T_SEMI) { + pdie(c, "expected ;"); } - feed(c); + feed(c.l); return n; } n = parse_expr(c); if (n) { - if (c.tt != T_SEMI) { - cdie(c, "expected ;"); + if (c.l.tt != T_SEMI) { + pdie(c, "expected ;"); } - feed(c); + feed(c.l); return n; } @@ -1076,7 +1001,7 @@ parse_stmt(c: *compiler): *node { // stmt_list := stmt // | stmt stmt_list -parse_stmt_list(c: *compiler): *node { +parse_stmt_list(c: *parser): *node { var n: *node; var e: *node; var a: *node; @@ -1102,7 +1027,7 @@ parse_stmt_list(c: *compiler): *node { // enum_item := ident // | ident '=' num -parse_enum_item(c: *compiler): *node { +parse_enum_item(c: *parser): *node { var a: *node; var b: *node; @@ -1111,14 +1036,14 @@ parse_enum_item(c: *compiler): *node { return 0:*node; } - if (c.tt != T_ASSIGN) { + if (c.l.tt != T_ASSIGN) { return mknode1(c, N_ENUMITEM, a); } - feed(c); + feed(c.l); b = parse_num(c); if (!b) { - cdie(c, "expected num"); + pdie(c, "expected num"); } return mknode(c, N_ENUMITEM, a, b); @@ -1126,7 +1051,7 @@ parse_enum_item(c: *compiler): *node { // enum_list := enum_item // | enum_list ',' enum_list -parse_enum_list(c: *compiler): *node { +parse_enum_list(c: *parser): *node { var n: *node; var e: *node; var a: *node; @@ -1140,10 +1065,10 @@ parse_enum_list(c: *compiler): *node { n = e; loop { - if (c.tt != T_COMMA) { + if (c.l.tt != T_COMMA) { return n; } - feed(c); + feed(c.l); a = parse_enum_item(c); if (!a) { @@ -1156,29 +1081,29 @@ parse_enum_list(c: *compiler): *node { } // enum_decl := 'enum' ident '{' enum_list '}' -parse_enum_decl(c: *compiler): *node { +parse_enum_decl(c: *parser): *node { var b: *node; - if (c.tt != T_IDENT) { + if (c.l.tt != T_IDENT) { return 0:*node; } - if (strcmp(c.token, "enum")) { + if (strcmp(c.l.token, "enum")) { return 0:*node; } - feed(c); + feed(c.l); - if (c.tt != T_LBRA) { - cdie(c, "expected {"); + if (c.l.tt != T_LBRA) { + pdie(c, "expected {"); } - feed(c); + feed(c.l); b = parse_enum_list(c); - if (c.tt != T_RBRA) { - cdie(c, "expected }"); + if (c.l.tt != T_RBRA) { + pdie(c, "expected }"); } - feed(c); + feed(c.l); return mknode(c, N_ENUM, 0:*node, b); } @@ -1187,36 +1112,36 @@ parse_enum_decl(c: *compiler): *node { // | '*' type // | '(' type ')' // | 'func' func_type -parse_type(c: *compiler): *node { +parse_type(c: *parser): *node { var n: *node; - if (c.tt == T_STAR) { - feed(c); + if (c.l.tt == T_STAR) { + feed(c.l); n = parse_type(c); return mknode1(c, N_PTRTYPE, n); } - if (c.tt == T_LPAR) { - feed(c); + if (c.l.tt == T_LPAR) { + feed(c.l); n = parse_type(c); - if (c.tt != T_RPAR) { - cdie(c, "expected )"); + if (c.l.tt != T_RPAR) { + pdie(c, "expected )"); } - feed(c); + feed(c.l); return n; } - if (c.tt == T_IDENT && !strcmp(c.token, "func")) { - feed(c); + if (c.l.tt == T_IDENT && !strcmp(c.l.token, "func")) { + feed(c.l); n = parse_func_type(c); if (!n) { - cdie(c, "expected func_type"); + pdie(c, "expected func_type"); } return n; @@ -1226,7 +1151,7 @@ parse_type(c: *compiler): *node { } // member_decl := ident ':' type -parse_member_decl(c: *compiler): *node { +parse_member_decl(c: *parser): *node { var n: *node; var a: *node; var b: *node; @@ -1236,14 +1161,14 @@ parse_member_decl(c: *compiler): *node { return 0: *node; } - if (c.tt != T_COLON) { - cdie(c, "expected :"); + if (c.l.tt != T_COLON) { + pdie(c, "expected :"); } - feed(c); + feed(c.l); b = parse_type(c); if (!b) { - cdie(c, "expected type"); + pdie(c, "expected type"); } return mknode(c, N_MEMBERDECL, a, b); @@ -1251,7 +1176,7 @@ parse_member_decl(c: *compiler): *node { // member_list := member_decl // | member_decl ';' member_list -parse_member_list(c: *compiler): *node { +parse_member_list(c: *parser): *node { var n: *node; var e: *node; var a: *node; @@ -1265,10 +1190,10 @@ parse_member_list(c: *compiler): *node { n = e; loop { - if (c.tt != T_SEMI) { + if (c.l.tt != T_SEMI) { return n; } - feed(c); + feed(c.l); a = parse_member_decl(c); if (!a) { @@ -1281,42 +1206,42 @@ parse_member_list(c: *compiler): *node { } // struct_decl := 'struct' ident '{' member_list '}' -parse_struct_decl(c: *compiler): *node { +parse_struct_decl(c: *parser): *node { var a: *node; var b: *node; - if (c.tt != T_IDENT) { + if (c.l.tt != T_IDENT) { return 0:*node; } - if (strcmp(c.token, "struct")) { + if (strcmp(c.l.token, "struct")) { return 0:*node; } - feed(c); + feed(c.l); a = parse_ident(c); if (!a) { - cdie(c, "expected ident"); + pdie(c, "expected ident"); } - if (c.tt != T_LBRA) { - cdie(c, "expected {"); + if (c.l.tt != T_LBRA) { + pdie(c, "expected {"); } - feed(c); + feed(c.l); b = parse_member_list(c); - if (c.tt != T_RBRA) { - cdie(c, "expected }"); + if (c.l.tt != T_RBRA) { + pdie(c, "expected }"); } - feed(c); + feed(c.l); return mknode(c, N_STRUCT, a, b); } // arg_decl := ':' type // ident ':' type -parse_arg_decl(c: *compiler): *node { +parse_arg_decl(c: *parser): *node { var n: *node; var a: *node; var b: *node; @@ -1326,14 +1251,14 @@ parse_arg_decl(c: *compiler): *node { return 0:*node; } - if (c.tt != T_COLON) { - cdie(c, "expected :"); + if (c.l.tt != T_COLON) { + pdie(c, "expected :"); } - feed(c); + feed(c.l); b = parse_type(c); if (!b) { - cdie(c, "expected type"); + pdie(c, "expected type"); } return mknode(c, N_ARGDECL, a, b); @@ -1341,7 +1266,7 @@ parse_arg_decl(c: *compiler): *node { // arg_list := arg_decl // | arg_decl ',' arg_list -parse_arg_list(c: *compiler): *node { +parse_arg_list(c: *parser): *node { var n: *node; var e: *node; var a: *node; @@ -1355,14 +1280,14 @@ parse_arg_list(c: *compiler): *node { n = e; loop { - if (c.tt != T_COMMA) { + if (c.l.tt != T_COMMA) { return n; } - feed(c); + feed(c.l); a = parse_arg_decl(c); if (!a) { - cdie(c, "expected identifier"); + pdie(c, "expected identifier"); } e.b = mknode1(c, N_ARGLIST, a); @@ -1374,37 +1299,37 @@ parse_arg_list(c: *compiler): *node { // | '(' arg_list ')' ':' type // | '(' ')' // | '(' arg_list ')' -parse_func_type(c: *compiler): *node { +parse_func_type(c: *parser): *node { var a: *node; var b: *node; - if (c.tt != T_LPAR) { + if (c.l.tt != T_LPAR) { return 0: *node; } - feed(c); + feed(c.l); a = parse_arg_list(c); - if (c.tt != T_RPAR) { - cdie(c, "expected )"); + if (c.l.tt != T_RPAR) { + pdie(c, "expected )"); } - feed(c); + feed(c.l); - if (c.tt != T_COLON) { + if (c.l.tt != T_COLON) { return mknode1(c, N_FUNCTYPE, a); } - feed(c); + feed(c.l); b = parse_type(c); if (!b) { - cdie(c, "expected type"); + pdie(c, "expected type"); } return mknode(c, N_FUNCTYPE, a, b); } // func_decl := ident func_type -parse_func_decl(c: *compiler): *node { +parse_func_decl(c: *parser): *node { var a: *node; var b: *node; @@ -1415,7 +1340,7 @@ parse_func_decl(c: *compiler): *node { b = parse_func_type(c); if (!b) { - cdie(c, "expected func_type"); + pdie(c, "expected func_type"); } return mknode(c, N_FUNCDECL, a, b); @@ -1423,7 +1348,7 @@ parse_func_decl(c: *compiler): *node { // func := func_decl '{' stmt_list '}' // | func_decl ';' -parse_func(c: *compiler): *node { +parse_func(c: *parser): *node { var n: *node; var a: *node; var b: *node; @@ -1433,22 +1358,22 @@ parse_func(c: *compiler): *node { return 0:*node; } - if (c.tt == T_SEMI) { - feed(c); + if (c.l.tt == T_SEMI) { + feed(c.l); return a; } - if (c.tt != T_LBRA) { - cdie(c, "expected {"); + if (c.l.tt != T_LBRA) { + pdie(c, "expected {"); } - feed(c); + feed(c.l); b = parse_stmt_list(c); - if (c.tt != T_RBRA) { - cdie(c, "expected }"); + if (c.l.tt != T_RBRA) { + pdie(c, "expected }"); } - feed(c); + feed(c.l); return mknode(c, N_FUNC, a, b); } @@ -1456,7 +1381,7 @@ parse_func(c: *compiler): *node { // decl := enum_decl // | struct_decl // | func -parse_decl(c: *compiler): *node { +parse_decl(c: *parser): *node { var n: *node; n = parse_enum_decl(c); @@ -1474,17 +1399,17 @@ parse_decl(c: *compiler): *node { // program := decl // | decl program -parse_program(c: *compiler, p: *node): *node { +parse_program(c: *parser): *node { var n: *node; var e: *node; var d: *node; d = parse_decl(c); if (!d) { - if (c.tt != T_EOF) { - cdie(c, "expected eof"); + if (c.l.tt != T_EOF) { + pdie(c, "expected eof"); } - return p; + return 0:*node; } e = mknode1(c, N_PROGRAM, d); @@ -1493,11 +1418,11 @@ parse_program(c: *compiler, p: *node): *node { loop { d = parse_decl(c); if (!d) { - if (c.tt != T_EOF) { - cdie(c, "expected eof"); + if (c.l.tt != T_EOF) { + pdie(c, "expected eof"); } - e.b = p; + e.b = 0:*node; return n; } @@ -1505,3 +1430,17 @@ parse_program(c: *compiler, p: *node): *node { e = e.b; } } + +parse(c: *parser, filename: *byte): *node { + var p: *node; + open_source(c.l, filename); + p = parse_program(c); + close_source(c.l); + return p; +} + +fillpos(c: *parser, n: *node) { + n.filename = c.l.filename; + n.lineno = c.l.lineno; + n.colno = c.l.colno; +} diff --git a/parse2.c b/parse2.c @@ -0,0 +1,915 @@ +struct parser { + a: *alloc; + p: *peg; +} + +setup_parser(a: *alloc): *parser { + var c: *parser; + + c = alloc(a, sizeof(*c)):*parser; + + c.a = a; + + c.p = peg_new("", "", 0, a); + + return c; +} + +parse(c: *parser, filename: *byte): *node { + var f: *file; + var fd: int; + var len: int; + var src: *byte; + var pn: *peg_node; + + fd = open(filename, 0, 0); + if fd < 0 { + fdputs(2, "failed to open "); + fdputs(2, filename); + fdputs(2, "\n"); + exit(1); + } + + f = fopen(fd, c.a); + src = freadall(f, &len); + fclose(f); + + peg_reset(c.p, filename, src, len); + pn = peg_parse(c.p, P_sp); + + return reconstruct(c, pn); +} + +fillpos(c: *parser, n: *node) { +} + +copypos(n: *node, pn: *peg_node) { + n.filename = pn.filename; + n.lineno = pn.line; + n.colno = pn.col; +} + +reconstruct(c: *parser, pn: *peg_node): *node { + var ret: *node; + var link: **node; + var n: *node; + var p: *node; + assert(pn.tag == P_grammar, "grammar"); + + ret = 0:*node; + link = &ret; + + pn = pn.child; + loop { + if !pn { + break; + } + + if pn.tag == P_enum_decl { + n = reconstruct_enum(c, pn); + } else if pn.tag == P_struct_decl { + n = reconstruct_struct(c, pn); + } else if pn.tag == P_func_decl { + n = reconstruct_func(c, pn); + } else { + die("invalid decl"); + } + + p = mknode1(c, N_PROGRAM, n); + copypos(p, pn); + + *link = p; + link = &p.b; + + pn = pn.next; + } + + return ret; +} + +reconstruct_intern(c: *parser, pn: *peg_node, s: *byte, len: int): *node { + var n: *node; + var i: int; + n = mknode0(c, N_IDENT); + copypos(n, pn); + i = 0; + n.s = alloc(c.a, len + 1); + loop { + if i == len { + break; + } + n.s[i] = s[i]; + i = i + 1; + } + n.s[i] = 0:byte; + return n; +} + +reconstruct_ident(c: *parser, pn: *peg_node): *node { + assert(pn.tag == P_ident, "ident"); + return reconstruct_intern(c, pn, pn.str, pn.len); +} + +reconstruct_enum_item(c: *parser, pn: *peg_node): *node { + var a: *node; + var b: *node; + var n: *node; + assert(pn.tag == P_enum_item, "enum_item"); + + a = reconstruct_ident(c, pn.child); + b = 0:*node; + + if pn.child.next { + b = reconstruct_expr(c, pn.child.next); + assert(b.kind == N_NUM, "enum must be num"); + } + + n = mknode(c, N_ENUMITEM, a, b); + copypos(n, pn); + + return n; +} + +reconstruct_enum(c: *parser, pn: *peg_node): *node { + var a: *node; + var link: **node; + var n: *node; + assert(pn.tag == P_enum_decl, "enum_decl"); + + n = mknode(c, N_ENUM, 0:*node, 0:*node); + copypos(n, pn); + + pn = pn.child.next; + link = &n.b; + loop { + if !pn { + break; + } + + a = mknode1(c, N_ENUMLIST, reconstruct_enum_item(c, pn)); + copypos(a, pn); + *link = a; + link = &a.b; + + pn = pn.next; + } + + return n; +} + +reconstruct_arg_decl(c: *parser, pn: *peg_node): *node { + var a: *node; + var b: *node; + var n: *node; + assert(pn.tag == P_arg_decl, "arg_decl"); + + a = reconstruct_ident(c, pn.child); + b = reconstruct_type(c, pn.child.next); + + n = mknode(c, N_ARGDECL, a, b); + copypos(n, pn); + + return n; +} + +reconstruct_func_type(c: *parser, pn: *peg_node): *node { + var a: *node; + var b: *node; + var n: *node; + var link: **node; + assert(pn.tag == P_func_type, "func_type"); + + n = mknode(c, N_FUNCTYPE, 0:*node, 0:*node); + copypos(n, pn); + + pn = pn.child; + link = &n.a; + loop { + if !pn { + break; + } + + if pn.tag == P_arg_decl { + a = mknode1(c, N_ARGLIST, reconstruct_arg_decl(c, pn)); + copypos(a, pn); + *link = a; + link = &a.b; + } else if pn.tag == P_type { + n.b = reconstruct_type(c, pn); + } else { + die("invalid func_type"); + } + + pn = pn.next; + } + + return n; +} + +reconstruct_type(c: *parser, pn: *peg_node): *node { + var n: *node; + assert(pn.tag == P_type, "type"); + pn = pn.child; + if pn.tag == P_ident { + return reconstruct_ident(c, pn); + } else if pn.tag == P_byte { + return reconstruct_intern(c, pn, "byte", 4); + } else if pn.tag == P_int { + return reconstruct_intern(c, pn, "int", 3); + } else if pn.tag == P_void { + return reconstruct_intern(c, pn, "void", 4); + } else if pn.tag == P_ptr_type { + n = mknode1(c, N_PTRTYPE, reconstruct_type(c, pn.child)); + copypos(n, pn); + return n; + } else if pn.tag == P_func { + return reconstruct_func_type(c, pn.next); + } else if pn.tag == P_type { + return reconstruct_type(c, pn); + } else { + die("reconstruct_type: invalid type"); + } +} + +reconstruct_member_decl(c: *parser, pn: *peg_node): *node { + var a: *node; + var b: *node; + var n: *node; + assert(pn.tag == P_member_decl, "member_decl"); + + a = reconstruct_ident(c, pn.child); + b = reconstruct_type(c, pn.child.next); + + n = mknode(c, N_MEMBERDECL, a, b); + copypos(n, pn); + + return n; +} + +reconstruct_member_list(c: *parser, pn: *peg_node): *node { + var n: *node; + var a: *node; + var ret: *node; + var link: **node; + + ret = 0:*node; + link = &ret; + loop { + if !pn { + break; + } + + a = reconstruct_member_decl(c, pn); + + n = mknode1(c, N_MEMBERLIST, a); + copypos(n, pn); + + *link = n; + link = &n.b; + + pn = pn.next; + } + + return ret; +} + +reconstruct_struct(c: *parser, pn: *peg_node): *node { + var n: *node; + var a: *node; + var b: *node; + assert(pn.tag == P_struct_decl, "struct_def"); + a = reconstruct_ident(c, pn.child.next); + b = reconstruct_member_list(c, pn.child.next.next); + n = mknode(c, N_STRUCT, a, b); + copypos(n, pn); + return n; +} + +reconstruct_expr(c: *parser, pn: *peg_node): *node { + assert(pn.tag == P_expr, "expr"); + return reconstruct_bool(c, pn.child); +} + +reconstruct_bool(c: *parser, pn: *peg_node): *node { + var ret: *node; + var n: *node; + var link: **node; + var kind: int; + assert(pn.tag == P_bool_expr, "bool_expr"); + + ret = reconstruct_comp(c, pn.child); + + link = &ret; + pn = pn.child.next; + loop { + if !pn { + break; + } + + if pn.tag == P_band_op { + kind = N_BAND; + } else if pn.tag == P_bor_op { + kind = N_BOR; + } else { + die("invalid boolop"); + } + + n = reconstruct_comp(c, pn.next); + *link = mknode(c, kind, *link, n); + copypos(*link, pn); + + pn = pn.next.next; + } + + return ret; +} + +reconstruct_comp(c: *parser, pn: *peg_node): *node { + var a: *node; + var b: *node; + var n: *node; + var kind: int; + var tag: int; + assert(pn.tag == P_comp_expr, "comp_expr"); + + a = reconstruct_add(c, pn.child); + if !pn.child.next { + return a; + } + + tag = pn.child.next.tag; + if tag == P_le_op { + kind = N_LE; + } else if tag == P_ge_op { + kind = N_GE; + } else if tag == P_lt_op { + kind = N_LT; + } else if tag == P_gt_op { + kind = N_GT; + } else if tag == P_eq_op { + kind = N_EQ; + } else if tag == P_ne_op { + kind = N_NE; + } else { + die("invalid compop"); + } + + b = reconstruct_add(c, pn.child.next.next); + + n = mknode(c, kind, a, b); + copypos(n, pn); + + return n; +} + +reconstruct_add(c: *parser, pn: *peg_node): *node { + var ret: *node; + var n: *node; + var link: **node; + var kind: int; + assert(pn.tag == P_add_expr, "add_expr"); + + ret = reconstruct_mul(c, pn.child); + + link = &ret; + pn = pn.child.next; + loop { + if !pn { + break; + } + + if pn.tag == P_add_op { + kind = N_ADD; + } else if pn.tag == P_sub_op { + kind = N_SUB; + } else if pn.tag == P_or_op { + kind = N_OR; + } else if pn.tag == P_xor_op { + kind = N_XOR; + } else { + die("invalid addop"); + } + + n = reconstruct_mul(c, pn.next); + *link = mknode(c, kind, *link, n); + copypos(*link, pn); + + pn = pn.next.next; + } + + return ret; +} + +reconstruct_mul(c: *parser, pn: *peg_node): *node { + var ret: *node; + var n: *node; + var link: **node; + var kind: int; + assert(pn.tag == P_mul_expr, "mul_expr"); + + ret = reconstruct_shift(c, pn.child); + + link = &ret; + pn = pn.child.next; + loop { + if !pn { + break; + } + + if pn.tag == P_mul_op { + kind = N_MUL; + } else if pn.tag == P_div_op { + kind = N_DIV; + } else if pn.tag == P_mod_op { + kind = N_MOD; + } else if pn.tag == P_and_op { + kind = N_AND; + } else { + die("invalid mulop"); + } + + n = reconstruct_shift(c, pn.next); + *link = mknode(c, kind, *link, n); + copypos(*link, pn); + + pn = pn.next.next; + } + + return ret; +} + +reconstruct_shift(c: *parser, pn: *peg_node): *node { + var ret: *node; + var n: *node; + var link: **node; + var kind: int; + assert(pn.tag == P_shift_expr, "shift_expr"); + + ret = reconstruct_unary(c, pn.child); + + link = &ret; + pn = pn.child.next; + loop { + if !pn { + break; + } + + if pn.tag == P_lsh_op { + kind = N_LSH; + } else if pn.tag == P_rsh_op { + kind = N_RSH; + } else { + die("invalid shift"); + } + + n = reconstruct_unary(c, pn.next); + *link = mknode(c, kind, *link, n); + copypos(*link, pn); + + pn = pn.next.next; + } + + return ret; +} + +reconstruct_unary(c: *parser, pn: *peg_node): *node { + var n: *node; + var ret: *node; + var link: **node; + var tag: int; + var kind: int; + assert(pn.tag == P_unary_expr, "unary_expr"); + + link = &ret; + pn = pn.child; + loop { + tag = pn.tag; + if tag == P_ref_op { + kind = N_REF; + } else if tag == P_deref_op { + kind = N_DEREF; + } else if tag == P_pos_op { + kind = N_POS; + } else if tag == P_neg_op { + kind = N_NEG; + } else if tag == P_not_op { + kind = N_NOT; + } else if tag == P_bnot_op { + kind = N_BNOT; + } else if tag == P_post_expr { + *link = reconstruct_post(c, pn); + return ret; + } else { + die("invalid unary_expr"); + } + + n = mknode0(c, kind); + copypos(n, pn); + *link = n; + link = &n.a; + + pn = pn.next; + } +} + +reconstruct_args(c: *parser, pn: *peg_node): *node { + var ret: *node; + var link: **node; + var a: *node; + var n: *node; + + ret = 0:*node; + link = &ret; + loop { + if !pn { + break; + } + + a = reconstruct_expr(c, pn); + n = mknode1(c, N_EXPRLIST, a); + copypos(n, pn); + + *link = n; + link = &n.b; + + pn = pn.next; + } + + return ret; +} + +reconstruct_post(c: *parser, pn: *peg_node): *node { + var ret: *node; + var n: *node; + var tag: int; + assert(pn.tag == P_post_expr, "post_expr"); + + ret = reconstruct_primary(c, pn.child); + + pn = pn.child.next; + loop { + if !pn { + break; + } + + tag = pn.tag; + + if tag == P_index_expr { + n = reconstruct_expr(c, pn.child); + ret = mknode(c, N_INDEX, ret, n); + copypos(ret, pn); + } else if tag == P_call_expr { + n = reconstruct_args(c, pn.child); + ret = mknode(c, N_CALL, ret, n); + copypos(ret, pn); + } else if tag == P_member_expr { + n = reconstruct_ident(c, pn.child); + ret = mknode(c, N_DOT, ret, n); + copypos(ret, pn); + } else if tag == P_cast_expr { + n = reconstruct_type(c, pn.child); + ret = mknode(c, N_CAST, ret, n); + copypos(ret, pn); + } else { + die("invalid post_expr"); + } + + pn = pn.next; + } + + return ret; +} + +reconstruct_primary(c: *parser, pn: *peg_node): *node { + assert(pn.tag == P_primary, "primary"); + pn = pn.child; + if pn.tag == P_ident { + return reconstruct_ident(c, pn); + } else if pn.tag == P_hex { + return reconstruct_hex(c, pn); + } else if pn.tag == P_dec { + return reconstruct_dec(c, pn); + } else if pn.tag == P_str { + return reconstruct_str(c, pn); + } else if pn.tag == P_char { + return reconstruct_char(c, pn); + } else if pn.tag == P_sizeof_expr { + return reconstruct_sizeof(c, pn); + } else if pn.tag == P_expr { + return reconstruct_expr(c, pn); + } else { + die("invalid primary"); + } +} + +reconstruct_hex(c: *parser, pn: *peg_node): *node { + var x: int; + var n: *node; + var ok: int; + assert(pn.tag == P_hex, "hex"); + x = hex2int(&pn.str[2], pn.len - 2, &ok); + if !ok { + die("invalid hex"); + } + n = mknode0(c, N_NUM); + copypos(n, pn); + n.n = x; + return n; +} + +reconstruct_dec(c: *parser, pn: *peg_node): *node { + var x: int; + var n: *node; + var ok: int; + assert(pn.tag == P_dec, "dec"); + x = dec2int(pn.str, pn.len, &ok); + if !ok { + die("invalid dec"); + } + n = mknode0(c, N_NUM); + copypos(n, pn); + n.n = x; + return n; +} + +reconstruct_str(c: *parser, pn: *peg_node): *node { + var i: int; + var j: int; + var len: int; + var ch: int; + var ok: int; + var s: *byte; + var n: *node; + assert(pn.tag == P_str, "str"); + s = alloc(c.a, pn.len); + i = 1; + j = 0; + len = pn.len - 1; + loop { + if i == len { + break; + } + ch = unescape(pn.str, &i, len, &ok); + if !ok { + die("invalid escape"); + } + s[j] = ch:byte; + j = j + 1; + } + s[j] = 0:byte; + n = mknode0(c, N_STR); + copypos(n, pn); + n.s = s; + return n; +} + +reconstruct_char(c: *parser, pn: *peg_node): *node { + var i: int; + var x: int; + var ok: int; + var n: *node; + assert(pn.tag == P_char, "char"); + i = 1; + x = unescape(pn.str, &i, pn.len - 1, &ok); + if !ok || i != pn.len - 1 { + die("invalid character"); + } + n = mknode0(c, N_CHAR); + copypos(n, pn); + n.n = x; + return n; +} +reconstruct_sizeof(c: *parser, pn: *peg_node): *node { + var n: *node; + var a: *node; + assert(pn.tag == P_sizeof_expr, "sizeof_expr"); + a = reconstruct_expr(c, pn.child.next); + n = mknode1(c, N_SIZEOF, a); + copypos(n, pn); + return n; +} + +reconstruct_stmt(c: *parser, pn: *peg_node): *node { + assert(pn.tag == P_stmt, "stmt"); + pn = pn.child; + if pn.tag == P_if_stmt { + return reconstruct_if(c, pn); + } else if pn.tag == P_loop_stmt { + return reconstruct_loop(c, pn); + } else if pn.tag == P_break_stmt { + return reconstruct_break(c, pn); + } else if pn.tag == P_continue_stmt { + return reconstruct_continue(c, pn); + } else if pn.tag == P_return_stmt { + return reconstruct_return(c, pn); + } else if pn.tag == P_var_stmt { + return reconstruct_var(c, pn); + } else if pn.tag == P_label_stmt { + return reconstruct_label(c, pn); + } else if pn.tag == P_goto_stmt { + return reconstruct_goto(c, pn); + } else if pn.tag == P_assign_stmt { + return reconstruct_assign(c, pn); + } else if pn.tag == P_expr_stmt { + return reconstruct_expr_stmt(c, pn); + } else if pn.tag == P_empty_stmt { + return reconstruct_empty(c, pn); + } else if pn.tag == P_compound_stmt { + return reconstruct_compound(c, pn); + } else { + die("invalid stmt"); + } +} + +reconstruct_if(c: *parser, pn: *peg_node): *node { + var ret: *node; + var link: **node; + var a: *node; + var b: *node; + var n: *node; + assert(pn.tag == P_if_stmt, "if_stmt"); + + a = reconstruct_expr(c, pn.child.next); + b = reconstruct_compound(c, pn.child.next.next); + ret = mknode1(c, N_CONDLIST, mknode(c, N_COND, a, b)); + copypos(ret, pn); + copypos(ret.a, pn); + + link = &ret.b; + pn = pn.child.next.next.next; + loop { + if !pn { + break; + } + + if pn.tag == P_elif_stmt { + a = reconstruct_expr(c, pn.child.next.next); + b = reconstruct_compound(c, pn.child.next.next.next); + n = mknode1(c, N_CONDLIST, mknode(c, N_COND, a, b)); + copypos(n, pn); + copypos(n.a, pn); + *link = n; + link = &n.b; + } else if pn.tag == P_else_stmt { + a = 0:*node; + b = reconstruct_compound(c, pn.child.next); + n = mknode1(c, N_CONDLIST, mknode(c, N_COND, a, b)); + copypos(n, pn); + copypos(n.a, pn); + *link = n; + link = &n.b; + break; + } else { + die("invalid if_stmt"); + } + + pn = pn.next; + } + + return ret; +} + +reconstruct_loop(c: *parser, pn: *peg_node): *node { + var n: *node; + var a: *node; + assert(pn.tag == P_loop_stmt, "loop_stmt"); + a = reconstruct_compound(c, pn.child.next); + n = mknode1(c, N_LOOP, a); + copypos(n, pn); + return n; +} + +reconstruct_break(c: *parser, pn: *peg_node): *node { + var n: *node; + assert(pn.tag == P_break_stmt, "break_stmt"); + n = mknode0(c, N_BREAK); + copypos(n, pn); + return n; +} + +reconstruct_continue(c: *parser, pn: *peg_node): *node { + var n: *node; + assert(pn.tag == P_continue_stmt, "continue_stmt"); + n = mknode0(c, N_CONTINUE); + copypos(n, pn); + return n; +} + +reconstruct_return(c: *parser, pn: *peg_node): *node { + var a: *node; + var n: *node; + assert(pn.tag == P_return_stmt, "return_stmt"); + a = 0:*node; + if pn.child.next { + a = reconstruct_expr(c, pn.child.next); + } + n = mknode1(c, N_RETURN, a); + copypos(n, pn); + return n; +} + +reconstruct_var(c: *parser, pn: *peg_node): *node { + var a: *node; + var b: *node; + var n: *node; + assert(pn.tag == P_var_stmt, "var_stmt"); + a = reconstruct_ident(c, pn.child.next); + b = reconstruct_type(c, pn.child.next.next); + n = mknode(c, N_VARDECL, a, b); + copypos(n, pn); + return n; +} + +reconstruct_label(c: *parser, pn: *peg_node): *node { + var a: *node; + var n: *node; + assert(pn.tag == P_label_stmt, "label_stmt"); + a = reconstruct_ident(c, pn.child); + n = mknode1(c, N_LABEL, a); + copypos(n, pn); + return n; +} + +reconstruct_goto(c: *parser, pn: *peg_node): *node { + var a: *node; + var n: *node; + assert(pn.tag == P_goto_stmt, "goto_stmt"); + a = reconstruct_ident(c, pn.child.next); + n = mknode1(c, N_GOTO, a); + copypos(n, pn); + return n; +} + +reconstruct_assign(c: *parser, pn: *peg_node): *node { + var a: *node; + var b: *node; + var n: *node; + assert(pn.tag == P_assign_stmt, "assign_stmt"); + a = reconstruct_unary(c, pn.child); + b = reconstruct_expr(c, pn.child.next); + n = mknode(c, N_ASSIGN, a, b); + copypos(n, pn); + return n; +} + +reconstruct_expr_stmt(c: *parser, pn: *peg_node): *node { + assert(pn.tag == P_expr_stmt, "expr_stmt"); + return reconstruct_expr(c, pn.child); +} + +reconstruct_empty(c: *parser, pn: *peg_node): *node { + assert(pn.tag == P_empty_stmt, "empty_stmt"); + return 0:*node; +} + +reconstruct_compound(c: *parser, pn: *peg_node): *node { + var ret: *node; + var n: *node; + var a: *node; + var link: **node; + assert(pn.tag == P_compound_stmt, "compound_stmt"); + pn = pn.child; + ret = 0:*node; + link = &ret; + loop { + if ! pn { + break; + } + + a = reconstruct_stmt(c, pn); + if a { + n = mknode1(c, N_STMTLIST, a); + copypos(n, pn); + *link = n; + link = &n.b; + } + + pn = pn.next; + } + return ret; +} + +reconstruct_func(c: *parser, pn: *peg_node): *node { + var a: *node; + var b: *node; + var d: *node; + var n: *node; + assert(pn.tag == P_func_decl, "func_def"); + + a = reconstruct_ident(c, pn.child); + b = reconstruct_func_type(c, pn.child.next); + + d = mknode(c, N_FUNCDECL, a, b); + copypos(d, pn); + + if !pn.child.next.next { + return d; + } + + b = reconstruct_compound(c, pn.child.next.next); + + n = mknode(c, N_FUNC, d, b); + copypos(n, pn); + + return n; +} diff --git a/peg.c b/peg.c @@ -101,28 +101,9 @@ translate_literal(c: *compiler, n: *peg_node) { fputs(c.out, "\");\n"); } -hexdig(c: byte): int { - var ch: int; - - ch = c:int; - - if ch >= '0' && ch <= '9' { - return ch - '0'; - } - - if ch >= 'a' && ch <= 'f' { - return ch - 'a' + 10; - } - - if ch >= 'A' && ch <= 'F' { - return ch - 'A' + 10; - } - - die("invalid hex digit"); -} - parse_escape(s: *byte, i: *int, n: int): int { var nc: int; + var ok: int; if *i == n { die("invalid escape"); @@ -153,7 +134,14 @@ parse_escape(s: *byte, i: *int, n: int): int { if n - *i < 2 { die("invalid escape"); } - nc = hexdig(s[*i]) * 16 + hexdig(s[*i + 1]); + nc = hexdig(s[*i]:int, &ok) * 16; + if !ok { + die("invalid hex"); + } + nc = nc + hexdig(s[*i + 1]:int, &ok); + if !ok { + die("invalid hex"); + } *i = *i + 2; return nc; } else { diff --git a/peglib.c b/peglib.c @@ -12,6 +12,8 @@ struct peg_op { nargs: int; start: int; end: int; + line: int; + col: int; } struct peg { @@ -52,6 +54,9 @@ struct peg_node { child: *peg_node; str: *byte; len: int; + filename: *byte; + line: int; + col: int; } choice(c: *peg) { @@ -150,6 +155,8 @@ enter(c: *peg, tag: int) { leave(c: *peg, tag: int) { var nargs: int; var start: int; + var line: int; + var col: int; var end: int; var tmp: *byte; @@ -157,6 +164,8 @@ leave(c: *peg, tag: int) { c.fail_depth = 0; nargs = c.depth - c.stack[c.sp].depth; + line = c.stack[c.sp].line; + col = c.stack[c.sp].col; start = c.stack[c.sp].pos; end = c.pos; @@ -177,6 +186,8 @@ leave(c: *peg, tag: int) { c.out[c.op].nargs = nargs; c.out[c.op].start = start; c.out[c.op].end = end; + c.out[c.op].line = line; + c.out[c.op].col = col; c.op = c.op + 1; c.depth = c.depth - nargs + 1; @@ -230,39 +241,44 @@ construct(c: *peg, sp: int): *peg_node { return c.nstack[0]; } - n = alloc(c.a, sizeof(*n)):*peg_node; + if c.out[i].tag != sp { + n = alloc(c.a, sizeof(*n)):*peg_node; + + n.tag = c.out[i].tag; + n.next = 0:*peg_node; + n.child = 0:*peg_node; + n.str = &c.src[c.out[i].start]; + n.len = c.out[i].end - c.out[i].start; + n.filename = c.filename; + n.line = c.out[i].line; + n.col = c.out[i].col; + + nargs = c.out[i].nargs; + if nargs > c.np { + die("node underflow"); + } - n.tag = c.out[i].tag; - n.next = 0:*peg_node; - n.child = 0:*peg_node; - n.str = &c.src[c.out[i].start]; - n.len = c.out[i].end - c.out[i].start; + link = &n.child; + j = c.np - nargs; + loop { + if j == c.np { + break; + } - nargs = c.out[i].nargs; - if nargs > c.np { - die("node underflow"); - } + if c.nstack[j] { + *link = c.nstack[j]; + link = &c.nstack[j].next; + } - link = &n.child; - j = c.np - nargs; - loop { - if j == c.np { - break; + j = j + 1; } - if c.nstack[j].tag != sp { - *link = c.nstack[j]; - link = &c.nstack[j].next; - } else { - free(c.a, c.nstack[j]:*byte); + c.np = c.np - nargs; + if c.np == c.ncap { + die("node overflow"); } - - j = j + 1; - } - - c.np = c.np - nargs; - if c.np == c.ncap { - die("node overflow"); + } else { + n = 0:*peg_node; } c.nstack[c.np] = n; @@ -334,7 +350,8 @@ peg_parse(c: *peg, sp: int): *peg_node { return construct(c, sp); } -peg_reset(c: *peg, src: *byte, len: int) { +peg_reset(c: *peg, filename: *byte, src: *byte, len: int) { + c.filename = filename; c.src = src; c.size = len; c.pos = 0; diff --git a/type.c b/type.c @@ -110,6 +110,14 @@ mktype2(c: *compiler, kind: int, a: *type, b: *type): *type { return mktype(c, kind, a, b, 0:*decl); } +type_isint(t: *type): int { + return t.kind == TY_INT || t.kind == TY_BYTE; +} + +type_isprim(t: *type): int { + return t.kind != TY_VOID && t.kind != TY_STRUCT; +} + prototype(c: *compiler, n: *node): *type { var a: *type; var b: *type; @@ -176,11 +184,3 @@ prototype(c: *compiler, n: *node): *type { cdie(c, "prototype: invalid type"); } } - -type_isint(t: *type): int { - return t.kind == TY_INT || t.kind == TY_BYTE; -} - -type_isprim(t: *type): int { - return t.kind != TY_VOID && t.kind != TY_STRUCT; -} diff --git a/watch.sh b/watch.sh @@ -1,6 +1,6 @@ #!/bin/sh clear -time sh -e ./build.sh +timeout 1 time sh -e ./build.sh echo status $? : < ~/.post exec "$0"