aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2012-09-22 17:34:51 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2012-09-22 17:34:51 +0300
commit546c03672b5b8044dbca0814eac8cbdddb898183 (patch)
tree8277c3ad7efe0b60ce64aa563b70e7999238a7c6 /lib
parent8d16cf26fc6e3a6c91eec21892d9da58286479f0 (diff)
downloadeclat-546c03672b5b8044dbca0814eac8cbdddb898183.tar.gz
eclat-546c03672b5b8044dbca0814eac8cbdddb898183.tar.bz2
Introduce forlan functions.
* lib/forlan.c (forlan_find_function): New function. (func_dump, func_print) (func_error,func_parent): Function placeholders. * lib/forlan.h (forlan_node_func) <fp>: Change datatype. (forlan_eval_env_t): New typedef. (forlan_value_type): New enum. (forlan_value,forlan_function): New struct. * lib/forlangrm.y: Check number of arguments passed to functions. * tests/forlan01.at: Update.
Diffstat (limited to 'lib')
-rw-r--r--lib/forlan.c52
-rw-r--r--lib/forlan.h29
-rw-r--r--lib/forlangrm.y50
3 files changed, 127 insertions, 4 deletions
diff --git a/lib/forlan.c b/lib/forlan.c
index 0854d08..008ee5b 100644
--- a/lib/forlan.c
+++ b/lib/forlan.c
@@ -85,7 +85,7 @@ void
dump_func(FILE *fp, union forlan_node *p, int *num, int lev)
{
struct grecs_list_entry *ep;
- fprintf(fp, "CALL: %s\n", p->func.fp);
+ fprintf(fp, "CALL: %s\n", p->func.fp->name);
if (p->func.args)
for (ep = p->func.args->head; ep; ep = ep->next)
forlan_dump_node(fp, ep->data, num, lev + 1);
@@ -256,3 +256,53 @@ forlan_dump_tree(FILE *fp, union forlan_node *node)
int n = 0;
forlan_dump_node(fp, node, &n, 0);
}
+
+struct forlan_eval_env {
+ struct grecs_node *tree;
+ struct grecs_node *last;
+};
+
+void
+func_dump(forlan_eval_env_t env, struct grecs_list *list)
+{
+ abort();
+}
+
+void
+func_print(forlan_eval_env_t env, struct grecs_list *list)
+{
+ abort();
+}
+
+void
+func_error(forlan_eval_env_t env, struct grecs_list *list)
+{
+ abort();
+}
+
+void
+func_parent(forlan_eval_env_t env, struct grecs_list *list)
+{
+ abort();
+}
+
+static struct forlan_function functab[] = {
+ { "dump", forlan_value_void, "n", 1, 1, func_dump },
+ { "print", forlan_value_void, "", 1, -1, func_print },
+ { "error", forlan_value_void, "", 1, -1, func_error },
+ { "parent", forlan_value_node, "n", 1, 1, func_parent },
+ { NULL }
+};
+
+struct forlan_function *
+forlan_find_function(const char *name)
+{
+ struct forlan_function *fp;
+ for (fp = functab; fp->name; fp++)
+ if (strcmp(name, fp->name) == 0)
+ return fp;
+ return NULL;
+}
+
+
+
diff --git a/lib/forlan.h b/lib/forlan.h
index 4dadc70..aa4dbe4 100644
--- a/lib/forlan.h
+++ b/lib/forlan.h
@@ -58,7 +58,7 @@ struct forlan_node_test {
/* Function call */
struct forlan_node_func {
enum forlan_type type;
- void *fp; /* FIXME: replace with typedef */
+ struct forlan_function *fp;
struct grecs_list *args; /* Arguments are struct forlan_node * */
};
@@ -121,3 +121,30 @@ extern union forlan_node *forlan_parse_tree;
void forlan_dump_node(FILE *fp, union forlan_node *p, int *num, int lev);
void forlan_dump_tree(FILE *fp, union forlan_node *node);
+
+typedef struct forlan_eval_env *forlan_eval_env_t;
+
+enum forlan_value_type {
+ forlan_value_void,
+ forlan_value_node,
+ forlan_value_literal
+};
+
+struct forlan_value {
+ enum forlan_value_type type;
+ union {
+ char *string;
+ struct grecs_node *node;
+ } v;
+};
+
+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);
diff --git a/lib/forlangrm.y b/lib/forlangrm.y
index 1b7781d..d2e0489 100644
--- a/lib/forlangrm.y
+++ b/lib/forlangrm.y
@@ -137,6 +137,12 @@ node : complist
$$->comp.abs = 1;
$$->comp.node = forlan_stmt_from_list($2);
}
+ | '.'
+ {
+ $$ = forlan_node_create(forlan_type_comp);
+ $$->comp.abs = 1;
+ $$->comp.node = NULL;
+ }
| LAST
{
$$ = forlan_node_create(forlan_type_last);
@@ -175,14 +181,54 @@ string : IDENT
funcall : IDENT '(' ')'
{
+ struct forlan_function *fp =
+ forlan_find_function($1);
+ if (!fp) {
+ grecs_error(&@1, 0,
+ "call to unknown function \"%s\"",
+ $1);
+ YYERROR;
+ }
+
+ if (fp->minargs != 0) {
+ grecs_error(&@1, 0,
+ "not enough arguments in call to \"%s\"",
+ $1);
+ YYERROR;
+ }
+
$$ = forlan_node_create(forlan_type_func);
- $$->func.fp = $1; //FIXME
+ $$->func.fp = fp;
$$->func.args = NULL;
}
| IDENT '(' arglist ')'
{
+ struct forlan_function *fp =
+ forlan_find_function($1);
+ if (!fp) {
+ grecs_error(&@1, 0,
+ "call to unknown function \"%s\"",
+ $1);
+ YYERROR;
+ }
+
+ if ($3->count < fp->minargs) {
+ grecs_error(&@1, 0,
+ "not enough arguments in call to \"%s\"",
+ $1);
+ YYERROR;
+ }
+ if (fp->maxargs >= 0 && $3->count > fp->minargs) {
+ grecs_error(&@1, 0,
+ "too many arguments in call to \"%s\"",
+ $1);
+ YYERROR;
+ }
+
+ /* FIXME: Check data types */
+
$$ = forlan_node_create(forlan_type_func);
- $$->func.fp = $1; //FIXME
+ $$->func.fp = fp;
$$->func.args = $3;
}
;

Return to:

Send suggestions and report system problems to the System administrator.