/* This file is part of Eclat. Copyright (C) 2012-2015 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 . */ #define FORLAN_DBG_LEX 3 #define FORLAN_DBG_GRAM 2 #define FORLAN_DBG_EVAL 1 typedef struct forlan_eval_env *forlan_eval_env_t; extern int forlan_dbg; void forlan_init(); void forlan_lex_from_buffer(const char *input, size_t length, struct grecs_locus_point *pt); void forlan_lex_from_file(FILE *fp, struct grecs_locus_point *pt); void forlan_lex_end(void); forlan_eval_env_t forlan_parse_buffer(const char *input, size_t length, struct grecs_locus_point *pt); forlan_eval_env_t forlan_parse_file(FILE *fp, struct grecs_locus_point *pt); union forlan_node; /* Declared below */ enum forlan_type { forlan_type_null, /* Unknown/unset type */ forlan_type_comp, /* A path component */ forlan_type_test, /* Value test (f[X]) */ forlan_type_func, /* Function call */ forlan_type_cond, /* Conditional */ forlan_type_stmt, /* Statement */ forlan_type_lit, /* Literal */ forlan_type_expr, /* Boolean expression */ forlan_type_last, /* Return last evaluated grecs_node */ forlan_type_asgn, /* Variable assignment */ forlan_type_var, /* Variable reference */ forlan_type_loop, /* Loop */ forlan_type_continue, /* continue statement */ forlan_type_break, /* break statement */ forlan_type_stop /* stop statement */ }; /* A path component */ struct forlan_node_comp { enum forlan_type type; union forlan_node *root; int wildcards; int argc; char **argv; struct grecs_value **labelv; }; /* Path test: .path.comp[value] */ struct forlan_node_test { enum forlan_type type; char *comp; char *value; }; /* Function call */ struct forlan_node_func { enum forlan_type type; struct forlan_function *fp; struct grecs_list *args; /* Arguments are struct forlan_node * */ }; /* Conditional */ struct forlan_node_cond { enum forlan_type type; union forlan_node *expr; /* Controlling expression */ union forlan_node *iftrue; /* Run this if expr yields true */ union forlan_node *iffalse; /* Run this if expr yields false */ }; /* Statement or statement list */ struct forlan_node_stmt { enum forlan_type type; union forlan_node *stmt; union forlan_node *next, *prev; }; /* Literal string */ struct forlan_node_lit { enum forlan_type type; char *string; }; /* Variable assignment */ struct forlan_node_asgn { enum forlan_type type; size_t idx; union forlan_node *node; }; /* Variable reference */ struct forlan_node_var { enum forlan_type type; size_t idx; }; /* Loop */ struct forlan_node_loop { enum forlan_type type; size_t idx; /* index of the controlling variable */ union forlan_node *node; /* controlling expression */ union forlan_node *stmt; /* statement */ }; /* Boolean opcodes */ enum forlan_opcode { forlan_opcode_node, /* Evaluate node, set 'last' */ forlan_opcode_and, /* Boolean AND */ forlan_opcode_or, /* Boolean OR */ forlan_opcode_not, /* Boolean NOT */ forlan_opcode_eq, /* Equality */ forlan_opcode_ne /* Inequality */ }; /* Boolean expression */ struct forlan_node_expr { enum forlan_type type; enum forlan_opcode opcode; union forlan_node *arg[2]; }; /* Now get all this together */ union forlan_node { enum forlan_type type; struct forlan_node_comp comp; /* A path component */ struct forlan_node_test test; /* Value test (f[X]) */ struct forlan_node_func func; /* Function call */ struct forlan_node_cond cond; /* Conditional */ struct forlan_node_stmt stmt; /* Statement */ struct forlan_node_lit lit; /* Literal */ struct forlan_node_expr expr; /* Boolean expression */ /* forlan_type_last needs no additional data */ struct forlan_node_asgn asgn; struct forlan_node_var var; struct forlan_node_loop loop; }; union forlan_node *forlan_node_create(enum forlan_type type); void forlan_node_free(union forlan_node *); struct grecs_list *forlan_stmt_list(void); struct grecs_list *forlan_complist(void); union forlan_node *forlan_stmt_from_list(struct grecs_list *list); void forlan_dump_node(FILE *fp, union forlan_node *p, int *num, int lev); void forlan_dump_tree(FILE *fp, forlan_eval_env_t env); enum forlan_value_type { forlan_value_void, forlan_value_node, forlan_value_literal, forlan_value_boolean }; #define FORLAN_NTYPES 4 struct forlan_value { enum forlan_value_type type; union { char *string; struct grecs_node *node; int num; } v; }; struct forlan_variable { char *name; /* Variable name */ int idx; /* Offset in the variable segment */ }; struct forlan_function { char *name; enum forlan_value_type rettype; char *argtypes; int minargs; int maxargs; void (*func)(forlan_eval_env_t, struct grecs_list *list); }; struct forlan_function *forlan_find_function(const char *name); void forlan_eval(struct forlan_eval_env *env, union forlan_node *p); int forlan_run(forlan_eval_env_t env, struct grecs_node *tree); forlan_eval_env_t forlan_create_environment(union forlan_node *parse_tree, size_t varcount); void forlan_free_environment(forlan_eval_env_t env);