commit 474200046322ff9e4591e30137ab3eb09dfb8d36
Author: William Casarin <jb55@jb55.com>
Date: Fri, 29 Sep 2017 20:19:55 -0700
initial commit
Diffstat:
5 files changed, 122 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,4 @@
+*.o
+*.tab.*
+/lex.yy.c
+/ratio
diff --git a/Makefile b/Makefile
@@ -0,0 +1,16 @@
+
+GEN=parser.tab.c parser.tab.h lex.yy.c
+
+all: ratio
+
+parser.tab.c parser.tab.h: parser.y
+ bison -d parser.y
+
+lex.yy.c: lexer.l parser.tab.h
+ flex lexer.l
+
+ratio: $(GEN)
+ $(CC) -o $@ -lgmp parser.tab.c lex.yy.c
+
+clean:
+ rm -f $(GEN)
diff --git a/lexer.l b/lexer.l
@@ -0,0 +1,32 @@
+%option noyywrap
+
+%{
+#include <stdio.h>
+#include <gmp.h>
+#include "ratio.h"
+
+#define YY_DECL int yylex()
+
+#include "parser.tab.h"
+
+%}
+
+%%
+
+[ \t] ; // ignore all whitespace
+[0-9]+ {
+ mpz_t i; mpz_init(i);
+ mpq_init(yylval.rval);
+ mpz_set_str(i, yytext, 10);
+ mpq_set_z(yylval.rval, i);
+ return T_RATIO;
+}
+\n {return T_NEWLINE;}
+"+" {return T_PLUS;}
+"-" {return T_MINUS;}
+"*" {return T_MULTIPLY;}
+"/" {return T_DIVIDE;}
+"(" {return T_LEFT;}
+")" {return T_RIGHT;}
+
+%%
diff --git a/parser.y b/parser.y
@@ -0,0 +1,63 @@
+%{
+
+#include <stdio.h>
+#include <gmp.h>
+#include <stdlib.h>
+
+extern int yylex();
+extern int yyparse();
+extern FILE* yyin;
+
+char buffer[255];
+
+void yyerror(const char* s);
+%}
+
+%union {
+ mpq_t rval;
+}
+
+%token<rval> T_RATIO
+%token T_PLUS T_MINUS T_MULTIPLY T_DIVIDE T_LEFT T_RIGHT
+%token T_NEWLINE T_QUIT
+%left T_PLUS T_MINUS
+%left T_MULTIPLY T_DIVIDE
+
+%type<rval> expr
+
+%start calc
+
+%%
+
+calc:
+ | calc line
+;
+
+line: T_NEWLINE
+ | expr T_NEWLINE { mpq_out_str(stdout, 10, $1); printf("\n"); }
+;
+
+expr: T_RATIO { mpq_set($$, $1); }
+ | expr T_PLUS expr { mpq_add($$, $1, $3); }
+ | expr T_MINUS expr { mpq_sub($$, $1, $3); }
+ | expr T_MULTIPLY expr { mpq_mul($$, $1, $3); }
+ | expr T_DIVIDE expr { mpq_div($$, $1, $3); }
+ | T_LEFT expr T_RIGHT { mpq_set($$, $2); }
+;
+
+%%
+
+int main() {
+ yyin = stdin;
+
+ do {
+ yyparse();
+ } while(!feof(yyin));
+
+ return 0;
+}
+
+void yyerror(const char* s) {
+ fprintf(stderr, "Parse error: %s\n", s);
+ exit(1);
+}
diff --git a/ratio.h b/ratio.h
@@ -0,0 +1,7 @@
+#include <gmp.h>
+
+void fresh_ratio(mpq_t r);
+void fresh_bigint(mpz_t i);
+
+void note_mpq(const mpq_t a);
+void note_mpz(const mpz_t a);