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:
M | bootstrap.sh | | | 2 | +- |
M | bufio.c | | | 2 | ++ |
M | build.sh | | | 28 | ++++++++++++++-------------- |
M | cc1.c | | | 316 | ++++++++++++++++++++----------------------------------------------------------- |
M | cc3.peg | | | 165 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
A | decl.c | | | 168 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
R | cc3.c -> dump.c | | | 0 | |
M | lex1.c | | | 121 | +++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------- |
M | lib.c | | | 162 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | node.c | | | 206 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | parse1.c | | | 729 | ++++++++++++++++++++++++++++++++++++------------------------------------------- |
A | parse2.c | | | 915 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | peg.c | | | 30 | +++++++++--------------------- |
M | peglib.c | | | 73 | +++++++++++++++++++++++++++++++++++++++++++++---------------------------- |
M | type.c | | | 16 | ++++++++-------- |
M | watch.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"