From dcd558a43aa9f1d12f54f5ca1649f0397d83eccc Mon Sep 17 00:00:00 2001 From: mtardy Date: Wed, 17 Jun 2020 12:55:40 +0200 Subject: [PATCH] basic calculator --- .gitignore | 5 +++++ Makefile | 11 +++++++++++ calc.leg | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ test.sh | 19 +++++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 calc.leg create mode 100755 test.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..97c85da --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# ignore generated parser +calc.c + +# ignore compiled parser +calc diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..df22575 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +CC=cc +PG=leg + +cparser: calc.c + $(CC) -o calc calc.c + +calc.c: calc.leg + $(PG) calc.leg > calc.c + +clean: + rm calc.c calc diff --git a/calc.leg b/calc.leg new file mode 100644 index 0000000..4ea4945 --- /dev/null +++ b/calc.leg @@ -0,0 +1,48 @@ +%{ + +/* compile: leg -o tmp.c tmp.leg + * cc -o tmp tmp.c + * + * run: echo "hello world" | ./tmp + */ + +#define YYSTYPE int +YYSTYPE yylval = 0; + +%} + +start = e:exp { yylval = e } + +exp = - s:sum { $$ = s } + +sum = PLUS* l:prod + ( PLUS+ r:prod { l += r } + | MINUS r:prod { l -= r } + )* { $$ = l } + +prod = l:neg + ( MULTI r:neg { l *= r } + | DIVIDE r:neg { l /= r } + | MODULO r:neg { l %= r } + )* { $$ = l } + +neg = MINUS n:neg { $$ = -n } + | n:NUMBER { $$ = n } + +- = [ \t]* +NUMBER = < [0-9]+ > - { $$ = atoi(yytext) } +PLUS = '+' - +MINUS = '-' - +MULTI = '*' - +DIVIDE = '/' - +MODULO = '%' - +%% + +int main(int argc, char **argv) +{ + while (yyparse()) { + printf("%d\n", yylval); + } + + return 0; +} diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..c89805e --- /dev/null +++ b/test.sh @@ -0,0 +1,19 @@ +#!/bin/bash +PROG=calc + +make + +echo "2+3" | ./${PROG} | cmp <(echo "5") && echo "test#1 passed!" || true +echo "2-3" | ./${PROG} | cmp <(echo "-1") && echo "test#2 passed!" || true +echo "2--3" | ./${PROG} | cmp <(echo "5") && echo "test#3 passed!" || true +echo "-2+3" | ./${PROG} | cmp <(echo "1") && echo "test#4 passed!" || true +echo "+2+3" | ./${PROG} | cmp <(echo "5") && echo "test#5 passed!" || true +echo "2*3" | ./${PROG} | cmp <(echo "6") && echo "test#6 passed!" || true +echo "4/2" | ./${PROG} | cmp <(echo "2") && echo "test#6 passed!" || true +echo "3/2" | ./${PROG} | cmp <(echo "1") && echo "test#7 passed!" || true +echo "5%2" | ./${PROG} | cmp <(echo "1") && echo "test#8 passed!" || true +echo "3*2+10*2" | ./${PROG} | cmp <(echo "26") && echo "test#9 passed!" || true +echo "-3*2+10*2" | ./${PROG} | cmp <(echo "14") && echo "test#10 passed!" || true +echo "- 5% 2 +2-6 / 2" | ./${PROG} | cmp <(echo "-2") && echo "test#11 passed!" || true + +make clean \ No newline at end of file