Mercurial > lbo > hg > ylisp
view gen/y.yy @ 174:0c4e9e76a2f2
all: Make ylisp work in Release mode too
by changing the way asserts are used when there are side-effects.
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Mon, 09 Sep 2019 19:57:39 +0200 |
parents | 1b2bd8c6cc25 |
children |
line wrap: on
line source
%code requires{ typedef void* yyscan_t; #include <src/expr.h> #include <src/value.h> #include <src/base/str.h> #include <src/base/vec.h> } %{ #include <assert.h> #include <error.h> #include <stdio.h> #include <string.h> #include <gen/y.tab.h> bool YENABLE_DEBUG_PRINT = false; #define ydbg_print(...) if (YENABLE_DEBUG_PRINT) fprintf(stderr, __VA_ARGS__) // Our error handler void yyerror(void* ignored, void* ignored2, ystr_t* ystr_error, char const* s); // Declare flex-generated functions int yylex(YYSTYPE* v, void* scanner); int yylex_init (yyscan_t* scanner); int yylex_destroy ( yyscan_t yyscanner ); void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); %} %define parse.error verbose %{ // The `scan` parameter is present in yyparse() as first argument and forwarded to yylex() as second argument. %} %param {void* scan} %{ // The output_yexprs parameter is only present in yyparse() as second argument and used in actions. %} %parse-param {yvec_t* output_yexprs} %{ // The ystr_error parameter is only present in yyparse. %} %parse-param {ystr_t* ystr_error} %{ // Supply yylval argument to yylex(). %} %define api.pure full %define lr.type ielr %union yvalue { // Parsed values ('semantic values'): // More yexprs. yvec_t exprs; // One yexpr. yexpr_t expr; // A reference. yref_t ref; // Lexed values: // A number literal (todo: floats) long long number; // A string literal. char* string; // An atom. char* atom; } %{ // Type of yylval. %} %token <number> TOK_NUMBER_LITERAL %token <string> TOK_STRING_LITERAL %token <atom> TOK_ATOM %token TOK_QUOTE %token TOK_LEFTP %token TOK_RIGHTP %type <exprs> many_sexpr %type <expr> sexpr %type <expr> literal %type <expr> inner_sexpr %type <expr> inner_quoted_sexpr %type <expr> value %type <expr> quoted_value %% prog: many_sexpr { // Assign overall result (list of yexpr_t) to parser's output // argument. yvec_append(output_yexprs, &$1); yvec_destroy(&$1); ydbg_print("finished\n"); } many_sexpr: many_sexpr sexpr { // Push found sexpr to previous sexprs. YVEC_PUSH(&$1, &$2); // Push result on stack. $$ = $1; } | %empty { yvec_t v; YVEC_INIT(&v, 0, yexpr_t); $$ = v; }; sexpr: TOK_QUOTE TOK_LEFTP inner_quoted_sexpr TOK_RIGHTP { ydbg_print("found quoted sexpr\n"); $$ = $3; } | TOK_LEFTP inner_sexpr TOK_RIGHTP { ydbg_print("found sexpr\n"); $$ = $2; }; inner_quoted_sexpr: inner_quoted_sexpr quoted_value { yexpr_init_or_extend(&$1, $2); $$ = $1; } // A quoted sexpr can contain more sexprs, but they are quoted too. | inner_quoted_sexpr TOK_LEFTP inner_quoted_sexpr TOK_RIGHTP { yexpr_init_or_extend(&$1, $3); $$ = $1; } | %empty { ydbg_print("finished quoted sexpr\n"); yexpr_t e = yexpr_new(); yvec_t v; YVEC_INIT(&v, 0, yexpr_t); yexpr_set_list(&e, v); $$ = e; }; inner_sexpr: inner_sexpr value { yexpr_init_or_extend(&$1, $2); $$ = $1; } | inner_sexpr sexpr { yexpr_init_or_extend(&$1, $2); $$ = $1; } | %empty { ydbg_print("finished sexpr\n"); yexpr_t e = yexpr_new(); yvec_t v; YVEC_INIT(&v, 0, yexpr_t); yexpr_set_list(&e, v); $$ = e; }; value: TOK_QUOTE quoted_value { ydbg_print("found quoted value\n"); $$ = $2; } | TOK_ATOM { ydbg_print("found ID %s\n", $1); ystr_t sym = ystr_new(NULL); ystr_set_owned(&sym, $1); yref_t ref = yref_new_str(&sym); yexpr_t expr = yexpr_new(); yexpr_set_ref(&expr, ref); $$ = expr; } | literal; quoted_value: TOK_ATOM { ydbg_print("found atom %s\n", $1); yexpr_t expr = yexpr_new(); yexpr_set_atom_name(&expr, $1); free($1); $$ = expr; } | literal; literal: TOK_NUMBER_LITERAL { ydbg_print("found number %lld\n", $1); yexpr_t expr = yexpr_new(); yexpr_set_number(&expr, $1); $$ = expr; } | TOK_STRING_LITERAL { ydbg_print("found string %s\n", $1); yexpr_t expr = yexpr_new(); ystr_t str = ystr_new(NULL); ystr_set_owned(&str, $1); yexpr_set_str(&expr, str); $$ = expr; }; %% int y_bison_parse(FILE* in, yvec_t* out_exprs, ystr_t* ystr_error) { void* scanner; int r; if (0 != (r = yylex_init(&scanner))) { error(r, 0, "couldn't initialize scanner!"); exit(1); } #ifndef DEBUG FILE* out = fopen("/dev/null", "w"); #else FILE* out = stdout; #endif yyset_in(in, scanner); yyset_out(out, scanner); YVEC_INIT(out_exprs, 16, yexpr_t); int ret = yyparse(scanner, out_exprs, ystr_error); #ifndef DEBUG fclose(out); #endif int lex_destroy_ok = yylex_destroy(scanner); assert(0 == lex_destroy_ok); return ret; } void yyerror(void* _scanner, void* _output, ystr_t* ystr_error, char const* s) { ystr_t s2 = ystr_new(NULL); ystr_set_owned(&s2, (char*)s); // no destroy! ystr_append(ystr_error, &s2); }