diff --git a/ase/awk/awk.c b/ase/awk/awk.c index b194f44e..6e7f6ec2 100644 --- a/ase/awk/awk.c +++ b/ase/awk/awk.c @@ -1,5 +1,5 @@ /* - * $Id: awk.c,v 1.9 2006-01-19 16:28:21 bacon Exp $ + * $Id: awk.c,v 1.10 2006-01-22 15:11:17 bacon Exp $ */ #include @@ -24,7 +24,6 @@ xp_awk_t* xp_awk_open (xp_awk_t* awk) } awk->opt = 0; - awk->tree = XP_NULL; awk->errnum = XP_AWK_ENOERR; awk->src_func = XP_NULL; @@ -35,23 +34,25 @@ xp_awk_t* xp_awk_open (xp_awk_t* awk) awk->in_arg = XP_NULL; awk->out_arg = XP_NULL; + awk->tree.begin = XP_NULL; + awk->tree.end = XP_NULL; + //awk->tree.funcs = XP_NULL; + awk->lex.curc = XP_CHAR_EOF; awk->lex.ungotc_count = 0; return awk; } -static void __collapse_tree (xp_awk_t* awk) -{ - /* TODO: collapse the tree */ - /* TODO */ - awk->tree = XP_NULL; -} - int xp_awk_close (xp_awk_t* awk) { - if (awk->tree != XP_NULL) __collapse_tree (awk); + if (awk->tree.begin != XP_NULL) xp_awk_clrpt (awk->tree.begin); + if (awk->tree.end != XP_NULL) xp_awk_clrpt (awk->tree.end); +/* +// TODO: destroy function list + if (awk->tree.funcs != XP_NULL) +*/ if (xp_awk_detsrc(awk) == -1) return -1; xp_str_close (&awk->token.name); diff --git a/ase/awk/awk.h b/ase/awk/awk.h index 45bef3a4..c5b0714c 100644 --- a/ase/awk/awk.h +++ b/ase/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h,v 1.16 2006-01-20 07:29:53 bacon Exp $ + * $Id: awk.h,v 1.17 2006-01-22 15:11:17 bacon Exp $ */ #ifndef _XP_AWK_AWK_H_ @@ -37,7 +37,10 @@ enum XP_AWK_EWHILE, /* keyword 'while' is expected */ XP_AWK_EASSIGN, /* assignment statement expected */ - XP_AWK_EIDENT /* identifier expected */ + XP_AWK_EIDENT, /* identifier expected */ + XP_AWK_EDUPBEGIN, /* duplicate BEGIN */ + XP_AWK_EDUPEND, /* duplicate END */ + XP_AWK_EDUPFUNC /* duplicate function name */ }; /* @@ -70,9 +73,6 @@ struct xp_awk_t /* options */ int opt; - /* parse tree */ - xp_awk_node_t* tree; - /* io functions */ xp_awk_io_t src_func; xp_awk_io_t in_func; @@ -82,15 +82,25 @@ struct xp_awk_t void* in_arg; void* out_arg; + /* parse tree */ + struct + { + //xp_awk_hash_t* funcs; + xp_awk_node_t* begin; + xp_awk_node_t* end; + } tree; + /* source buffer management */ - struct { + struct + { xp_cint_t curc; xp_cint_t ungotc[5]; xp_size_t ungotc_count; } lex; /* token */ - struct { + struct + { int type; xp_str_t name; } token; diff --git a/ase/awk/parse.c b/ase/awk/parse.c index 977f5e8a..9ba46eab 100644 --- a/ase/awk/parse.c +++ b/ase/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c,v 1.28 2006-01-20 15:58:42 bacon Exp $ + * $Id: parse.c,v 1.29 2006-01-22 15:11:17 bacon Exp $ */ #include @@ -71,9 +71,11 @@ enum { BINOP_MOD }; -static xp_awk_node_t* __parse_program (xp_awk_t* awk); -static xp_awk_node_t* __parse_funcdcl (xp_awk_t* awk); -static xp_awk_node_t* __parse_patnact (xp_awk_t* awk); +static xp_awk_node_t* __parse_progunit (xp_awk_t* awk); +static xp_awk_node_t* __parse_function (xp_awk_t* awk); +static xp_awk_node_t* __parse_begin (xp_awk_t* awk); +static xp_awk_node_t* __parse_end (xp_awk_t* awk); +static xp_awk_node_t* __parse_action (xp_awk_t* awk); static xp_awk_node_t* __parse_block (xp_awk_t* awk); static xp_awk_node_t* __parse_statement (xp_awk_t* awk); static xp_awk_node_t* __parse_statement_nb (xp_awk_t* awk); @@ -163,23 +165,25 @@ static struct __kwent __kwtab[] = int xp_awk_parse (xp_awk_t* awk) { - xp_awk_node_t* node; GET_CHAR (awk); GET_TOKEN (awk); - node = __parse_program(awk); - if (node == XP_NULL) { + while (1) { + if (MATCH(awk,TOKEN_EOF)) break; + + if (__parse_progunit(awk) == XP_NULL) { + // TODO: cleanup the parse tree created so far.... xp_printf (XP_TEXT("error - %d\n"), awk->errnum); - return -1; + return -1; + } } -xp_printf (XP_TEXT("end - %d\n"), awk->errnum); - awk->tree = node; +xp_printf (XP_TEXT("sucessful end - %d\n"), awk->errnum); return 0; } -static xp_awk_node_t* __parse_program (xp_awk_t* awk) +static xp_awk_node_t* __parse_progunit (xp_awk_t* awk) { /* pattern { action } @@ -187,33 +191,72 @@ static xp_awk_node_t* __parse_program (xp_awk_t* awk) */ xp_awk_node_t* node; - while (1) { - if (MATCH(awk,TOKEN_FUNCTION)) { - node = __parse_funcdcl(awk); + if (MATCH(awk,TOKEN_FUNCTION)) { + node = __parse_function(awk); + if (node == XP_NULL) { + // TODO: cleanup + return XP_NULL; } - else { - node = __parse_patnact(awk); + } + else if (MATCH(awk,TOKEN_BEGIN)) { + node = __parse_begin (awk); + if (node == XP_NULL) { + // TODO: cleanup + return XP_NULL; + } + } + else if (MATCH(awk, TOKEN_END)) { + node = __parse_end (awk); + if (node == XP_NULL) { + // TODO: cleanup + return XP_NULL; + } + } + /* TODO: process patterns and expressions */ + /* + expressions + /regular expression/ + pattern && pattern + pattern || pattern + !pattern + (pattern) + pattern, pattern + */ + else { + /* pattern-less actions */ + node = __parse_action (awk); + if (node == XP_NULL) { + // TODO: cleanup + return XP_NULL; } - if (node == XP_NULL) return XP_NULL; -xp_printf (XP_TEXT(">>>>> breaking ... for testing ...\n")); -break; + // TODO: weave the action block into awk->tree.actions... } return node; } -static xp_awk_node_t* __parse_funcdcl (xp_awk_t* awk) +static xp_bool_t __function_defined (xp_awk_t* awk, const xp_char_t* name) +{ +// TODO: complete this... + return xp_false; +} + +static xp_awk_node_t* __parse_function (xp_awk_t* awk) { xp_char_t* name; + xp_awk_func_t* func; xp_awk_node_t* body; -/* TODO: *******************************/ - - /* skip the keyword 'function' */ if (__get_token(awk) == -1) return XP_NULL; + + /* function name */ if (!MATCH(awk,TOKEN_IDENT)) PANIC (awk, XP_AWK_EIDENT); + if (__function_defined(awk,XP_STR_BUF(&awk->token.name))) { + PANIC (awk, XP_AWK_EDUPFUNC); + } + name = xp_strdup (XP_STR_BUF(&awk->token.name)); if (name == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); @@ -233,6 +276,7 @@ static xp_awk_node_t* __parse_funcdcl (xp_awk_t* awk) return XP_NULL; } + /* parameter name list */ if (MATCH(awk,TOKEN_RPAREN)) { /* no function parameter */ if (__get_token(awk) == -1) { @@ -266,64 +310,81 @@ static xp_awk_node_t* __parse_funcdcl (xp_awk_t* awk) } if (__get_token(awk) == -1) { +// TODO: cleanup parameter name list xp_free (name); return XP_NULL; } } if (!MATCH(awk,TOKEN_LBRACE)) { -// TODO: cleanup +// TODO: cleanup parameter name list + xp_free (name); PANIC (awk, XP_AWK_ELBRACE); } if (__get_token(awk) == -1) { -// TODO: cleanup +// TODO: cleanup parameter name list + xp_free (name); return XP_NULL; } + /* function body */ body = __parse_block (awk); if (body == XP_NULL) { -// TODO: cleanup; +// TODO: cleanup parameter name list + xp_free (name); return XP_NULL; } -// TODO: return something else... + func = (xp_awk_func_t*) xp_malloc (xp_sizeof(xp_awk_func_t)); + if (func == XP_NULL) { + xp_free (name); + xp_awk_clrpt (body); + return XP_NULL; + } + + func->name = name; + func->nargs = 0; + func->body = body; + +/* TODO: weave the function body into awk->tree.funcs */ return body; } -static xp_awk_node_t* __parse_patnact (xp_awk_t* awk) +static xp_awk_node_t* __parse_begin (xp_awk_t* awk) { - /* - BEGIN - END - expressions - /regular expression/ - pattern && pattern - pattern || pattern - !pattern - (pattern) - pattern, pattern - */ - xp_awk_node_t* node; - if (MATCH(awk,TOKEN_BEGIN)) { - if (__get_token(awk) == -1) return XP_NULL; - } - else if (MATCH(awk,TOKEN_END)) { - if (__get_token(awk) == -1) return XP_NULL; - } - /* patterns ... - * etc */ - - if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, XP_AWK_ELBRACE); + if (awk->tree.begin != XP_NULL) PANIC (awk, XP_AWK_EDUPBEGIN); if (__get_token(awk) == -1) return XP_NULL; - node = __parse_block(awk); + node = __parse_action (awk); if (node == XP_NULL) return XP_NULL; + awk->tree.begin = node; return node; } +static xp_awk_node_t* __parse_end (xp_awk_t* awk) +{ + xp_awk_node_t* node; + + if (awk->tree.end != XP_NULL) PANIC (awk, XP_AWK_EDUPEND); + if (__get_token(awk) == -1) return XP_NULL; + + node = __parse_action (awk); + if (node == XP_NULL) return XP_NULL; + + awk->tree.end = node; + return node; +} + +static xp_awk_node_t* __parse_action (xp_awk_t* awk) +{ + if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, XP_AWK_ELBRACE); + if (__get_token(awk) == -1) return XP_NULL; + return __parse_block(awk); +} + /* TODO: what is the best name for the parsing routine for the outermost block? */ static xp_awk_node_t* __parse_block (xp_awk_t* awk) { diff --git a/ase/awk/tree.h b/ase/awk/tree.h index c17d318a..bc153855 100644 --- a/ase/awk/tree.h +++ b/ase/awk/tree.h @@ -1,5 +1,5 @@ /* - * $Id: tree.h,v 1.14 2006-01-20 07:29:54 bacon Exp $ + * $Id: tree.h,v 1.15 2006-01-22 15:11:17 bacon Exp $ */ #ifndef _XP_AWK_TREE_H_ @@ -40,6 +40,14 @@ typedef struct xp_awk_node_if_t xp_awk_node_if_t; typedef struct xp_awk_node_while_t xp_awk_node_while_t; typedef struct xp_awk_node_for_t xp_awk_node_for_t; + +struct xp_awk_func_t +{ + xp_char_t* name; + xp_size_t nargs; + xp_awk_node_t* body; +}; + #define XP_AWK_NODE_HDR \ int type; \ xp_awk_node_t* next diff --git a/ase/test/awk/awk.c b/ase/test/awk/awk.c index 793425be..287585f6 100644 --- a/ase/test/awk/awk.c +++ b/ase/test/awk/awk.c @@ -77,7 +77,14 @@ int xp_main (int argc, xp_char_t* argv[]) } xp_printf (XP_TEXT("-----------------------------------------------\n")); - xp_awk_prnpt (awk.tree); + if (awk.tree.begin != XP_NULL) { + xp_printf (XP_TEXT("BEGIN ")); + xp_awk_prnpt (awk.tree.begin); + } + if (awk.tree.end != XP_NULL) { + xp_printf (XP_TEXT("END ")); + xp_awk_prnpt (awk.tree.end); + } xp_awk_close (&awk); return 0;