scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit 1f4874cced9c4f1308556b07e835bb47547becc0
parent 3e7e69413c50005c9e35de23fab8fc8ec9604f68
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 12 Jun 2012 21:53:47 +0200

Rewrite the expression parser

This parser applies the rule in the correct order and runs actions each time
that one of the rule matches.

Diffstat:
MMakefile | 2+-
Acode.c | 253+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acode.h | 8++++++++
Mexpr.c | 276+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
4 files changed, 469 insertions(+), 70 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,5 +1,5 @@ -OBJS = types.o decl.o lex.o error.o symbol.o flow.o main.o expr.o keyword.o +OBJS = types.o decl.o lex.o error.o symbol.o flow.o main.o expr.o keyword.o code.o LIBS = all: kcc diff --git a/code.c b/code.c @@ -0,0 +1,253 @@ + +#include "cc.h" +#include "code.h" +#include "symbol.h" + + +#define NR_MACHINE_OP 30 +#define NR_SYM_STACK 30 + +static struct symbol *stack[NR_SYM_STACK]; +static struct symbol **stackp = stack; + +void push(register struct symbol *sym) +{ + if (stackp == &stack[NR_SYM_STACK]) + error("out of memory"); + *stackp++ = sym; +} + +void code(void *data) +{ +} + +void execute(void) +{ +} + + + +void gen_ary(void) +{ + puts("gen_ary"); +} + +void gen_call(void) +{ + puts("gen_call"); +} + +void gen_or(void) +{ + puts("gen_or"); +} + +void gen_tern(void) +{ + puts("gen_tern"); +} + +void gen_band(void) +{ + puts("gen_band"); +} + +void gen_bxor(void) +{ + puts("gen_bxor"); +} + +void gen_bor(void) +{ + puts("gen_bor"); +} + +void gen_and(void) +{ + puts("gen_and"); +} + +void gen_sizeof(void) +{ + puts("gen_sizeof"); +} + +void gen_field(void) +{ + puts("gen_field"); +} + +void gen_ptr(void) +{ + puts("gen_ptr"); +} + +void gen_preinc(void) +{ + puts("gen_preinc"); +} + +void gen_predec(void) +{ + puts("gen_predec"); +} + +void gen_addr(void) +{ + puts("gen_addr"); +} + +void gen_indir(void) +{ + puts("gen_indir"); +} + +void gen_minus(void) +{ + puts("gen_minus"); +} + +void gen_plus(void) +{ + puts("gen_plus"); +} + +void gen_cpl(void) +{ + puts("gen_cpl"); +} + +void gen_neg(void) +{ + puts("gen_neg"); +} + +void gen_mul(void) +{ + puts("gen_mul"); +} + +void gen_div(void) +{ + puts("gen_div"); +} + +void gen_mod(void) +{ + puts("gen_mod"); +} + +void gen_add(void) +{ + puts("gen_add"); +} + +void gen_sub(void) +{ + puts("gen_sub"); +} + +void gen_shl(void) +{ + puts("gen_shl"); +} + +void gen_shr(void) +{ + puts("gen_shr"); +} + +void gen_lt(void) +{ + puts("gen_lt"); +} + +void gen_gt(void) +{ + puts("gen_gt"); +} + +void gen_ge(void) +{ + puts("gen_ge"); +} + +void gen_le(void) +{ + puts("gen_le"); +} + +void gen_eq(void) +{ + puts("gen_eq"); +} + +void gen_ne(void) +{ + puts("gen_ne"); +} + +void gen_a_mul(void) +{ + puts("gen_a"); +} + +void gen_a_div(void) +{ + puts("gen_a"); +} + +void gen_a_mod(void) +{ + puts("gen_a"); +} + +void gen_a_add(void) +{ + puts("gen_a"); +} + +void gen_a_sub(void) +{ + puts("gen_a"); +} + +void gen_a_shl(void) +{ + puts("gen_a"); +} + +void gen_a_shr(void) +{ + puts("gen_a"); +} + +void gen_a_and(void) +{ + puts("gen_a"); +} + +void gen_a_xor(void) +{ + puts("gen_a"); +} + +void gen_a_or(void) +{ + puts("gen_a"); +} + +void gen_postinc(void) +{ + puts("gen_postinc"); +} + +void gen_postdec(void) +{ + puts("gen_postdec"); +} + +void gen_assign(void) +{ + puts("gen_assign"); +} diff --git a/code.h b/code.h @@ -0,0 +1,8 @@ +#ifndef CODE_H +#define CODE_H + +struct symbol; +extern void push(register struct symbol *sym); +extern void runcode(void); + +#endif diff --git a/expr.c b/expr.c @@ -1,22 +1,38 @@ #include <stddef.h> +#include <stdio.h> +#include "cc.h" #include "tokens.h" #include "symbol.h" #include "syntax.h" +#include "code.h" -#include <stdio.h> /* TODO: remove this */ +extern void gen_ary(void), gen_call(void), gen_or(void), gen_tern(void), + gen_band(void), gen_bxor(void), gen_bor(void), gen_and(void), + gen_sizeof(void), gen_field(void), gen_ptr(void), gen_preinc(void), + gen_predec(void), gen_addr(void), gen_indir(void), gen_minus(void), + gen_plus(void), gen_cpl(void), gen_neg(void), gen_mul(void), + gen_div(void), gen_mod(void), gen_add(void), gen_sub(void), + gen_shl(void), gen_shr(void), gen_lt(void), gen_gt(void), + gen_ge(void), gen_le(void), gen_eq(void), gen_ne(void), + gen_a_mul(void), gen_a_div(void), gen_a_mod(void), gen_a_add(void), + gen_a_sub(void), gen_a_shl(void), gen_a_shr(void), gen_a_and(void), + gen_a_xor(void), gen_a_or(void), gen_postinc(void), + gen_postdec(void), gen_assign(void); void expr(void); static void primary(void) { + fputs("static void primary(void)", stderr); switch (yytoken) { case IDEN: if (!yyval.sym) error("'%s' undeclared", yytext); case CONSTANT: next(); + push(yyval.sym); break; case '(': next(); @@ -24,35 +40,44 @@ static void primary(void) expect(')'); break; } + fputs("leaving static void primary(void)", stderr); } static void postfix(void) { - primary(); + fputs("static void postfix(void)", stderr); + primary(); /* TODO: fix ( case */ for (;;) { + register void (*fp)(void); switch (yytoken) { case '[': next(); expr(); expect(']'); - break; + gen_ary(); + continue; case '(': next(); expr(); expect(')'); - break; - case '.': - case PTR: - next(); - expect(IDEN); - break; - case INC: - case DEC: - next(); - break; + gen_call(); + continue; + case '.': fp = gen_field; goto expect_iden; + case PTR: fp = gen_ptr; goto expect_iden; + case INC: fp = gen_postinc; goto next; + case DEC: fp = gen_postdec; goto next; default: + fputs("leaving static void postfix(void)", stderr); return; } + expect_iden: + next(); + expect(IDEN); + fp(); + continue; + next: + next(); + continue; } } @@ -60,146 +85,259 @@ static void cast(void); static void unary(void) { + fputs("static void unary(void)", stderr); for (;;) { + register void (*fp)(void); switch (yytoken) { case SIZEOF: next(); if (accept('(')) { type_name(); expect(')'); - return; + } else { + unary(); } - break; - case INC: - case DEC: - next(); - break; - case '&': case '*': case '-': case '~': case '!': case '+': - next(); - cast(); - return; + gen_sizeof(); + continue; + case INC: fp = gen_preinc; goto call_unary; + case DEC: fp = gen_predec; goto call_unary; + case '&': fp = gen_addr; goto call_cast; + case '*': fp = gen_indir; goto call_cast; + case '-': fp = gen_minus; goto call_cast; + case '+': fp = gen_plus; goto call_cast; + case '~': fp = gen_cpl; goto call_cast; + case '!': fp = gen_neg; goto call_cast; default: postfix(); + fputs("leaving static void unary(void)", stderr); return; } + call_cast: + next(); + cast(); + fp(); + return; + call_unary: + next(); + unary(); + fp(); + return; } } static void cast(void) { + fputs("static void cast(void)", stderr); while (accept('(')) { type_name(); /* check if it really is a type name */ expect(')'); } unary(); + fputs("leaving static void cast(void)", stderr); } static void mul(void) { - do + fputs("static void mul(void)", stderr); + cast(); + for (;;) { + register void (*fp)(void); + switch (yytoken) { + case '*': fp = gen_mul; break; + case '/': fp = gen_div; break; + case '%': fp = gen_mod; break; + default: + fputs("leaving static void mul(void)", stderr); + return; + } + next(); cast(); - while(accept('*') || accept('/') || accept('%')); + fp(); + } } static void add(void) { - do + fputs("static void add(void)", stderr); + mul(); + for (;;) { + register void (*fp)(void); + switch (yytoken) { + case '+': fp = gen_add; break; + case '-': fp = gen_sub; break; + default: + fputs("leaving static void add (void)", stderr); + return; + } + next(); mul(); - while (accept('+') || accept('-')); + fp(); + } } static void shift(void) { - do + fputs("static void shift(void)", stderr); + add(); + for (;;) { + register void (*fp)(void); + switch (yytoken) { + case LSHIFT: fp = gen_shl; break; + case RSHIFT: fp = gen_shr; break; + default: + fputs("leaving static void shift (void)", stderr); + return; + } + next(); add(); - while (accept(LSHIFT) || accept(RSHIFT)); + fp(); + } } static void relational(void) { - do + fputs("static void relational(void)", stderr); + shift(); + for (;;) { + register void (*fp)(void); + switch (yytoken) { + case '<': fp = gen_lt; break; + case '>': fp = gen_gt; break; + case GE: fp = gen_ge; break; + case LE: fp = gen_le; break; + default: + fputs("leaving static void relational (void)", stderr); + return; + } + next(); shift(); - while (accept('<') || accept('>') || accept(GE) || accept(LE)); + fp(); + } } -static void equality(void) +static void eq(void) { - do + fputs("static void eq(void)", stderr); + relational(); + for (;;) { + register void (*fp)(void); + switch (yytoken) { + case EQ: fp = gen_eq; break; + case NE: fp = gen_ne; break; + default: + fputs("leaving static void eq (void)", stderr); + return; + } + next(); relational(); - while (accept(EQ) || accept(NE)); + fp(); + } } static void bit_and(void) { - do - equality(); - while (accept('&')); + fputs("static void bit_and(void)", stderr); + eq(); + while (yytoken == '&') { + next(); + eq(); + gen_band(); + } + fputs("leaving static void bit_and (void)", stderr); } -static void bit_exor(void) +static void bit_xor(void) { - do + fputs("static void bit_xor(void)", stderr); + bit_and(); + while (yytoken == '^') { + next(); bit_and(); - while (accept('^')); + gen_bxor(); + } + fputs("leaving static void bit_xor(void)", stderr); } static void bit_or(void) { - do - bit_exor(); - while (accept('|')); + fputs("static void bit_or(void)", stderr); + bit_xor(); + while (yytoken == '|') { + next(); + bit_xor(); + gen_bor(); + } + fputs("leaving static void bit_or(void)", stderr); } static void and(void) { - do + fputs("static void and(void)", stderr); + bit_or(); + while (yytoken == AND) { + next(); bit_or(); - while (accept(AND)); + gen_and(); + } + fputs("leaving static void and(void)", stderr); } static void or(void) { - do + fputs("static void or(void)", stderr); + and(); + while (yytoken == OR) { + next(); and(); - while (accept(OR)); + gen_or(); + } + fputs("leaving static void or(void)", stderr); } -static void conditional(void) +static void cond(void) { + fputs("static void cond(void)", stderr); or(); - if (accept('?')) { - expr(); - expect(':'); - conditional(); + while (yytoken == '?') { + expr(); + expect(':'); + or(); + gen_tern(); } + fputs("leaving static void cond(void)", stderr); } static void assign(void) { - unary(); - switch (yytoken) { - case '=': - case MUL_EQ: - case DIV_EQ: - case MOD_EQ: - case ADD_EQ: - case SUB_EQ: - case LSHIFT_EQ: - case RSHIFT_EQ: - case AND_EQ: - case XOR_EQ: - case OR_EQ: + fputs("static void assign(void)", stderr); + cond(); + for (;;) { + register void (*fp)(void); + switch (yytoken) { + case '=': fp = gen_assign; break; + case MUL_EQ: fp = gen_a_mul; break; + case DIV_EQ: fp = gen_a_div; break; + case MOD_EQ: fp = gen_a_mod; break; + case ADD_EQ: fp = gen_a_add; break; + case SUB_EQ: fp = gen_a_sub; break; + case LSHIFT_EQ: fp = gen_a_shl; break; + case RSHIFT_EQ: fp = gen_a_shr; break; + case AND_EQ: fp = gen_a_and; break; + case XOR_EQ: fp = gen_a_xor; break; + case OR_EQ: fp = gen_a_or; break; + default: + fputs("static void assign (void)", stderr); + return; + } next(); assign(); - break; - default: - conditional(); - break; + fp(); } } void expr(void) { + fputs("void expr(void)", stderr); do assign(); while (yytoken == ',');