diff options
Diffstat (limited to 'src/cli_parse.y')
-rw-r--r-- | src/cli_parse.y | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/src/cli_parse.y b/src/cli_parse.y new file mode 100644 index 0000000..f0e43a8 --- /dev/null +++ b/src/cli_parse.y @@ -0,0 +1,206 @@ +%{ + +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "cli_val.h" + +extern int yy_cli_def_lineno; +static vtw_def *parse_defp; +static int parse_status; +static boolean cli_def_type_only=0; /*{ if (cli_def_type_only) YYACCEPT;}*/ +/* XXX: sigh, the -p flag to yacc should do this for us kkkk*/ +#define yystacksize tpltstacksize +#define yysslim tpltsslim + +/* forward prototypes */ +extern int yy_cli_parse_parse(); +extern int yy_cli_def_lex(); +extern void yy_cli_parse_error(const char *); +static void cli_deferror(const char *); + extern FILE *yy_cli_def_in; +#define YYDEBUG 1 +#define yy_cli_parse_lex yy_cli_def_lex +%} +%token EOL +%token MULTI +%token TAG +%token TYPE +%token HELP +%token DEFAULT +%token PATTERN +%token EXEC +%token SYNTAX +%token COMMIT +%token CHECK +%left SEMI +%token <val>VALUE +%token <type>TYPE_DEF +%token <strp>VAR +%token <strp> STRING +%token <strp> EX_STRING +%token SYNTAX_ERROR +%token <action>ACTION +%left ASSIGN +%left OR +%left AND +%right NOT +%left COMMA +%nonassoc <cond>COND +%token RP +%token LP +%type <nodep> val +%type <nodep> exp +%type <val> val0 +%type <nodep> action +%type <nodep> action0 + +%union { + char *strp; + valstruct val; + vtw_type_e type; + vtw_cond_e cond; + vtw_node *nodep; + vtw_act_type action; +} + +%% + +input: tag + | EOL input + | tag otherinput + ; + +otherinput: type EOL + | cause EOL + | otherinput type EOL + | otherinput cause EOL + | otherinput EOL + | syntax_error + ; + +tag: /* empty */ + | TAG EOL {parse_defp->tag = TRUE;} + | MULTI EOL {parse_defp->multi = TRUE;} + ; + +type: TYPE TYPE_DEF SEMI STRING + { parse_defp->def_type = $2; + parse_defp->def_type_help = $4; } + ; + + +type: TYPE TYPE_DEF + { parse_defp->def_type = $2; + } + ; + +cause: help_cause + | default_cause + | syntax_cause + | ACTION action { append(parse_defp->actions + $1, $2, 0);} + ; + +help_cause: HELP STRING + { parse_defp->def_type_help = $2; /* no semantics for now */ + } + +default_cause: DEFAULT VALUE + { + if ($2.val_type != parse_defp->def_type) + yy_cli_parse_error((const char *)"Bad default\n"); + parse_defp->def_default = $2.val; + } +default_cause: DEFAULT STRING + { + if (TEXT_TYPE != parse_defp->def_type) + yy_cli_parse_error((const char *)"Bad default\n"); + parse_defp->def_default = $2; + } + +syntax_cause: SYNTAX exp {append(parse_defp->actions + syntax_act, $2, 0);} + ; + +syntax_cause: COMMIT exp {append(parse_defp->actions + syntax_act, $2, 1);} + ; + +action0: STRING { $$ = make_node(EXEC_OP, make_str_node($1),NULL);} + ; +action: action0 + | action0 SEMI STRING + {$$ = make_node(HELP_OP, $1, make_str_node($3));} + | exp + ; +exp: LP exp RP + {$$=$2;} + | exp AND exp {$$ = make_node(AND_OP,$1,$3);} + | exp OR exp {$$ = make_node(OR_OP,$1,$3);} + | val COND val + {$$ = make_node(COND_OP,$1,$3);$$->vtw_node_aux = $2;} + | PATTERN VAR STRING + { $$ = make_node(PATTERN_OP,make_var_node($2), + make_str_node($3));} + | EXEC STRING + { $$ = make_node(EXEC_OP,make_str_node($2),NULL);} + | NOT exp {$$ = make_node(NOT_OP,$2,NULL);} + | exp SEMI STRING + {$$ = make_node(HELP_OP, $1, make_str_node($3));} + | VAR ASSIGN val + {$$ = make_node(ASSIGN_OP, make_var_node($1), $3);} + ; + +val: VAR {$$ = make_var_node($1);} + | val0 {$$ = make_val_node(&($1));} + | EX_STRING {$$=make_str_node0($1, B_QUOTE_OP);} + ; + +val0: VALUE + + | val0 COMMA val0 { add_val(&($1), &($3)); $$=$1; } + + | STRING {$$ = str2val($1);} + ; + +syntax_error: SYNTAX_ERROR { + cli_deferror("syntax error"); + } + ; + + +%% +char *parse_path; +int parse_def(vtw_def *defp, char *path, boolean type_only) +{ + int status; + yy_cli_def_lineno = 1; + parse_status = 0; + parse_defp = defp; + cli_def_type_only = type_only; + yy_cli_def_in = fopen(path, "r"); +#if 0 + yy_cli_parse_debug = 1; +#endif + if (!yy_cli_def_in) + return -5; + parse_path = path; + status = yy_cli_parse_parse(); /* 0 is OK */ + fclose(yy_cli_def_in); + return status; +} +static void +cli_deferror(const char *s) +{ + printf("Error: %s in file %s, line %d\n",s, parse_path, + yy_cli_def_lineno); +} + +void yy_cli_parse_error(const char *s) +{ + cli_deferror(s); +} + + + + + |