aboutsummaryrefslogtreecommitdiff
path: root/Source/Parser/wp_parser.y
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Parser/wp_parser.y')
-rw-r--r--Source/Parser/wp_parser.y83
1 files changed, 83 insertions, 0 deletions
diff --git a/Source/Parser/wp_parser.y b/Source/Parser/wp_parser.y
new file mode 100644
index 000000000..e3a007949
--- /dev/null
+++ b/Source/Parser/wp_parser.y
@@ -0,0 +1,83 @@
+
+%{
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <math.h>
+ #include "wp_parser_y.h"
+ int yylex (void);
+%}
+
+/* We do not need to make this reentrant safe, because we use flex and
+ bison for generating AST only and this part doesn't need to be
+ thread safe.
+*/
+/*%define api.pure full */
+
+/* This is the type returned by functions wp_new* declared in
+ wp_parser_y.h. See also bison rules at the end of this file.
+*/
+%union {
+ struct wp_node* n;
+ double d;
+ struct wp_symbol* s;
+ enum wp_f1_t f1;
+ enum wp_f2_t f2;
+}
+
+/* Define tokens. They are used by flex too. */
+%token <n> NODE
+%token <d> NUMBER
+%token <s> SYMBOL
+%token <f1> F1
+%token <f2> F2
+%token EOL
+%token POW "**" '^'
+
+%nonassoc F1 F2
+%right '='
+%left '+' '-'
+%left '*' '/'
+%left '<' '>'
+%nonassoc NEG
+%right POW
+
+/* This specifies the type of `exp` (i.e., struct wp_node*). Rules
+ specified later pass `exp` to wp_new* functions declared in
+ wp_parser_y.h.
+*/
+%type <n> exp
+
+%start input
+
+%%
+
+/* Given `\n` terminated input, a tree is generated and passed to
+ * function wp_defexpr defined in wp_parser_y.c.
+ */
+input:
+ %empty
+| input exp EOL {
+ wp_defexpr($2);
+ }
+;
+
+/* Enum types WP_ADD, WP_SUB, etc. are defined in wp_parser_y.h.
+ * Functions wp_new* are also declared in that file.
+ */
+exp:
+ NUMBER { $$ = wp_newnumber($1); }
+| SYMBOL { $$ = wp_newsymbol($1); }
+| exp '+' exp { $$ = wp_newnode(WP_ADD, $1, $3); }
+| exp '-' exp { $$ = wp_newnode(WP_SUB, $1, $3); }
+| exp '*' exp { $$ = wp_newnode(WP_MUL, $1, $3); }
+| exp '/' exp { $$ = wp_newnode(WP_DIV, $1, $3); }
+| '(' exp ')' { $$ = $2; }
+| exp '<' exp { $$ = wp_newf2(WP_LT, $1, $3); }
+| exp '>' exp { $$ = wp_newf2(WP_GT, $1, $3); }
+| '-'exp %prec NEG { $$ = wp_newnode(WP_NEG, $2, NULL); }
+| exp POW exp { $$ = wp_newf2(WP_POW, $1, $3); }
+| F1 '(' exp ')' { $$ = wp_newf1($1, $3); }
+| F2 '(' exp ',' exp ')' { $$ = wp_newf2($1, $3, $5); }
+;
+
+%%