summaryrefslogtreecommitdiffabout
path: root/lib/forlangrm.y
Side-by-side diff
Diffstat (limited to 'lib/forlangrm.y') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/forlangrm.y237
1 files changed, 237 insertions, 0 deletions
diff --git a/lib/forlangrm.y b/lib/forlangrm.y
new file mode 100644
index 0000000..1b7781d
--- a/dev/null
+++ b/lib/forlangrm.y
@@ -0,0 +1,237 @@
+%{
+/* This file is part of Eclat.
+ Copyright (C) 2012 Sergey Poznyakoff.
+
+ Eclat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ Eclat is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "libeclat.h"
+#include <grecs.h>
+#include <grecs-locus.h>
+#include "forlangrm.h"
+#include "forlan.h"
+
+static int yyerror(char *);
+union forlan_node *forlan_parse_tree;
+%}
+%error-verbose
+%locations
+
+%union {
+ char *string;
+ union forlan_node *node;
+ struct grecs_list *list;
+};
+
+%token <string> STRING IDENT
+%token LAST IF ELSE
+
+%left OR
+%left AND
+%left NOT
+
+%type <node> stmt stmt_cond stmt_expr stmt_blk cond bool node comp funcall arg
+%type <list> stmtlist complist arglist
+%type <string> string
+
+%%
+input : stmtlist
+ {
+ forlan_parse_tree = forlan_stmt_from_list($1);
+ }
+ ;
+
+stmtlist : stmt
+ {
+ $$ = forlan_stmt_list();
+ grecs_list_append($$, $1);
+ }
+ | stmtlist stmt
+ {
+ grecs_list_append($1, $2);
+ $$ = $1;
+ }
+ ;
+
+stmt : stmt_cond
+ | stmt_expr
+ | stmt_blk
+ ;
+
+stmt_blk : '{' stmtlist '}'
+ {
+ $$ = forlan_stmt_from_list($2);
+ }
+ ;
+
+stmt_cond : IF cond stmt
+ {
+ $$ = forlan_node_create(forlan_type_cond);
+ $$->cond.expr = $2;
+ $$->cond.iftrue = $3;
+ $$->cond.iffalse = NULL;
+ }
+ | IF cond stmt ELSE stmt
+ {
+ $$ = forlan_node_create(forlan_type_cond);
+ $$->cond.expr = $2;
+ $$->cond.iftrue = $3;
+ $$->cond.iffalse = $5;
+ }
+ ;
+
+cond : bool
+ ;
+
+bool : node
+ {
+ $$ = forlan_node_create(forlan_type_expr);
+ $$->expr.opcode = forlan_opcode_node;
+ $$->expr.arg[0] = $1;
+ }
+ | bool AND bool
+ {
+ $$ = forlan_node_create(forlan_type_expr);
+ $$->expr.opcode = forlan_opcode_and;
+ $$->expr.arg[0] = $1;
+ $$->expr.arg[1] = $3;
+ }
+ | bool OR bool
+ {
+ $$ = forlan_node_create(forlan_type_expr);
+ $$->expr.opcode = forlan_opcode_or;
+ $$->expr.arg[0] = $1;
+ $$->expr.arg[1] = $3;
+ }
+ | NOT bool
+ {
+ $$ = forlan_node_create(forlan_type_expr);
+ $$->expr.opcode = forlan_opcode_not;
+ $$->expr.arg[0] = $2;
+ }
+ | '(' bool ')'
+ {
+ $$ = $2;
+ }
+ ;
+
+node : complist
+ {
+ $$ = forlan_node_create(forlan_type_comp);
+ $$->comp.abs = 0;
+ $$->comp.node = forlan_stmt_from_list($1);
+ }
+ | '.' complist
+ {
+ $$ = forlan_node_create(forlan_type_comp);
+ $$->comp.abs = 1;
+ $$->comp.node = forlan_stmt_from_list($2);
+ }
+ | LAST
+ {
+ $$ = forlan_node_create(forlan_type_last);
+ }
+ ;
+
+complist : comp
+ {
+ $$ = forlan_stmt_list();
+ grecs_list_append($$, $1);
+ }
+ | complist '.' comp
+ {
+ grecs_list_append($1, $3);
+ $$ = $1;
+ }
+ ;
+
+comp : IDENT
+ {
+ $$ = forlan_node_create(forlan_type_lit);
+ $$->lit.string = $1;
+ }
+ | IDENT '[' string ']'
+ {
+ $$ = forlan_node_create(forlan_type_test);
+ $$->test.comp = $1;
+ $$->test.value = $3;
+ }
+ | funcall
+ ;
+
+string : IDENT
+ | STRING
+ ;
+
+funcall : IDENT '(' ')'
+ {
+ $$ = forlan_node_create(forlan_type_func);
+ $$->func.fp = $1; //FIXME
+ $$->func.args = NULL;
+ }
+ | IDENT '(' arglist ')'
+ {
+ $$ = forlan_node_create(forlan_type_func);
+ $$->func.fp = $1; //FIXME
+ $$->func.args = $3;
+ }
+ ;
+
+arglist : arg
+ {
+ $$ = forlan_stmt_list();
+ grecs_list_append($$, $1);
+ }
+ | arglist ',' arg
+ {
+ grecs_list_append($1, $3);
+ $$ = $1;
+ }
+ ;
+
+arg : node
+ | STRING
+ {
+ $$ = forlan_node_create(forlan_type_lit);
+ $$->lit.string = $1;
+ }
+ ;
+
+stmt_expr : funcall ';'
+ ;
+%%
+static int
+yyerror(char *s)
+{
+ grecs_error(&yylloc, 0, "%s", s);
+ return 0;
+}
+
+int
+forlan_parser()
+{
+ yydebug = debug_level(forlan_dbg) >= FORLAN_DBG_GRAM;
+ return yyparse();
+}
+
+int
+forlan_parse(const char *input, size_t length, struct grecs_locus_point *pt)
+{
+ int rc;
+ forlan_lex_begin(input, length, pt);
+ rc = forlan_parser();
+ forlan_lex_end();
+ return rc;
+}
+
+

Return to:

Send suggestions and report system problems to the System administrator.