%{ | |
#include <stdio.h> | |
#include "parser.h" | |
%} | |
%% | |
[ \r\n\t]* { continue; /* Skip blanks. */ } | |
[0-9]+ { sscanf(yytext, "%d", &yylval->value); return TOKEN_NUMBER; } | |
"*" { return TOKEN_STAR; } | |
"+" { return TOKEN_PLUS; } | |
"(" { return TOKEN_LPAREN; } | |
")" { return TOKEN_RPAREN; } | |
. { continue; /* Ignore unexpected characters. */} |
#include <stdio.h> | |
#include "parser.h" | |
#include "lexer.h" | |
int yyparse(yyscan_t scanner); | |
int compile(const char *source) { | |
yyscan_t scanner; | |
YY_BUFFER_STATE state; | |
if (yylex_init(&scanner)) { | |
return 1; /* could not initialize */ | |
} | |
state = yy_scan_string(source, scanner); | |
if (yyparse(scanner)) { | |
return 2; /* error parsing */ | |
} | |
yy_delete_buffer(state, scanner); | |
yylex_destroy(scanner); | |
return 0; | |
} | |
int main(void) { | |
char test[] = "4 + 2*10 + 3*(5 + 1)"; | |
int code = compile(test); | |
return code; | |
} | |
FILES = lexer.c parser.c main.c | |
main: $(FILES) | |
$(CC) $(CFLAGS) $(FILES) -o main | |
lexer.c lexer.h: lexer.l | |
flex --outfile=lexer.c --header-file=lexer.h --nodefault \ | |
--reentrant --bison-bridge --nounistd --noyywrap --never-interactive --warn Lexer.l | |
parser.c parser.h: parser.y lexer.c | |
bison --output=parser.c --defines=parser.h parser.y | |
clean: | |
rm -f *.o *~ lexer.c lexer.h parser.c parser.h main |
%{ | |
#include "parser.h" | |
#include "lexer.h" | |
#define emit printf | |
void yyerror(yyscan_t scanner, const char *msg) { | |
fprintf(stderr, "Error: %s\n", msg); | |
} | |
%} | |
%pure-parser | |
%lex-param { void* scanner } | |
%parse-param { void* scanner } | |
%union { | |
int value; | |
} | |
%token TOKEN_LPAREN "(" | |
%token TOKEN_RPAREN ")" | |
%token TOKEN_PLUS "+" | |
%token TOKEN_STAR "*" | |
%token <value> TOKEN_NUMBER "number" | |
%type <void> input | |
%left "+" | |
%left "*" | |
%% | |
input: | |
{ emit(".global main\n"); | |
emit("main:\n"); } | |
expr { emit(" pop %%rax\n"); | |
emit(" ret\n"); } | |
expr: | |
"number" { emit(" push $%d\n", $1); } | |
| expr "+" expr { emit(" pop %%rax\n"); | |
emit(" pop %%rbx\n"); | |
emit(" add %%rbx, %%rax\n"); | |
emit(" push %%rax\n"); } | |
| expr "*" expr { emit(" pop %%rax\n"); | |
emit(" pop %%rbx\n"); | |
emit(" mul %%rbx\n"); | |
emit(" push %%rax\n"); } | |
| "(" expr ")" { /* No action. */ } |
.global main | |
main: | |
push $4 | |
push $2 | |
push $10 | |
pop %rax | |
pop %rbx | |
mul %rbx | |
push %rax | |
pop %rax | |
pop %rbx | |
add %rbx, %rax | |
push %rax | |
push $3 | |
push $5 | |
push $1 | |
pop %rax | |
pop %rbx | |
add %rbx, %rax | |
push %rax | |
pop %rax | |
pop %rbx | |
mul %rbx | |
push %rax | |
pop %rax | |
pop %rbx | |
add %rbx, %rax | |
push %rax | |
pop %rax | |
ret |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment