diff options
author | Jo-Philipp Wich <jo@mein.io> | 2020-08-10 17:05:03 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2020-08-21 23:04:45 +0200 |
commit | a56887df2a0f51b42d9d4013515e847b1a050c58 (patch) | |
tree | 3416726feacc13d8a94e4fda90edc1a6773fa71e /parser.y |
Initial commit
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'parser.y')
-rw-r--r-- | parser.y | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/parser.y b/parser.y new file mode 100644 index 0000000..eab4583 --- /dev/null +++ b/parser.y @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2020 Jo-Philipp Wich <jo@mein.io> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +%token_type {struct ut_opcode *} +%extra_argument {struct ut_state *s} + +%nonassoc T_LEXP T_REXP T_LSTM T_RSTM. + +%nonassoc T_IF. +%nonassoc T_ELSE. + +%left T_COMMA. +%right T_ASBAND T_ASBXOR T_ASBOR. +%right T_ASLEFT T_ASRIGHT. +%right T_ASMUL T_ASDIV T_ASMOD. +%right T_ASADD T_ASSUB. +%right T_ASSIGN. +%right T_QMARK T_COLON. +%left T_OR. +%left T_AND. +%left T_BOR. +%left T_BXOR. +%left T_BAND. +%left T_IN. +%left T_EQ T_NE. +%left T_LT T_LE T_GT T_GE. +%left T_LSHIFT T_RSHIFT. +%left T_ADD T_SUB. +%left T_MUL T_DIV T_MOD. +%right T_NOT T_COMPL. +%right T_INC T_DEC. +%left T_LPAREN T_LBRACK. + + +%include { +#include <assert.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#include "ast.h" +#include "lexer.h" +#include "parser.h" + +#define YYSTACKDEPTH 0 +#define YYNOERRORRECOVERY + +#define new_op(type, val, ...) \ + ut_new_op(s, type, val, ##__VA_ARGS__, (void *)1) + +#define wrap_op(op, ...) \ + ut_wrap_op(op, ##__VA_ARGS__, (void *)1) + +#define append_op ut_append_op + +#define no_empty_obj(op) \ + ((!op || op->type != T_LBRACE || op->operand[0]) ? op : NULL) + +#define new_func(name, args, body) \ + ut_new_func(s, name, args, body) + +} + +%syntax_error { + int i; + + s->error.code = UT_ERROR_UNEXPECTED_TOKEN; + + if (TOKEN) + s->off = TOKEN->off; + + for (i = 0; i < sizeof(tokennames) / sizeof(tokennames[0]); i++) + if (yy_find_shift_action(yypParser, (YYCODETYPE)i) < YYNSTATE + YYNRULE) + s->error.info.tokens[i / 64] |= ((unsigned)1 << (i % 64)); +} + + +input ::= chunks(A). { s->main = new_func(NULL, NULL, A); } +input ::= . { s->main = new_func(NULL, NULL, new_op(T_TEXT, json_object_new_string(""))); } + +chunks(A) ::= chunks(B) T_TEXT(C). { A = B ? append_op(B, C) : C; } +chunks(A) ::= chunks(B) tplexp(C). { A = B ? append_op(B, C) : C; } +chunks(A) ::= chunks(B) stmt(C). { A = B ? append_op(B, C) : C; } +chunks(A) ::= T_TEXT(B). { A = B; } +chunks(A) ::= tplexp(B). { A = B; } +chunks(A) ::= stmt(B). { A = B; } + +tplexp(A) ::= T_LEXP(B) exp_stmt(C) T_REXP. { A = wrap_op(B, C); } + +stmts(A) ::= stmts(B) stmt(C). { A = B ? append_op(B, C) : C; } +stmts(A) ::= stmt(B). { A = B; } + +stmt(A) ::= cpd_stmt(B). { A = B; } +stmt(A) ::= exp_stmt(B). { A = B; } +stmt(A) ::= sel_stmt(B). { A = B; } +stmt(A) ::= iter_stmt(B). { A = B; } +stmt(A) ::= func_stmt(B). { A = B; } +stmt(A) ::= ret_stmt(B). { A = B; } +stmt(A) ::= break_stmt(B). { A = B; } +stmt(A) ::= decl_stmt(B). { A = B; } + +//cpd_stmt(A) ::= T_LBRACE T_RBRACE. { A = NULL; } +cpd_stmt(A) ::= T_LBRACE stmts(B) T_RBRACE. { A = B; } + +exp_stmt(A) ::= exp(B) T_SCOL. { A = B; } +exp_stmt(A) ::= T_SCOL. { A = NULL; } + +sel_stmt(A) ::= T_IF(B) T_LPAREN exp(C) T_RPAREN stmt(D) T_ELSE stmt(E). + { A = wrap_op(B, C, no_empty_obj(D), no_empty_obj(E)); } +sel_stmt(A) ::= T_IF(B) T_LPAREN exp(C) T_RPAREN stmt(D). [T_IF] + { A = wrap_op(B, C, no_empty_obj(D)); } +sel_stmt(A) ::= T_IF(B) T_LPAREN exp(C) T_RPAREN T_COLON chunks(D) T_ELSE chunks(E) T_ENDIF. + { A = wrap_op(B, C, D, E); } +sel_stmt(A) ::= T_IF(B) T_LPAREN exp(C) T_RPAREN T_COLON chunks(D) T_ENDIF. [T_IF] + { A = wrap_op(B, C, D); } + +iter_stmt(A) ::= T_WHILE(B) T_LPAREN exp(C) T_RPAREN stmt(D). + { A = wrap_op(B, C, no_empty_obj(D)); } +iter_stmt(A) ::= T_WHILE(B) T_LPAREN exp(C) T_RPAREN T_COLON chunks(D) T_ENDWHILE. + { A = wrap_op(B, C, D); } +iter_stmt(A) ::= T_FOR(B) T_LPAREN exp(C) T_RPAREN stmt(D). + { A = wrap_op(B, C, NULL, NULL, no_empty_obj(D)); } +iter_stmt(A) ::= T_FOR(B) T_LPAREN exp(C) T_RPAREN T_COLON chunks(D) T_ENDFOR. + { A = wrap_op(B, C, NULL, NULL, no_empty_obj(D)); } +iter_stmt(A) ::= T_FOR(B) T_LPAREN exp_stmt(C) exp_stmt(D) T_RPAREN stmt(E). + { A = wrap_op(B, C, D, NULL, no_empty_obj(E)); } +iter_stmt(A) ::= T_FOR(B) T_LPAREN exp_stmt(C) exp_stmt(D) exp(E) T_RPAREN stmt(F). + { A = wrap_op(B, C, D, E, no_empty_obj(F)); } +iter_stmt(A) ::= T_FOR(B) T_LPAREN exp_stmt(C) exp_stmt(D) T_RPAREN T_COLON chunks(E) T_ENDFOR. + { A = wrap_op(B, C, D, NULL, E); } +iter_stmt(A) ::= T_FOR(B) T_LPAREN exp_stmt(C) exp_stmt(D) exp(E) T_RPAREN T_COLON chunks(F) T_ENDFOR. + { A = wrap_op(B, C, D, E, F); } + +func_stmt(A) ::= T_FUNC T_LABEL(B) T_LPAREN T_RPAREN cpd_stmt(C). + { A = new_func(B, NULL, C); } +func_stmt(A) ::= T_FUNC T_LABEL(B) T_LPAREN T_RPAREN empty_object. + { A = new_func(B, NULL, NULL); } +func_stmt(A) ::= T_FUNC T_LABEL(B) T_LPAREN T_RPAREN T_COLON chunks(C) T_ENDFUNC. + { A = new_func(B, NULL, C); } +func_stmt(A) ::= T_FUNC T_LABEL(B) T_LPAREN args(C) T_RPAREN cpd_stmt(D). + { A = new_func(B, C, D); } +func_stmt(A) ::= T_FUNC T_LABEL(B) T_LPAREN args(C) T_RPAREN empty_object. + { A = new_func(B, C, NULL); } +func_stmt(A) ::= T_FUNC T_LABEL(B) T_LPAREN args(C) T_RPAREN T_COLON chunks(D) T_ENDFUNC. + { A = new_func(B, C, D); } + +args(A) ::= args(B) T_COMMA T_LABEL(C). { A = append_op(B, C); } +args(A) ::= T_LABEL(B). { A = B; } + +ret_stmt(A) ::= T_RETURN(B) exp(C) T_SCOL. { A = wrap_op(B, C); } +ret_stmt(A) ::= T_RETURN(B) T_SCOL. { A = B; } + +break_stmt(A) ::= T_BREAK(B) T_SCOL. { A = B; } +break_stmt(A) ::= T_CONTINUE(B) T_SCOL. { A = B; } + +decl_stmt(A) ::= T_LOCAL(B) decls(C) T_SCOL. { A = wrap_op(B, C); } + +decls(A) ::= decls(B) T_COMMA decl(C). { A = append_op(B, C); } +decls(A) ::= decl(B). { A = B; } + +decl(A) ::= T_LABEL(B) T_ASSIGN(C) ternary_exp(D). { A = wrap_op(C, B, D); } +decl(A) ::= T_LABEL(B). { A = new_op(T_ASSIGN, NULL, B); } + +exp(A) ::= exp(B) T_COMMA assign_exp(C). { A = append_op(B, C); } +exp(A) ::= assign_exp(B). { A = B; } + +assign_exp(A) ::= unary_exp(B) T_ASSIGN(C) ternary_exp(D). + { A = wrap_op(C, B, D); } +assign_exp(A) ::= unary_exp(B) T_ASADD ternary_exp(C). { A = new_op(T_ADD, NULL, B, C); A = new_op(T_ASSIGN, NULL, B, A); } +assign_exp(A) ::= unary_exp(B) T_ASSUB ternary_exp(C). { A = new_op(T_SUB, NULL, B, C); A = new_op(T_ASSIGN, NULL, B, A); } +assign_exp(A) ::= unary_exp(B) T_ASMUL ternary_exp(C). { A = new_op(T_MUL, NULL, B, C); A = new_op(T_ASSIGN, NULL, B, A); } +assign_exp(A) ::= unary_exp(B) T_ASDIV ternary_exp(C). { A = new_op(T_DIV, NULL, B, C); A = new_op(T_ASSIGN, NULL, B, A); } +assign_exp(A) ::= unary_exp(B) T_ASMOD ternary_exp(C). { A = new_op(T_MOD, NULL, B, C); A = new_op(T_ASSIGN, NULL, B, A); } +assign_exp(A) ::= unary_exp(B) T_ASLEFT ternary_exp(C). { A = new_op(T_LSHIFT, NULL, B, C); A = new_op(T_ASSIGN, NULL, B, A); } +assign_exp(A) ::= unary_exp(B) T_ASRIGHT ternary_exp(C). + { A = new_op(T_RSHIFT, NULL, B, C); A = new_op(T_ASSIGN, NULL, B, A); } +assign_exp(A) ::= unary_exp(B) T_ASBAND ternary_exp(C). { A = new_op(T_BAND, NULL, B, C); A = new_op(T_ASSIGN, NULL, B, A); } +assign_exp(A) ::= unary_exp(B) T_ASBXOR ternary_exp(C). { A = new_op(T_BXOR, NULL, B, C); A = new_op(T_ASSIGN, NULL, B, A); } +assign_exp(A) ::= unary_exp(B) T_ASBOR ternary_exp(C). { A = new_op(T_BOR, NULL, B, C); A = new_op(T_ASSIGN, NULL, B, A); } +assign_exp(A) ::= ternary_exp(B). { A = B; } + +ternary_exp(A) ::= or_exp(B) T_QMARK(C) assign_exp(D) T_COLON ternary_exp(E). + { A = wrap_op(C, B, D, E); } +ternary_exp(A) ::= or_exp(B). { A = B; } + +or_exp(A) ::= or_exp(B) T_OR(C) and_exp(D). { A = wrap_op(C, B, D); } +or_exp(A) ::= and_exp(B). { A = B; } + +and_exp(A) ::= and_exp(B) T_AND(C) bor_exp(D). { A = wrap_op(C, B, D); } +and_exp(A) ::= bor_exp(B). { A = B; } + +bor_exp(A) ::= bor_exp(B) T_BOR(C) bxor_exp(D). { A = wrap_op(C, B, D); } +bor_exp(A) ::= bxor_exp(B). { A = B; } + +bxor_exp(A) ::= bxor_exp(B) T_BXOR(C) band_exp(D). { A = wrap_op(C, B, D); } +bxor_exp(A) ::= band_exp(B). { A = B; } + +band_exp(A) ::= band_exp(B) T_BAND(C) in_exp(D). { A = wrap_op(C, B, D); } +band_exp(A) ::= in_exp(B). { A = B; } + +in_exp(A) ::= equal_exp(B) T_IN(C) equal_exp(D). { A = wrap_op(C, B, D); } +in_exp(A) ::= equal_exp(B). { A = B; } + +equal_exp(A) ::= equal_exp(B) T_EQ(C) rel_exp(D). { A = wrap_op(C, B, D); } +equal_exp(A) ::= equal_exp(B) T_NE(C) rel_exp(D). { A = wrap_op(C, B, D); } +equal_exp(A) ::= rel_exp(B). { A = B; } + +rel_exp(A) ::= rel_exp(B) T_LT(C) shift_exp(D). { A = wrap_op(C, B, D); } +rel_exp(A) ::= rel_exp(B) T_LE(C) shift_exp(D). { A = wrap_op(C, B, D); } +rel_exp(A) ::= rel_exp(B) T_GT(C) shift_exp(D). { A = wrap_op(C, B, D); } +rel_exp(A) ::= rel_exp(B) T_GE(C) shift_exp(D). { A = wrap_op(C, B, D); } +rel_exp(A) ::= shift_exp(B). { A = B; } + +shift_exp(A) ::= shift_exp(B) T_LSHIFT(C) add_exp(D). { A = wrap_op(C, B, D); } +shift_exp(A) ::= shift_exp(B) T_RSHIFT(C) add_exp(D). { A = wrap_op(C, B, D); } +shift_exp(A) ::= add_exp(B). { A = B; } + +add_exp(A) ::= add_exp(B) T_ADD(C) mul_exp(D). { A = wrap_op(C, B, D); } +add_exp(A) ::= add_exp(B) T_SUB(C) mul_exp(D). { A = wrap_op(C, B, D); } +add_exp(A) ::= mul_exp(B). { A = B; } + +mul_exp(A) ::= mul_exp(B) T_MUL(C) unary_exp(D). { A = wrap_op(C, B, D); } +mul_exp(A) ::= mul_exp(B) T_DIV(C) unary_exp(D). { A = wrap_op(C, B, D); } +mul_exp(A) ::= mul_exp(B) T_MOD(C) unary_exp(D). { A = wrap_op(C, B, D); } +mul_exp(A) ::= unary_exp(B). { A = B; } + +unary_exp(A) ::= T_INC(B) unary_exp(C). [T_LPAREN] { A = wrap_op(B, C); } +unary_exp(A) ::= T_DEC(B) unary_exp(C). [T_LPAREN] { A = wrap_op(B, C); } +unary_exp(A) ::= T_ADD(B) unary_exp(C). [T_NOT] { A = wrap_op(B, C); } +unary_exp(A) ::= T_SUB(B) unary_exp(C). [T_NOT] { A = wrap_op(B, C); } +unary_exp(A) ::= T_COMPL(B) unary_exp(C). { A = wrap_op(B, C); } +unary_exp(A) ::= T_NOT(B) unary_exp(C). { A = wrap_op(B, C); } +unary_exp(A) ::= postfix_exp(B). { A = B; } + +postfix_exp(A) ::= unary_exp(B) T_INC(C). { A = wrap_op(C, B); A->val = (void *)1; } +postfix_exp(A) ::= unary_exp(B) T_DEC(C). { A = wrap_op(C, B); A->val = (void *)1; } +postfix_exp(A) ::= unary_exp(B) T_LPAREN(C) T_RPAREN. { A = wrap_op(C, B); } +postfix_exp(A) ::= unary_exp(B) T_LPAREN(C) arg_exp(D) T_RPAREN. + { A = wrap_op(C, B, D); } +postfix_exp(A) ::= postfix_exp(B) T_DOT(C) T_LABEL(D). { A = wrap_op(C, B, D); } +postfix_exp(A) ::= postfix_exp(B) T_LBRACK(C) assign_exp(D) T_RBRACK. + { A = wrap_op(C, B, D); A->val = (void *)1; } +postfix_exp(A) ::= primary_exp(B). { A = B; } + +primary_exp(A) ::= T_BOOL(B). { A = B; } +primary_exp(A) ::= T_NUMBER(B). { A = B; } +primary_exp(A) ::= T_DOUBLE(B). { A = B; } +primary_exp(A) ::= T_STRING(B). { A = B; } +primary_exp(A) ::= T_LABEL(B). { A = B; } +primary_exp(A) ::= array(B). { A = B; } +primary_exp(A) ::= object(B). { A = B; } +primary_exp(A) ::= T_LPAREN assign_exp(B) T_RPAREN. { A = B; } +primary_exp(A) ::= T_FUNC T_LPAREN T_RPAREN empty_object. + { A = new_func(NULL, NULL, NULL); } +primary_exp(A) ::= T_FUNC T_LPAREN args(B) T_RPAREN empty_object. + { A = new_func(NULL, B, NULL); } +primary_exp(A) ::= T_FUNC T_LPAREN T_RPAREN cpd_stmt(B). + { A = new_func(NULL, NULL, B); } +primary_exp(A) ::= T_FUNC T_LPAREN args(B) T_RPAREN cpd_stmt(C). + { A = new_func(NULL, B, C); } + +array(A) ::= T_LBRACK(B) T_RBRACK. { A = B; } +array(A) ::= T_LBRACK(B) exp(C) T_RBRACK. { A = wrap_op(B, C); } + +object(A) ::= empty_object(B). { A = B; } +object(A) ::= T_LBRACE(B) tuples(C) T_RBRACE. { A = wrap_op(B, C); } + +empty_object(A) ::= T_LBRACE(B) T_RBRACE. { A = B; } + +tuples(A) ::= tuples(B) T_COMMA tuple(C). { A = append_op(B, C); } +tuples(A) ::= tuple(B). { A = B; } + +tuple(A) ::= T_LABEL(B) T_COLON exp(C). { A = append_op(B, C); } +tuple(A) ::= T_STRING(B) T_COLON exp(C). { A = append_op(B, C); } + +arg_exp(A) ::= arg_exp(B) T_COMMA assign_exp(C). { A = append_op(B, C); } +arg_exp(A) ::= assign_exp(B). { A = B; } |