diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cfb7081 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +CC=gcc +YACC=yacc +LEX=lex +name=testl0 +lexf=$(name).l +yaccf=$(name).y + +yacco=y.tab.h y.tab.c y.output +lexo=lex.yy.c +objs=$(yacco) $(lexo) + +$(name): $(filter %.c, $(objs)) node.o + $(CC) -o $@ $^ + +$(yacco): + $(YACC) -dv $(yaccf) + +$(lexo): + $(LEX) $(lexf) + +node.o: node.c + gcc -c $^ -o $@ + +.PHONY: clean +clean: + rm -f $(objs) $(name) diff --git a/node.c b/node.c new file mode 100644 index 0000000..4575961 --- /dev/null +++ b/node.c @@ -0,0 +1,9 @@ +#include "node.h" +#include + +node* node_float_new(double value) { + node_float* nf = malloc(sizeof(node_float)); + nf->type = NODE_FLOAT; + nf->value = value; + return (node*)nf; +} diff --git a/node.h b/node.h new file mode 100644 index 0000000..6a87b06 --- /dev/null +++ b/node.h @@ -0,0 +1,41 @@ +#ifndef TESTL0_H +#define TESTL0_H + +enum node_type { + NODE_FLOAT +}; + +#define NODE_HEADER enum node_type type + +typedef struct { + NODE_HEADER; +} node; + +typedef struct { + NODE_HEADER; + int len; + int max; + node** data; +} node_nodes; + +typedef struct { + NODE_HEADER; + double value; +} node_float; + +typedef struct node_string { + int len; + char buf[0]; +} *node_string; + +typedef struct { + NODE_HEADER; + node_string op; + node* lhs; + node* rhs; +} node_op; + + +node* node_float_new(double); + +#endif diff --git a/node.o b/node.o new file mode 100644 index 0000000..0e17fba --- /dev/null +++ b/node.o Binary files differ diff --git a/testl0.l b/testl0.l new file mode 100644 index 0000000..32931ba --- /dev/null +++ b/testl0.l @@ -0,0 +1,38 @@ +%{ +#include +#include "node.h" +#include "y.tab.h" + +int +yywrap(void) +{ + return 1; +} +%} + +%% +"+" return ADD; +"-" return SUB; +"*" return MUL; +"/" return DIV; +"\n" return CR; + +"if" return IF; +"(" return COND_BEGIN; +")" return COND_END; +"else" return ELSE; +"endif" return ENDIF; + +[1-9][0-9]* { + double temp; + sscanf(yytext, "%lf", &temp); + yylval.double_value = temp; + return DOUBLE_LITERAL; +} +[0-9]*\.[0-9]* { + double temp; + sscanf(yytext, "%lf", &temp); + yylval.double_value = temp; + return DOUBLE_LITERAL; +} +%% diff --git a/testl0.y b/testl0.y new file mode 100644 index 0000000..e2d631e --- /dev/null +++ b/testl0.y @@ -0,0 +1,83 @@ +%{ +#define YYDEBUG 1 +#include "node.h" +#include +%} +%union { + node* nd; + double double_value; +} + +%type primary_expression +%type DOUBLE_LITERAL +%type expression term + +%token DOUBLE_LITERAL +%token ADD SUB MUL DIV CR +%token COND_BEGIN COND_END +%token IF ELSE ENDIF + +%% +line_list + : line + | line_list line + ; +line + : expression CR + { + printf(">>%lf\n", $1); + } +expression + : term + | expression ADD term + { + $$ = $1 + $3; + } + | expression SUB term + { + $$ = $1 - $3; + } + | IF COND_BEGIN expression COND_END expression ELSE expression ENDIF + { + $$ = ($3) ? ($5) : ($7); + } +term + : primary_expression + { + $$ = ((node_float*)$1)->value; + } + | term MUL primary_expression + { + $$ = $1 * ((node_float*)$3)->value; + } + | term DIV primary_expression + { + $$ = $1 / ((node_float*)$3)->value; + } + ; +primary_expression + : DOUBLE_LITERAL + { + $$ = node_float_new($1); + } + ; +%% +int +yyerror(char const *str) +{ + extern char *yytext; + fprintf(stderr, "parser error near %s\n", yytext); + return 0; +} + +int main(void) +{ + extern int yyparse(void); + extern FILE *yyin; + + yyin = stdin; + if(yyparse()) { + fprintf(stderr, "Error! Error! Error!\n"); + exit(1); + } +}