diff options
| author | Andre Noll <maan@tuebingen.mpg.de> | 2018-01-11 23:40:23 +0100 |
|---|---|---|
| committer | Andre Noll <maan@tuebingen.mpg.de> | 2018-01-11 23:40:23 +0100 |
| commit | b95de7e4b629c3ffb90ae09b53d0178285e73629 (patch) | |
| tree | 2929492fa05274fc150e09c4821dbf52a65149f3 /txp.y | |
initialinitial
Diffstat (limited to 'txp.y')
| -rw-r--r-- | txp.y | 130 |
1 files changed, 130 insertions, 0 deletions
@@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Provide more verbose and specific error messages instead of just "syntax + * error". + */ +%define parse.error verbose + +/* + * Verbose error messages may contain incorrect information if LAC (Lookahead + * Correction) is not enabled. + */ +%define parse.lac full + +/* Avoid symbol clashes (lopsub might also expose yy* symbols). */ +%define api.prefix {txp_yy} + +/* + * Although locations are automatically enabled as soon as the grammar uses the + * special @N tokens, specifying %locations explicitly allows for more accurate + * syntax error messages. + */ +%locations + +/* + * Generate a pure (reentrant) parser. With this option enabled, yylval and + * yylloc become local variables in yyparse(), and a different calling + * convention is used for yylex(). + */ +%define api.pure full + +/* Additional arguments to yylex(), yyparse() and yyerror() */ +%param {struct txp_context *ctx} +%param {struct txp_ast_node **ast} +%param {txp_yyscan_t yyscanner} /* reentrant lexers */ + +%{ +#include "tf.h" +#include "txp.bison.h" + +int yylex(TXP_YYSTYPE *lvalp, TXP_YYLTYPE *llocp, struct txp_context *ctx, + struct txp_ast_node **ast, txp_yyscan_t yyscanner); +static void yyerror(YYLTYPE *llocp, struct txp_context *ctx, + struct txp_ast_node **ast, txp_yyscan_t yyscanner, const char *msg); + +%} + +%union { + struct txp_ast_node *node; +} + +/* terminals */ +%token <node> NUM +%token <node> STRING_LITERAL +%token <node> REGEX_PATTERN + +/* keywords with semantic value */ +%token <node> NUM_LINES +%token <node> FALSE TRUE + +/* keywords without semantic value */ +%token TAG + +/* operators, ordered by precendence */ +%left OR +%left AND +%left EQUAL NOT_EQUAL +%left LESS_THAN LESS_OR_EQUAL GREATER_OR_EQUAL REGEX_MATCH FILENAME_MATCH +%left '-' '+' +%left '*' '/' +%right NOT NEG /* negation (unary minus) */ + +/* nonterminals */ +%type <node> string +%type <node> exp +%type <node> boolexp + +%% + +program: + /* empty */ {*ast = NULL; return 0;} + | string {*ast = $1; return 0;} + | exp {*ast = $1; return 0;} + | boolexp {*ast = $1; return 0;} + +string: STRING_LITERAL {$$ = $1;} +; + +exp: NUM {$$ = $1;} + | exp '+' exp {$$ = ast_node_new_binary('+', $1, $3);} + | exp '-' exp {$$ = ast_node_new_binary('-', $1, $3);} + | exp '*' exp {$$ = ast_node_new_binary('*', $1, $3);} + | exp '/' exp {$$ = ast_node_new_binary('/', $1, $3);} + | '-' exp %prec NEG {$$ = ast_node_new_unary(NEG, $2);} + | '(' exp ')' {$$ = $2;} + | NUM_LINES {$$ = txp_new_ast_leaf_node(NUM_LINES);} +; + +boolexp: TRUE {$$ = txp_new_ast_leaf_node(TRUE);} + | FALSE {$$ = txp_new_ast_leaf_node(FALSE);} + | '(' boolexp ')' {$$ = $2;} + | boolexp OR boolexp {$$ = ast_node_new_binary(OR, $1, $3);} + | boolexp AND boolexp {$$ = ast_node_new_binary(AND, $1, $3);} + | NOT boolexp {$$ = ast_node_new_unary(NOT, $2);} + | exp EQUAL exp {$$ = ast_node_new_binary(EQUAL, $1, $3);} + | exp NOT_EQUAL exp {$$ = ast_node_new_binary(NOT_EQUAL, $1, $3);} + | exp '<' exp {$$ = ast_node_new_binary('<', $1, $3);} + | exp '>' exp {$$ = ast_node_new_binary('>', $1, $3);} + | exp LESS_OR_EQUAL exp { + $$ = ast_node_new_binary(LESS_OR_EQUAL, $1, $3); + } + | exp GREATER_OR_EQUAL exp { + $$ = ast_node_new_binary(GREATER_OR_EQUAL, $1, $3); + } + | string REGEX_MATCH REGEX_PATTERN { + $$ = ast_node_new_binary(REGEX_MATCH, $1, $3); + } + | string EQUAL string {$$ = ast_node_new_binary(EQUAL, $1, $3);} + | string NOT_EQUAL string {$$ = ast_node_new_binary(NOT_EQUAL, $1, $3);} +; +%% + +/* Called by yyparse() on error */ +static void yyerror(YYLTYPE *llocp, struct txp_context *ctx, + __attribute__ ((unused)) struct txp_ast_node **ast, + __attribute__ ((unused)) txp_yyscan_t yyscanner, + const char *msg) +{ + txp_parse_error(llocp->first_line, ctx, "%s", msg); +} |
