os

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

cc4.om (14749B)


      1 enum {
      2 	LEFT_BRACE,
      3 	RIGHT_BRACE,
      4 	LEFT_SQUARE,
      5 	RIGHT_SQUARE,
      6 	LEFT_PAREN,
      7 	RIGHT_PAREN,
      8 	DOT,
      9 	ASSIGN,
     10 	SEMI,
     11 	COLON,
     12 	QMARK,
     13 	STAR,
     14 	AMP,
     15 	COMMA,
     16 	BANG,
     17 	PLUS,
     18 	MINUS,
     19 	NOT,
     20 	SLASH,
     21 	MOD,
     22 	PIPE,
     23 	XOR,
     24 	AND_THEN,
     25 	OR_ELSE,
     26 	LE,
     27 	GE,
     28 	LT,
     29 	GT,
     30 	EQ,
     31 	NE,
     32 	LEFT_SHIFT,
     33 	RIGHT_SHIFT,
     34 	RETURN,
     35 	BREAK,
     36 	SIZEOF,
     37 	IF,
     38 	ELSE,
     39 	LOOP,
     40 	CONTINUE,
     41 	GOTO,
     42 	VAR,
     43 	ENUM,
     44 	STRUCT,
     45 	UNION,
     46 	BYTE,
     47 	INT,
     48 	VOID,
     49 	FUNC,
     50 	AS,
     51 	NIL,
     52 	LEX,
     53 	LALR,
     54 	IDENT,
     55 	NUMBER,
     56 	STRING,
     57 	CHARSET,
     58 }
     59 
     60 lexer {
     61 	"{" { return LEFT_BRACE; }
     62 	"}" { return RIGHT_BRACE; }
     63 
     64 	"[" { return LEFT_SQUARE; }
     65 	"]" { return RIGHT_SQUARE; }
     66 
     67 	"(" { return LEFT_PAREN; }
     68 	")" { return RIGHT_PAREN; }
     69 
     70 	"." { return DOT; }
     71 	"=" { return ASSIGN; }
     72 	";" { return SEMI; }
     73 	":" { return COLON; }
     74 	"?" { return QMARK; }
     75 	"*" { return STAR; }
     76 	"&" { return AMP; }
     77 	"," { return COMMA; }
     78 	"!" { return BANG; }
     79 	"+" { return PLUS; }
     80 	"-" { return MINUS; }
     81 	"~" { return NOT; }
     82 	"/" { return SLASH; }
     83 	"%" { return MOD; }
     84 	"|" { return PIPE; }
     85 	"^" { return XOR; }
     86 
     87 	"&&" { return AND_THEN; }
     88 	"||" { return OR_ELSE; }
     89 
     90 	"<=" { return LE; }
     91 	">=" { return GE; }
     92 	"<" { return LT; }
     93 	">" { return GT; }
     94 	"==" { return EQ; }
     95 	"!=" { return NE; }
     96 
     97 	"<<" { return LEFT_SHIFT; }
     98 	">>" { return RIGHT_SHIFT; }
     99 
    100 	"return" { return RETURN; }
    101 	"break" { return BREAK; }
    102 	"sizeof" { return SIZEOF; }
    103 	"if" { return IF; }
    104 	"else" { return ELSE; }
    105 	"loop" { return LOOP; }
    106 	"continue" { return CONTINUE; }
    107 	"goto" { return GOTO; }
    108 	"var" { return VAR; }
    109 	"enum" { return ENUM; }
    110 	"struct" { return STRUCT; }
    111 	"union" { return UNION; }
    112 	"byte" { return BYTE; }
    113 	"int" { return INT; }
    114 	"void" { return VOID; }
    115 	"func" { return FUNC; }
    116 	"as" { return AS; }
    117 	"nil" { return NIL; }
    118 	"lexer" { return LEX; }
    119 	"lalr" { return LALR; }
    120 
    121 	["a-zA-Z_"]["a-zA-Z0-9_"]* {
    122 		var n: *node;
    123 		n = mknode(ctx.c.p, N_IDENT, nil, nil);
    124 		n.s = mkstr(ctx.a, &ctx.buf[ctx.start], ctx.end - ctx.start);
    125 		ctx.val.n = n;
    126 		return IDENT;
    127 	}
    128 
    129 	"0b" ["01"] (["01_"]* ["01"])? {
    130 		var n: *node;
    131 		var ok: int;
    132 		n = mknode(ctx.c.p, N_NUM, nil, nil);
    133 		n.n = bin2int(&ctx.buf[ctx.start + 2], ctx.end - ctx.start - 2, &ok);
    134 		if !ok {
    135 			die("invalid bin");
    136 		}
    137 		ctx.val.n = n;
    138 		return NUMBER;
    139 	}
    140 
    141 	"0x" ["0-9a-fA-F"] (["0-9a-fA-F_"]* ["0-9a-fA-F"])? {
    142 		var n: *node;
    143 		var ok: int;
    144 		n = mknode(ctx.c.p, N_NUM, nil, nil);
    145 		n.n = hex2int(&ctx.buf[ctx.start + 2], ctx.end - ctx.start - 2, &ok);
    146 		if !ok {
    147 			die("invalid hex");
    148 		}
    149 		ctx.val.n = n;
    150 		return NUMBER;
    151 	}
    152 
    153 	["0-9"] (["0-9_"]* ["0-9"])? {
    154 		var n: *node;
    155 		var x: int;
    156 		var ok: int;
    157 		n = mknode(ctx.c.p, N_NUM, nil, nil);
    158 		n.n = dec2int(&ctx.buf[ctx.start], ctx.end - ctx.start, &ok);
    159 		if !ok {
    160 			die("invalid dec");
    161 		}
    162 		ctx.val.n = n;
    163 		return NUMBER;
    164 	}
    165 
    166 	"'" ("\\" . | ["^\\\x27"])* "'" {
    167 		var n: *node;
    168 		var i: int;
    169 		var x: int;
    170 		var ok: int;
    171 		n = mknode(ctx.c.p, N_NUM, nil, nil);
    172 		i = ctx.start + 1;
    173 		n.n = unescape(ctx.buf, &i, ctx.end - 1, &ok);
    174 		if !ok || i != ctx.end - 1 {
    175 			die("invalid char");
    176 		}
    177 		ctx.val.n = n;
    178 		return NUMBER;
    179 	}
    180 
    181 	"\"" ("\\" . | ["^\\\x22"])* "\"" {
    182 		var n: *node;
    183 		var i: int;
    184 		var j: int;
    185 		var ok: int;
    186 		n = mknode(ctx.c.p, N_STR, nil, nil);
    187 		n.s = alloc(ctx.a, ctx.end - ctx.start);
    188 		i = ctx.start + 1;
    189 		j = 0;
    190 		loop {
    191 			if i == ctx.end - 1 {
    192 				break;
    193 			}
    194 			n.s[j] = unescape(ctx.buf, &i, ctx.end - 1, &ok) as byte;
    195 			if !ok {
    196 				die("invalid string");
    197 			}
    198 			j = j + 1;
    199 		}
    200 		n.s[j] = 0 as byte;
    201 		ctx.val.n = n;
    202 		return STRING;
    203 	}
    204 
    205 	"[\"" (["^\"\\"] | "\\".)* "\"]" {
    206 		var n: *node;
    207 		n = mknode(ctx.c.p, N_CHARSET, nil, nil);
    208 		n.s = parse_charset(ctx.a, &ctx.buf[ctx.start + 2], ctx.end - ctx.start - 4);
    209 		ctx.val.n = n;
    210 		return CHARSET;
    211 	}
    212 
    213 	[" \r\n\t"] { }
    214 	"//" ["^\n"]* "\n" { }
    215 }
    216 
    217 lalr {
    218 	grammar
    219 		= decl_list { ctx.val.n = ctx.sem[0].n; }
    220 	;
    221 
    222 	decl_list
    223 		= decl_list decl { ctx.val.n = mknode(ctx.c.p, N_PROGRAM, ctx.sem[1].n, ctx.sem[0].n); }
    224 		| { ctx.val.n = nil; }
    225 	;
    226 
    227 	decl
    228 		= enum_decl { ctx.val.n = ctx.sem[0].n; }
    229 		| struct_decl { ctx.val.n = ctx.sem[0].n; }
    230 		| union_decl { ctx.val.n = ctx.sem[0].n; }
    231 		| func_def { ctx.val.n = ctx.sem[0].n; }
    232 		| lexer_grammar { ctx.val.n = ctx.sem[0].n; }
    233 		| lalr_grammar { ctx.val.n = ctx.sem[0].n; }
    234 	;
    235 
    236 	enum_item
    237 		= IDENT { ctx.val.n = mknode(ctx.c.p, N_ENUMITEM, ctx.sem[0].n, nil); }
    238 		| IDENT ASSIGN expr { ctx.val.n = mknode(ctx.c.p, N_ENUMITEM, ctx.sem[0].n, ctx.sem[2].n); }
    239 	;
    240 
    241 	enum_item_list
    242 		= enum_item COMMA enum_item_list { ctx.val.n = mknode(ctx.c.p, N_ENUMLIST, ctx.sem[0].n, ctx.sem[2].n); }
    243 		| enum_item COMMA { ctx.val.n = mknode(ctx.c.p, N_ENUMLIST, ctx.sem[0].n, nil); }
    244 		| enum_item { ctx.val.n = mknode(ctx.c.p, N_ENUMLIST, ctx.sem[0].n, nil); };
    245 
    246 	enum_decl
    247 		= ENUM LEFT_BRACE enum_item_list RIGHT_BRACE { ctx.val.n = mknode(ctx.c.p, N_ENUM, ctx.sem[2].n, nil); }
    248 	;
    249 
    250 	member_decl
    251 		= IDENT COLON type_decl SEMI { ctx.val.n = mknode(ctx.c.p, N_MEMBERDECL, ctx.sem[0].n, ctx.sem[2].n); }
    252 	;
    253 
    254 	member_decl_list
    255 		= member_decl member_decl_list { ctx.val.n = mknode(ctx.c.p, N_MEMBERLIST, ctx.sem[0].n, ctx.sem[1].n); }
    256 		| { ctx.val.n = nil; }
    257 	;
    258 
    259 	struct_decl
    260 		= STRUCT IDENT LEFT_BRACE member_decl_list RIGHT_BRACE { ctx.val.n = mknode(ctx.c.p, N_STRUCT, ctx.sem[1].n, ctx.sem[3].n); }
    261 	;
    262 
    263 	union_decl
    264 		= UNION IDENT LEFT_BRACE member_decl_list RIGHT_BRACE { ctx.val.n = mknode(ctx.c.p, N_UNION, ctx.sem[1].n, ctx.sem[3].n); }
    265 	;
    266 
    267 	type_decl
    268 		= IDENT { ctx.val.n = ctx.sem[0].n; }
    269 		| BYTE { ctx.val.n = mkident(ctx.c.p, "byte"); }
    270 		| INT { ctx.val.n = mkident(ctx.c.p, "int"); }
    271 		| VOID { ctx.val.n = mkident(ctx.c.p, "void"); }
    272 		| FUNC func_type { ctx.val.n = ctx.sem[1].n; }
    273 		| STAR type_decl { ctx.val.n = mknode(ctx.c.p, N_PTRTYPE, ctx.sem[1].n, nil); }
    274 		| LEFT_PAREN type_decl RIGHT_PAREN { ctx.val.n = ctx.sem[1].n; }
    275 	;
    276 
    277 	arg_decl
    278 		= IDENT COLON type_decl { ctx.val.n = mknode(ctx.c.p, N_ARGDECL, ctx.sem[0].n, ctx.sem[2].n); }
    279 	;
    280 
    281 	arg_decl_list
    282 		= arg_decl COMMA arg_decl_list { ctx.val.n = mknode(ctx.c.p, N_ARGLIST, ctx.sem[0].n, ctx.sem[2].n); }
    283 		| arg_decl { ctx.val.n = mknode(ctx.c.p, N_ARGLIST, ctx.sem[0].n, nil); }
    284 		| { ctx.val.n = nil; }
    285 	;
    286 
    287 	func_return_type
    288 		= COLON type_decl { ctx.val.n = ctx.sem[1].n; }
    289 		| { ctx.val.n = nil; }
    290 	;
    291 
    292 	func_type
    293 		= LEFT_PAREN arg_decl_list RIGHT_PAREN func_return_type { ctx.val.n = mknode(ctx.c.p, N_FUNCTYPE, ctx.sem[1].n, ctx.sem[3].n); }
    294 	;
    295 
    296 	func_decl
    297 		= FUNC IDENT func_type { ctx.val.n = mknode(ctx.c.p, N_FUNCDECL, ctx.sem[1].n, ctx.sem[2].n); }
    298 	;
    299 
    300 	func_def
    301 		= func_decl SEMI { ctx.val.n = ctx.sem[0].n; }
    302 		| func_decl compound_stmt { ctx.val.n = mknode(ctx.c.p, N_FUNC, ctx.sem[0].n, ctx.sem[1].n); }
    303 	;
    304 
    305 	stmt
    306 		= if_stmt { ctx.val.n = ctx.sem[0].n; }
    307 		| loop_stmt { ctx.val.n = ctx.sem[0].n; }
    308 		| break_stmt { ctx.val.n = ctx.sem[0].n; }
    309 		| continue_stmt { ctx.val.n = ctx.sem[0].n; }
    310 		| return_stmt { ctx.val.n = ctx.sem[0].n; }
    311 		| var_stmt { ctx.val.n = ctx.sem[0].n; }
    312 		| label_stmt { ctx.val.n = ctx.sem[0].n; }
    313 		| goto_stmt { ctx.val.n = ctx.sem[0].n; }
    314 		| assign_stmt { ctx.val.n = ctx.sem[0].n; }
    315 		| expr_stmt { ctx.val.n = ctx.sem[0].n; }
    316 		| empty_stmt { ctx.val.n = ctx.sem[0].n; }
    317 		| compound_stmt { ctx.val.n = ctx.sem[0].n; }
    318 	;
    319 
    320 	if_stmt
    321 		= IF expr compound_stmt { ctx.val.n = mknode(ctx.c.p, N_CONDLIST, mknode(ctx.c.p, N_COND, ctx.sem[1].n, ctx.sem[2].n), nil); }
    322 		| IF expr compound_stmt ELSE if_stmt { ctx.val.n = mknode(ctx.c.p, N_CONDLIST, mknode(ctx.c.p, N_COND, ctx.sem[1].n, ctx.sem[2].n), ctx.sem[4].n); }
    323 		| IF expr compound_stmt ELSE compound_stmt {
    324 			var n: *node;
    325 			n = mknode(ctx.c.p, N_CONDLIST, mknode(ctx.c.p, N_COND, nil, ctx.sem[4].n), n);
    326 			n = mknode(ctx.c.p, N_CONDLIST, mknode(ctx.c.p, N_COND, ctx.sem[1].n, ctx.sem[2].n), n);
    327 			ctx.val.n = n;
    328 		}
    329 	;
    330 
    331 	loop_stmt
    332 		= LOOP compound_stmt { ctx.val.n = mknode(ctx.c.p, N_LOOP, ctx.sem[1].n, nil); }
    333 	;
    334 
    335 	break_stmt
    336 		= BREAK SEMI { ctx.val.n = mknode(ctx.c.p, N_BREAK, nil, nil); }
    337 	;
    338 
    339 	continue_stmt
    340 		= CONTINUE SEMI { ctx.val.n = mknode(ctx.c.p, N_CONTINUE, nil, nil); }
    341 	;
    342 
    343 	return_stmt
    344 		= RETURN expr SEMI { ctx.val.n = mknode(ctx.c.p, N_RETURN, ctx.sem[1].n, nil); }
    345 		| RETURN SEMI { ctx.val.n = mknode(ctx.c.p, N_RETURN, nil, nil); }
    346 	;
    347 
    348 	var_stmt
    349 		= VAR IDENT COLON type_decl SEMI { ctx.val.n = mknode(ctx.c.p, N_VARDECL, ctx.sem[1].n, ctx.sem[3].n); }
    350 	;
    351 
    352 	label_stmt
    353 		= IDENT COLON { ctx.val.n = mknode(ctx.c.p, N_LABEL, ctx.sem[0].n, nil); }
    354 	;
    355 
    356 	goto_stmt
    357 		= GOTO IDENT SEMI { ctx.val.n = mknode(ctx.c.p, N_GOTO, ctx.sem[1].n, nil); }
    358 	;
    359 
    360 	assign_stmt
    361 		= unary_expr ASSIGN expr SEMI { ctx.val.n = mknode(ctx.c.p, N_ASSIGN, ctx.sem[0].n, ctx.sem[2].n); }
    362 	;
    363 
    364 	expr_stmt
    365 		= expr SEMI { ctx.val.n = ctx.sem[0].n; }
    366 	;
    367 
    368 	empty_stmt
    369 		= SEMI { ctx.val.n = nil; }
    370 	;
    371 
    372 	stmt_list
    373 		= stmt stmt_list { ctx.val.n = mknode(ctx.c.p, N_STMTLIST, ctx.sem[0].n, ctx.sem[1].n); }
    374 		| { ctx.val.n = nil; }
    375 	;
    376 
    377 	compound_stmt
    378 		= LEFT_BRACE stmt_list RIGHT_BRACE { ctx.val.n = ctx.sem[1].n; }
    379 	;
    380 
    381 	expr
    382 		= expr AND_THEN comp_expr { ctx.val.n = mknode(ctx.c.p, N_BAND, ctx.sem[0].n, ctx.sem[2].n); }
    383 		| expr OR_ELSE comp_expr { ctx.val.n = mknode(ctx.c.p, N_BOR, ctx.sem[0].n, ctx.sem[2].n); }
    384 		| comp_expr { ctx.val.n = ctx.sem[0].n; }
    385 	;
    386 
    387 	comp_expr
    388 		= add_expr LE add_expr { ctx.val.n = mknode(ctx.c.p, N_LE, ctx.sem[0].n, ctx.sem[2].n); }
    389 		| add_expr GE add_expr { ctx.val.n = mknode(ctx.c.p, N_GE, ctx.sem[0].n, ctx.sem[2].n); }
    390 		| add_expr LT add_expr { ctx.val.n = mknode(ctx.c.p, N_LT, ctx.sem[0].n, ctx.sem[2].n); }
    391 		| add_expr GT add_expr { ctx.val.n = mknode(ctx.c.p, N_GT, ctx.sem[0].n, ctx.sem[2].n); }
    392 		| add_expr EQ add_expr { ctx.val.n = mknode(ctx.c.p, N_EQ, ctx.sem[0].n, ctx.sem[2].n); }
    393 		| add_expr NE add_expr { ctx.val.n = mknode(ctx.c.p, N_NE, ctx.sem[0].n, ctx.sem[2].n); }
    394 		| add_expr { ctx.val.n = ctx.sem[0].n; }
    395 	;
    396 
    397 	add_expr
    398 		= add_expr PLUS mul_expr { ctx.val.n = mknode(ctx.c.p, N_ADD, ctx.sem[0].n, ctx.sem[2].n); }
    399 		| add_expr MINUS mul_expr { ctx.val.n = mknode(ctx.c.p, N_SUB, ctx.sem[0].n, ctx.sem[2].n); }
    400 		| add_expr PIPE mul_expr { ctx.val.n = mknode(ctx.c.p, N_OR, ctx.sem[0].n, ctx.sem[2].n); }
    401 		| add_expr XOR mul_expr { ctx.val.n = mknode(ctx.c.p, N_XOR, ctx.sem[0].n, ctx.sem[2].n); }
    402 		| mul_expr { ctx.val.n = ctx.sem[0].n; }
    403 	;
    404 
    405 	mul_expr
    406 		= mul_expr STAR shift_expr { ctx.val.n = mknode(ctx.c.p, N_MUL, ctx.sem[0].n, ctx.sem[2].n); }
    407 		| mul_expr SLASH shift_expr { ctx.val.n = mknode(ctx.c.p, N_DIV, ctx.sem[0].n, ctx.sem[2].n); }
    408 		| mul_expr MOD shift_expr { ctx.val.n = mknode(ctx.c.p, N_MOD, ctx.sem[0].n, ctx.sem[2].n); }
    409 		| mul_expr AMP shift_expr { ctx.val.n = mknode(ctx.c.p, N_AND, ctx.sem[0].n, ctx.sem[2].n); }
    410 		| shift_expr { ctx.val.n = ctx.sem[0].n; }
    411 	;
    412 
    413 	shift_expr
    414 		= shift_expr LEFT_SHIFT unary_expr { ctx.val.n = mknode(ctx.c.p, N_LSH, ctx.sem[0].n, ctx.sem[2].n); }
    415 		| shift_expr RIGHT_SHIFT unary_expr { ctx.val.n = mknode(ctx.c.p, N_RSH, ctx.sem[0].n, ctx.sem[2].n); }
    416 		| unary_expr { ctx.val.n = ctx.sem[0].n; }
    417 	;
    418 
    419 	unary_expr
    420 		= AMP unary_expr { ctx.val.n = mknode(ctx.c.p, N_REF, ctx.sem[1].n, nil); }
    421 		| STAR unary_expr { ctx.val.n = mknode(ctx.c.p, N_DEREF, ctx.sem[1].n, nil); }
    422 		| PLUS unary_expr { ctx.val.n = mknode(ctx.c.p, N_POS, ctx.sem[1].n, nil); }
    423 		| MINUS unary_expr { ctx.val.n = mknode(ctx.c.p, N_NEG, ctx.sem[1].n, nil); }
    424 		| NOT unary_expr { ctx.val.n = mknode(ctx.c.p, N_NOT, ctx.sem[1].n, nil); }
    425 		| BANG unary_expr { ctx.val.n = mknode(ctx.c.p, N_BNOT, ctx.sem[1].n, nil); }
    426 		| post_expr { ctx.val.n = ctx.sem[0].n; }
    427 	;
    428 
    429 	expr_list
    430 		= expr COMMA expr_list { ctx.val.n = mknode(ctx.c.p, N_EXPRLIST, ctx.sem[0].n, ctx.sem[2].n); }
    431 		| expr { ctx.val.n = mknode(ctx.c.p, N_EXPRLIST, ctx.sem[0].n, nil); }
    432 		| { ctx.val.n = nil; }
    433 	;
    434 
    435 	post_expr
    436 		= post_expr LEFT_SQUARE expr RIGHT_SQUARE { ctx.val.n = mknode(ctx.c.p, N_INDEX, ctx.sem[0].n, ctx.sem[2].n); }
    437 		| post_expr LEFT_PAREN expr_list RIGHT_PAREN { ctx.val.n = mknode(ctx.c.p, N_CALL, ctx.sem[0].n, ctx.sem[2].n); }
    438 		| post_expr DOT IDENT { ctx.val.n = mknode(ctx.c.p, N_DOT, ctx.sem[0].n, ctx.sem[2].n); }
    439 		| post_expr AS type_decl { ctx.val.n = mknode(ctx.c.p, N_CAST, ctx.sem[0].n, ctx.sem[2].n);}
    440 		| primary { ctx.val.n = ctx.sem[0].n; }
    441 	;
    442 
    443 	primary
    444 		= IDENT { ctx.val.n = ctx.sem[0].n; }
    445 		| NUMBER { ctx.val.n = ctx.sem[0].n; }
    446 		| STRING { ctx.val.n = ctx.sem[0].n; }
    447 		| SIZEOF LEFT_PAREN expr RIGHT_PAREN { ctx.val.n = mknode(ctx.c.p, N_SIZEOF, ctx.sem[2].n, nil); }
    448 		| NIL { ctx.val.n = mknode(ctx.c.p, N_NIL, nil, nil); }
    449 		| LEFT_PAREN expr RIGHT_PAREN { ctx.val.n = ctx.sem[1].n; }
    450 	;
    451 
    452 	lexer_primary
    453 		= LEFT_PAREN lexer_pattern RIGHT_PAREN { ctx.val.n = ctx.sem[1].n; }
    454 		| DOT { ctx.val.n = mknode(ctx.c.p, N_LEXDOT, nil, nil); }
    455 		| STRING { ctx.val.n = ctx.sem[0].n; }
    456 		| CHARSET { ctx.val.n = ctx.sem[0].n; }
    457 	;
    458 
    459 	lexer_suffix
    460 		= lexer_suffix STAR { ctx.val.n = mknode(ctx.c.p, N_LEXSTAR, ctx.sem[0].n, nil); }
    461 		| lexer_suffix PLUS { ctx.val.n = mknode(ctx.c.p, N_LEXPLUS, ctx.sem[0].n, nil); }
    462 		| lexer_suffix QMARK { ctx.val.n = mknode(ctx.c.p, N_LEXQMARK, ctx.sem[0].n, nil); }
    463 		| lexer_primary { ctx.val.n = ctx.sem[0].n; }
    464 	;
    465 
    466 	lexer_alternative
    467 		= lexer_suffix lexer_alternative { ctx.val.n = mknode(ctx.c.p, N_LEXCONCAT, ctx.sem[0].n, ctx.sem[1].n); }
    468 		| lexer_suffix { ctx.val.n = ctx.sem[0].n; }
    469 	;
    470 
    471 	lexer_pattern
    472 		= lexer_alternative PIPE lexer_pattern { ctx.val.n = mknode(ctx.c.p, N_LEXALT, ctx.sem[0].n, ctx.sem[2].n); }
    473 		| lexer_alternative { ctx.val.n = ctx.sem[0].n; }
    474 	;
    475 
    476 	lexer_rule
    477 		= lexer_pattern compound_stmt { ctx.val.n = mknode(ctx.c.p, N_LEXRULE, ctx.sem[0].n, ctx.sem[1].n); }
    478 	;
    479 
    480 	lexer_rule_list
    481 		= lexer_rule lexer_rule_list { ctx.val.n = mknode(ctx.c.p, N_LEXLIST, ctx.sem[0].n, ctx.sem[1].n); }
    482 		| { ctx.val.n = nil; }
    483 	;
    484 
    485 	lexer_grammar
    486 		= LEX LEFT_BRACE lexer_rule_list RIGHT_BRACE { ctx.val.n = mknode(ctx.c.p, N_LEXER, ctx.sem[2].n, nil); }
    487 	;
    488 
    489 	lalr_primary
    490 		= IDENT { ctx.val.n = ctx.sem[0].n; }
    491 		| compound_stmt { ctx.val.n = ctx.sem[0].n; }
    492 	;
    493 
    494 	lalr_alternative
    495 		= lalr_primary lalr_alternative { ctx.val.n = mknode(ctx.c.p, N_PRODITEM, ctx.sem[0].n, ctx.sem[1].n); }
    496 		| { ctx.val.n = nil; }
    497 	;
    498 
    499 	lalr_pattern
    500 		= lalr_alternative PIPE lalr_pattern { ctx.val.n = mknode(ctx.c.p, N_PRODALT, ctx.sem[0].n, ctx.sem[2].n); }
    501 		| lalr_alternative { ctx.val.n = mknode(ctx.c.p, N_PRODALT, ctx.sem[0].n, nil); }
    502 	;
    503 
    504 	lalr_rule
    505 		= IDENT ASSIGN lalr_pattern { ctx.val.n = mknode(ctx.c.p, N_PROD, ctx.sem[0].n, ctx.sem[2].n); }
    506 	;
    507 
    508 	lalr_rule_list
    509 		= lalr_rule SEMI lalr_rule_list { ctx.val.n = mknode(ctx.c.p, N_PRODLIST, ctx.sem[0].n, ctx.sem[2].n); }
    510 		| lalr_rule SEMI { ctx.val.n = mknode(ctx.c.p, N_PRODLIST, ctx.sem[0].n, nil); }
    511 	;
    512 
    513 	lalr_grammar
    514 		= LALR LEFT_BRACE lalr_rule_list RIGHT_BRACE { ctx.val.n = mknode(ctx.c.p, N_GRAMMAR, ctx.sem[2].n, nil); }
    515 	;
    516 }