summaryrefslogtreecommitdiffhomepage
path: root/parser.y
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2020-08-10 17:05:03 +0200
committerJo-Philipp Wich <jo@mein.io>2020-08-21 23:04:45 +0200
commita56887df2a0f51b42d9d4013515e847b1a050c58 (patch)
tree3416726feacc13d8a94e4fda90edc1a6773fa71e /parser.y
Initial commit
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'parser.y')
-rw-r--r--parser.y290
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; }