summaryrefslogtreecommitdiff
path: root/simple-c/parser.y
diff options
context:
space:
mode:
Diffstat (limited to 'simple-c/parser.y')
-rw-r--r--simple-c/parser.y75
1 files changed, 75 insertions, 0 deletions
diff --git a/simple-c/parser.y b/simple-c/parser.y
new file mode 100644
index 0000000..ac61b8b
--- /dev/null
+++ b/simple-c/parser.y
@@ -0,0 +1,75 @@
+/* calculator. */
+%{
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "lexer.h"
+
+void yyerror(const char *msg);
+
+// Here is an example how to create custom data structure
+typedef struct custom_data {
+ char* name;
+ int counter;
+} custom_data;
+
+%}
+
+%union{
+ double dval;
+ int ival;
+ struct custom_data* cval; // define the pointer type for custom data structure
+}
+
+%define parse.error verbose
+%locations
+
+%start input
+%token MULT DIV PLUS MINUS EQUAL L_PAREN R_PAREN END
+%token <dval> NUMBER
+%type <dval> exp
+%type <cval> input
+%left PLUS MINUS
+%left MULT DIV
+%nonassoc UMINUS
+
+%%
+
+input: {
+ $$ = malloc(sizeof(custom_data)); $$->name = "input"; $$->counter = 0;
+}
+| input line {
+ $$ = $1; $1->counter++;
+}
+;
+
+line: exp EQUAL END { printf("\t%f\n", $1); };
+
+exp: NUMBER { $$ = $1; }
+| exp PLUS exp { $$ = $1 + $3; }
+| exp MINUS exp { $$ = $1 - $3; }
+| exp MULT exp { $$ = $1 * $3; }
+| exp DIV exp {
+ if ($3==0) yyerror("divide by zero"); else $$ = $1 / $3;
+}
+| MINUS exp %prec UMINUS { $$ = -$2; }
+| L_PAREN exp R_PAREN { $$ = $2; }
+;
+%%
+
+int main(int argc, char **argv)
+{
+ if (argc > 1) {
+ yyin = fopen(argv[1], "r");
+ if (yyin == NULL){
+ printf("syntax: %s filename\n", argv[0]);
+ }
+ }
+ yyparse(); // Calls yylex() for tokens.
+ return 0;
+}
+
+void yyerror(const char *msg)
+{
+ printf("** Line %d: %s\n", yylloc.first_line, msg);
+}