%{ #include #include #include #include "gram.h" #include int yyerror(char *msg); int yylex(); PUBLIC gram_t::gram_t() { val = 0; type = TYPE_INT; } PUBLIC gram_t::gram_t(const gram_t &c) { val = c.val; type = c.type; res = c.res; var = c.var; s = c.s; } PUBLIC void gram_t::operator =(const gram_t &c) { val = c.val; type = c.type; res = c.res; var = c.var; s = c.s; } PUBLIC void gram_t::print(){ if (type == TYPE_INT){ printf ("%d",val); }else if (type == TYPE_LIST){ const char *prefix = ""; printf ("{"); for (unsigned i=0; i 1){ sort (ret.res.begin(),ret.res.end()); for (unsigned i=0; i 1){ gram_t tmp = *this; sort (tmp.res.begin(),tmp.res.end()); gram_t tmp2; tmp2.type = TYPE_LIST; for (unsigned i=0; i s+1) e--; ret.res.push_back(string(s,e)); } } }else if (name == "grep"){ if (arg == NULL){ yyerror ("Missing argument from grep function"); }else{ ret.type = TYPE_LIST; regex_t r; if (regcomp(&r,arg->s.c_str(),REG_NOSUB)==-1){ yyerror ("Invalid grep expression"); }else{ for (unsigned i=0; i vars; %} %token NB EQ PLUS MOINS DIV XOR FUNC FOIS FIN PARO PARC EOL VAR COMMA OPENB CLOSEB DOT AND SCOL %left PLUS MOINS XOR DOT AND SCOL %left FOIS DIV %start AXIOME %% AXIOME : FIN | LINE | AXIOME LINE ; LINE : EXP EOL { gram_res = $1; printf("RES "); if (testing){$1.print(); printf ("\n" );} } | VAR EQ EXP EOL { vars[$1.var]=$3; gram_res=$3; if (testing){printf ("VAR %s = ",$1.var.c_str()); $3.print(); printf ("\n"); } } | EOL ; EXP : NB { $$ = $1 } | VAR { $$ = $1 } | LIST { $$ = $1 } | PARO EXP PARC { $$ = $2 } | EXP PLUS EXP { $$ = $1 + $3 } | EXP MOINS EXP { $$ = $1 - $3 } | EXP XOR EXP { $$ = $1 ^ $3 } | EXP AND EXP { $$ = $1 & $3 } | EXP SCOL EXP { $$ = $1.concat($3) } | EXP FOIS EXP { $$.val = $1.val * $3.val } | EXP DIV EXP { $$.val = $1.val / $3.val } | EXP DOT FUNC PARO EXP PARC { $$ = $1.func($3.s,&$5) } | EXP DOT FUNC PARO PARC { $$ = $1.func($3.s,NULL) } ; LIST : OPENB ARGS CLOSEB { $$.res = $2.res; $$.type = TYPE_LIST} ARGS : EXP { $$.res.push_back($1.s)} | ARGS COMMA EXP { $$.res = $1.res; $$.res.push_back($3.s) } ; %% #include static int noline = 1; static const char *input_buf = NULL; static bool gram_errors = false; int yyerror(char *msg) { gram_errors = true; fprintf(stderr,"Line %d: %s\n",noline,msg); return 0; } static int gram_getchar() { int car = EOF; if (input_buf != NULL){ if (*input_buf != '\0') car = *input_buf++; }else{ car = getchar() ; } return car; } int yylex( ) { static bool is_init = false; static set funcs; if (!is_init){ is_init = true; funcs.insert ("sort"); funcs.insert ("uniq"); funcs.insert ("notuniq"); funcs.insert ("basename"); funcs.insert ("dirname"); funcs.insert ("grep"); funcs.insert ("sed"); funcs.insert ("count"); } yylval.type = TYPE_INT; yylval.res.clear(); yylval.val = 0; yylval.var = ""; while(1){ yylval.s = ""; int car = gram_getchar(); if ( car == EOF ) return 0 ; if ( isdigit(car) ) { yylval.val = 0; while(1){ yylval.s += (char)car; yylval.val *= 10; yylval.val += car - '0'; car = gram_getchar(); if (!isdigit(car)){ if (input_buf != NULL){ input_buf--; }else{ ungetc(car,stdin); } break; } } return NB; } if (isalpha(car)){ while(1){ yylval.s += (char)car; car = gram_getchar(); if (!isalnum(car)){ if (input_buf != NULL){ input_buf--; }else{ ungetc(car,stdin); } break; } } if (funcs.count(yylval.s)>0){ return FUNC; }else{ yylval.var = yylval.s; yylval.val = vars[yylval.var].val; yylval.res = vars[yylval.var].res; yylval.type = vars[yylval.var].type; return VAR; } } if (car == '"'){ while(1){ car = gram_getchar(); if (car == '"') break; if (car == '\n') break; yylval.s += (char)car; } return NB; } // if (car == '\n') return EOL; yylval.s = (char)car; if (!isspace(car)){ switch ( car ) { case '+' : return PLUS; case '-' : return MOINS; case '^' : return XOR; case '/' : return DIV; case '*': return FOIS; case '(': return PARO; case ')': return PARC; case '{': return OPENB; case '}': return CLOSEB; case ',': return COMMA; case '&': return AND; case '.': return DOT; case ':': return SCOL; case ';': return EOL; case '=': return EQ; } } if (car == '\n') noline++; } } void gram_setvar (const char *v, const char *val) { gram_t x; x.type = TYPE_INT; x.s = val; x.val = atoi(val); vars[v] = x; } void gram_setvar (const char *v, const vector &vals) { gram_t x; x.type = TYPE_LIST; x.res = vals; vars[v] = x; } gram_t *gram_getvar(const char *name) { gram_t *ret = NULL; map::iterator it = vars.find(name); if (it != vars.end()){ ret = &it->second; } return ret; } int gram_getvars(strings &names) { for (map::iterator it = vars.begin(); it != vars.end(); it++){ names.push_back(it->first); } return names.size(); } gram_t *gram_eval (const char *s, string &error) { noline = 1; input_buf = s; gram_errors = false; // printf ("Eval :%s:\n",s); yyparse(); input_buf = ""; return gram_errors ? NULL : &gram_res; } #ifdef TEST int main( int argc, char *argv[] ) { testing=true; yyparse() ; } #endif