*** empty log message ***

This commit is contained in:
hyung-hwan 2006-01-31 16:57:45 +00:00
parent af6626d66a
commit 63fbbfedec
5 changed files with 205 additions and 102 deletions

View File

@ -1,5 +1,5 @@
/*
* $Id: awk.c,v 1.14 2006-01-30 14:45:12 bacon Exp $
* $Id: awk.c,v 1.15 2006-01-31 16:57:45 bacon Exp $
*/
#include <xp/awk/awk.h>
@ -31,14 +31,15 @@ xp_awk_t* xp_awk_open (xp_awk_t* awk)
return XP_NULL;
}
if (xp_awk_tab_open(&awk->parse.funcs) == XP_NULL) {
if (xp_awk_tab_open(&awk->parse.params) == XP_NULL) {
xp_str_close (&awk->token.name);
xp_awk_hash_close (&awk->tree.funcs);
if (awk->__dynamic) xp_free (awk);
return XP_NULL;
}
awk->opt = 0;
awk->opt.parse = 0;
awk->opt.run = 0;
awk->errnum = XP_AWK_ENOERR;
awk->src_func = XP_NULL;
@ -65,13 +66,58 @@ int xp_awk_close (xp_awk_t* awk)
if (xp_awk_detsrc(awk) == -1) return -1;
xp_awk_hash_close (&awk->tree.funcs);
xp_awk_tab_close (&awk->parse.funcs);
xp_awk_tab_close (&awk->parse.params);
xp_str_close (&awk->token.name);
if (awk->__dynamic) xp_free (awk);
return 0;
}
int xp_awk_geterrnum (xp_awk_t* awk)
{
return awk->errnum;
}
const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk)
{
static const xp_char_t* __errstr[] =
{
XP_TEXT("no error"),
XP_TEXT("out of memory"),
XP_TEXT("cannot open source"),
XP_TEXT("cannot close source"),
XP_TEXT("cannot read source"),
XP_TEXT("invalid character"),
XP_TEXT("cannot unget character"),
XP_TEXT("unexpected end of source"),
XP_TEXT("left brace expected"),
XP_TEXT("left parenthesis expected"),
XP_TEXT("right parenthesis expected"),
XP_TEXT("right bracket expected"),
XP_TEXT("comma expected"),
XP_TEXT("semicolon expected"),
XP_TEXT("expression expected"),
XP_TEXT("keyword 'while' expected"),
XP_TEXT("assignment statement expected"),
XP_TEXT("identifier expected"),
XP_TEXT("duplicate BEGIN"),
XP_TEXT("duplicate END"),
XP_TEXT("duplicate function name"),
XP_TEXT("duplicate parameter name"),
XP_TEXT("duplicate name"),
};
if (awk->errnum >= 0 && awk->errnum < xp_countof(__errstr)) {
return __errstr[awk->errnum];
}
return XP_TEXT("unknown error");
}
// TODO: write a function to clear awk->parse data structure.
// this would be need either as a separate function or as a part of xp_awk_clear...
// do i have to pass an option to xp_awk_clear to do this???
@ -148,3 +194,4 @@ static void __free_func (void* func)
xp_awk_clrpt (f->body);
xp_free (f);
}

View File

@ -1,5 +1,5 @@
/*
* $Id: awk.h,v 1.22 2006-01-30 14:34:47 bacon Exp $
* $Id: awk.h,v 1.23 2006-01-31 16:57:45 bacon Exp $
*/
#ifndef _XP_AWK_AWK_H_
@ -21,6 +21,7 @@ enum
{
XP_AWK_ENOERR,
XP_AWK_ENOMEM, /* out of memory */
XP_AWK_ESRCOP,
XP_AWK_ESRCCL,
XP_AWK_ESRCDT, /* error in reading source */
@ -43,6 +44,7 @@ enum
XP_AWK_EDUPBEGIN, /* duplicate BEGIN */
XP_AWK_EDUPEND, /* duplicate END */
XP_AWK_EDUPFUNC, /* duplicate function name */
XP_AWK_EDUPPARAM, /* duplicate parameter name */
XP_AWK_EDUPNAME /* duplicate name - function, variable, etc */
};
@ -65,16 +67,21 @@ enum
XP_AWK_IO_DATA
};
/* options */
/* parse options */
enum
{
XP_AWK_ASSIGN_ONLY /* a non-assignment expression cannot be used as a statement */
XP_AWK_EXPLICIT = (1 << 0), /* variable requires explicit declaration */
XP_AWK_UNIQUE = (1 << 1) /* a function name should not coincide to be a variable name */
};
struct xp_awk_t
{
/* options */
int opt;
struct
{
int parse;
int run;
} opt;
/* io functions */
xp_awk_io_t src_func;
@ -97,10 +104,9 @@ struct xp_awk_t
/* temporary information that the parser needs */
struct
{
xp_awk_tab_t funcs;
// TODO: locals, globals???
xp_char_t* vars; /* global and local variable names... */
xp_char_t* args; /* function arguments */
//xp_awk_tab_t vars; /* global and local variable names... */
xp_awk_tab_t params;
} parse;
/* source buffer management */
@ -137,6 +143,10 @@ xp_awk_t* xp_awk_open (xp_awk_t* awk);
*/
int xp_awk_close (xp_awk_t* awk);
int xp_awk_geterrnum (xp_awk_t* awk);
const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk);
/*
* FUNCTION: xp_awk_clear
*/

View File

@ -1,5 +1,5 @@
/*
* $Id: parse.c,v 1.40 2006-01-30 14:45:12 bacon Exp $
* $Id: parse.c,v 1.41 2006-01-31 16:57:45 bacon Exp $
*/
#include <xp/awk/awk.h>
@ -118,10 +118,6 @@ static int __classfy_ident (const xp_char_t* ident);
static xp_long_t __str_to_long (const xp_char_t* name);
static INLINE xp_size_t __add_func_name (xp_awk_t* awk, const xp_char_t* name);
static INLINE xp_size_t __find_func_name (xp_awk_t* awk, const xp_char_t* name);
static INLINE int __remove_func_name (xp_awk_t* awk, xp_size_t index);
static INLINE xp_size_t __find_func_arg (xp_awk_t* awk, const xp_char_t* name);
static INLINE xp_size_t __find_variable (xp_awk_t* awk, const xp_char_t* name);
@ -233,9 +229,8 @@ int xp_awk_parse (xp_awk_t* awk)
if (MATCH(awk,TOKEN_EOF)) break;
if (__parse_progunit(awk) == XP_NULL) {
// TODO: cleanup the parse tree created so far....
// function tables also etc...
xp_printf (XP_TEXT("error - %d\n"), awk->errnum);
// TODO: cleanup the parse tree created so far....
// function tables also etc...
return -1;
}
}
@ -294,62 +289,60 @@ static xp_awk_node_t* __parse_function (xp_awk_t* awk)
xp_char_t* name_dup;
xp_awk_node_t* body;
xp_awk_func_t* func;
xp_size_t fnpos;
xp_size_t nargs = 0;
xp_size_t nargs;
/* eat up the keyword 'function' and get the next token */
if (__get_token(awk) == -1) return XP_NULL;
/* function name */
if (!MATCH(awk,TOKEN_IDENT)) PANIC (awk, XP_AWK_EIDENT);
/* match a function name */
if (!MATCH(awk,TOKEN_IDENT)) {
/* cannot find a valid identifier for a function name */
PANIC (awk, XP_AWK_EIDENT);
}
name = XP_STR_BUF(&awk->token.name);
if (__find_func_name(awk,name) != (xp_size_t)-1) {
// TODO: do i have to tell DUPFUNC from DUPNAME???
//PANIC (awk, XP_AWK_EDUPFUNC);
PANIC (awk, XP_AWK_EDUPNAME);
if (xp_awk_hash_get(&awk->tree.funcs, name) != XP_NULL) {
/* the function is defined previously */
PANIC (awk, XP_AWK_EDUPFUNC);
}
// TODO: make this feature optional..
// find in the global variable list...
if (__find_variable(awk,name) != (xp_size_t)-1) {
PANIC (awk, XP_AWK_EDUPNAME);
if (awk->opt.parse & XP_AWK_UNIQUE) {
/* check if it coincides to be a variable name */
if (__find_variable(awk,name) != (xp_size_t)-1) {
PANIC (awk, XP_AWK_EDUPNAME);
}
}
fnpos = __add_func_name (awk, name);
if (fnpos == -1) PANIC (awk, XP_AWK_ENOMEM);
// TODO: move this strdup down the function....
// maybe just before func_t is allocated...
/* clone the function name before it is overwritten */
name_dup = xp_strdup (name);
if (name_dup == XP_NULL) {
__remove_func_name (awk, fnpos);
PANIC (awk, XP_AWK_ENOMEM);
}
if (name_dup == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
/* skip the function name */
/* get the next token */
if (__get_token(awk) == -1) {
__remove_func_name (awk, fnpos);
xp_free (name_dup);
return XP_NULL;
}
/* match a left parenthesis */
if (!MATCH(awk,TOKEN_LPAREN)) {
__remove_func_name (awk, fnpos);
/* a function name is not followed by a left parenthesis */
xp_free (name_dup);
PANIC (awk, XP_AWK_ELPAREN);
}
/* get the next token */
if (__get_token(awk) == -1) {
__remove_func_name (awk, fnpos);
xp_free (name_dup);
return XP_NULL;
}
/* parameter name list */
/* make sure that parameter table is empty */
xp_assert (xp_awk_tab_getsize(&awk->parse.params) == 0);
/* read parameter list */
if (MATCH(awk,TOKEN_RPAREN)) {
/* no function parameter */
/* no function parameter found. get the next token */
if (__get_token(awk) == -1) {
__remove_func_name (awk, fnpos);
xp_free (name_dup);
return XP_NULL;
}
@ -357,70 +350,83 @@ static xp_awk_node_t* __parse_function (xp_awk_t* awk)
else {
while (1) {
if (!MATCH(awk,TOKEN_IDENT)) {
__remove_func_name (awk, fnpos);
xp_free (name_dup);
xp_awk_tab_clear (&awk->parse.params);
PANIC (awk, XP_AWK_EIDENT);
}
nargs++;
// TODO: push args to param list...
// TODO: check duplicates againt variables if shading is not supported
// global x; function f (x) { print x; } -> x in print x is a parameter
if (xp_awk_tab_find (&awk->parse.params,
XP_STR_BUF(&awk->token.name), 0) != (xp_size_t)-1) {
xp_free (name_dup);
xp_awk_tab_clear (&awk->parse.params);
PANIC (awk, XP_AWK_EDUPPARAM);
}
if (xp_awk_tab_adddatum (&awk->parse.params,
XP_STR_BUF(&awk->token.name)) == (xp_size_t)-1) {
xp_free (name_dup);
xp_awk_tab_clear (&awk->parse.params);
PANIC (awk, XP_AWK_ENOMEM);
}
if (__get_token(awk) == -1) {
__remove_func_name (awk, fnpos);
xp_free (name_dup);
xp_awk_tab_clear (&awk->parse.params);
return XP_NULL;
}
if (MATCH(awk,TOKEN_RPAREN)) break;
if (!MATCH(awk,TOKEN_COMMA)) {
__remove_func_name (awk, fnpos);
xp_free (name_dup);
xp_awk_tab_clear (&awk->parse.params);
PANIC (awk, XP_AWK_ECOMMA);
}
if (__get_token(awk) == -1) {
__remove_func_name (awk, fnpos);
xp_free (name_dup);
xp_awk_tab_clear (&awk->parse.params);
return XP_NULL;
}
}
if (__get_token(awk) == -1) {
__remove_func_name (awk, fnpos);
// TODO: cleanup parameter name list
xp_free (name_dup);
xp_awk_tab_clear (&awk->parse.params);
return XP_NULL;
}
}
/* check if the function body starts with a left brace */
if (!MATCH(awk,TOKEN_LBRACE)) {
__remove_func_name (awk, fnpos);
// TODO: cleanup parameter name list
xp_free (name_dup);
xp_awk_tab_clear (&awk->parse.params);
PANIC (awk, XP_AWK_ELBRACE);
}
if (__get_token(awk) == -1) {
__remove_func_name (awk, fnpos);
// TODO: cleanup parameter name list
xp_free (name_dup);
xp_awk_tab_clear (&awk->parse.params);
return XP_NULL;
}
/* actual function body */
body = __parse_block (awk);
if (body == XP_NULL) {
__remove_func_name (awk, fnpos);
// TODO: cleanup parameter name list
xp_free (name_dup);
xp_awk_tab_clear (&awk->parse.params);
return XP_NULL;
}
// TODO: consider if the parameters should be saved for some reasons..
nargs = xp_awk_tab_getsize(&awk->parse.params);
/* parameter names are not required anymore. clear them */
xp_awk_tab_clear (&awk->parse.params);
func = (xp_awk_func_t*) xp_malloc (xp_sizeof(xp_awk_func_t));
if (func == XP_NULL) {
__remove_func_name (awk, fnpos);
// TODO: cleanup parameter name list
xp_free (name_dup);
xp_awk_clrpt (body);
return XP_NULL;
@ -432,7 +438,6 @@ static xp_awk_node_t* __parse_function (xp_awk_t* awk)
xp_assert (xp_awk_hash_get(&awk->tree.funcs, name_dup) == XP_NULL);
if (xp_awk_hash_put(&awk->tree.funcs, name_dup, func) == XP_NULL) {
__remove_func_name (awk, fnpos);
xp_free (name_dup);
xp_awk_clrpt (body);
xp_free (func);
@ -696,10 +701,11 @@ static xp_awk_node_t* __parse_expression (xp_awk_t* awk)
if (!MATCH(awk,TOKEN_ASSIGN)) return x;
xp_assert (x->next == XP_NULL);
if (x->type != XP_AWK_NODE_VAR &&
if (x->type != XP_AWK_NODE_ARG &&
x->type != XP_AWK_NODE_ARGIDX &&
x->type != XP_AWK_NODE_VAR &&
x->type != XP_AWK_NODE_VARIDX &&
x->type != XP_AWK_NODE_POS) {
// TODO: XP_AWK_NODE_ARG, XP_AWK_NODE_ARGIDX
xp_awk_clrpt (x);
PANIC (awk, XP_AWK_EASSIGN);
}
@ -880,27 +886,27 @@ static xp_awk_node_t* __parse_unary (xp_awk_t* awk)
static xp_awk_node_t* __parse_primary (xp_awk_t* awk)
{
if (MATCH(awk,TOKEN_IDENT)) {
xp_char_t* name;
xp_char_t* name_dup;
name = (xp_char_t*)xp_strdup(XP_STR_BUF(&awk->token.name));
if (name == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
name_dup = (xp_char_t*)xp_strdup(XP_STR_BUF(&awk->token.name));
if (name_dup == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
if (__get_token(awk) == -1) {
xp_free (name);
xp_free (name_dup);
return XP_NULL;
}
if (MATCH(awk,TOKEN_LBRACK)) {
xp_awk_node_t* node;
node = __parse_hashidx (awk, name);
if (node == XP_NULL) xp_free (name);
node = __parse_hashidx (awk, name_dup);
if (node == XP_NULL) xp_free (name_dup);
return (xp_awk_node_t*)node;
}
else if (MATCH(awk,TOKEN_LPAREN)) {
/* function call */
xp_awk_node_t* node;
node = __parse_funcall (awk, name);
if (node == XP_NULL) xp_free (name);
node = __parse_funcall (awk, name_dup);
if (node == XP_NULL) xp_free (name_dup);
return (xp_awk_node_t*)node;
}
else {
@ -910,24 +916,37 @@ static xp_awk_node_t* __parse_primary (xp_awk_t* awk)
node = (xp_awk_node_var_t*)xp_malloc(xp_sizeof(xp_awk_node_var_t));
if (node == XP_NULL) {
xp_free (name);
xp_free (name_dup);
PANIC (awk, XP_AWK_ENOMEM);
}
/* search the parameter name list */
idxa = xp_awk_tab_find (&awk->parse.params, name_dup, 0);
if (idxa != (xp_size_t)-1) {
node->type = XP_AWK_NODE_ARG;
node->next = XP_NULL;
//node->id.name = XP_NULL;
node->id.name = name_dup;
node->id.idxa = idxa;
return (xp_awk_node_t*)node;
}
/* search the variable name list */
// TODO:
idxa = __find_variable (awk, name);
idxa = __find_variable (awk, name_dup);
if (idxa == (xp_size_t)-1) {
idxa = __find_func_arg (awk, name);
idxa = __find_func_arg (awk, name_dup);
if (idxa == (xp_size_t)-1) {
node->type = XP_AWK_NODE_VAR;
node->next = XP_NULL;
node->id.name = name;
node->id.name = name_dup;
}
else {
node->type = XP_AWK_NODE_ARG;
node->next = XP_NULL;
// TODO: do i need to store the name here???
node->id.name = name;
node->id.name = name_dup;
node->id.idxa = idxa;
}
}
@ -936,7 +955,7 @@ static xp_awk_node_t* __parse_primary (xp_awk_t* awk)
node->type = XP_AWK_NODE_VAR;
node->next = XP_NULL;
// TODO: do i need to store the name here???
node->id.name = name;
node->id.name = name_dup;
node->id.idxa = idxa;
}
@ -1040,6 +1059,7 @@ static xp_awk_node_t* __parse_hashidx (xp_awk_t* awk, xp_char_t* name)
{
xp_awk_node_t* idx;
xp_awk_node_idx_t* node;
xp_size_t idxa;
if (__get_token(awk) == -1) return XP_NULL;
@ -1062,6 +1082,20 @@ static xp_awk_node_t* __parse_hashidx (xp_awk_t* awk, xp_char_t* name)
PANIC (awk, XP_AWK_ENOMEM);
}
/* search the parameter name list */
idxa = xp_awk_tab_find (&awk->parse.params, name, 0);
if (idxa != (xp_size_t)-1) {
node->type = XP_AWK_NODE_ARGIDX;
node->next = XP_NULL;
//node->id.name = XP_NULL;
node->id.name = name;
node->id.idxa = idxa;
node->idx = idx;
return (xp_awk_node_t*)node;
}
// TODO: search variable list
node->type = XP_AWK_NODE_VARIDX;
node->next = XP_NULL;
node->id.name = name;
@ -1770,23 +1804,6 @@ static xp_long_t __str_to_long (const xp_char_t* name)
return n;
}
static INLINE xp_size_t __add_func_name (xp_awk_t* awk, const xp_char_t* name)
{
xp_assert (__find_func_name(awk,name) == (xp_size_t)-1);
return xp_awk_tab_adddatum(&awk->parse.funcs, name);
}
static INLINE int __remove_func_name (xp_awk_t* awk, xp_size_t index)
{
return xp_awk_tab_remrange (&awk->parse.funcs, index, 1);
}
static INLINE xp_size_t __find_func_name (xp_awk_t* awk, const xp_char_t* name)
{
return xp_awk_tab_find(&awk->parse.funcs, name, 0);
}
static INLINE xp_size_t __find_func_arg (xp_awk_t* awk, const xp_char_t* name)
{
/*

View File

@ -1,5 +1,5 @@
/*
* $Id: tree.c,v 1.13 2006-01-28 06:38:01 bacon Exp $
* $Id: tree.c,v 1.14 2006-01-31 16:57:45 bacon Exp $
*/
#include <xp/awk/awk.h>
@ -65,6 +65,18 @@ static int __print_expr_node (xp_awk_node_t* node)
xp_printf (XP_TEXT("%s"), ((xp_awk_node_term_t*)node)->value);
break;
case XP_AWK_NODE_ARG:
xp_printf (XP_TEXT("__arg%u"),
(unsigned int)((xp_awk_node_var_t*)node)->id.idxa);
break;
case XP_AWK_NODE_ARGIDX:
xp_printf (XP_TEXT("__arg%u["),
(unsigned int)((xp_awk_node_idx_t*)node)->id.idxa);
__print_expr_node (((xp_awk_node_idx_t*)node)->idx);
xp_printf (XP_TEXT("]"));
break;
case XP_AWK_NODE_VAR:
xp_printf (XP_TEXT("%s"), ((xp_awk_node_var_t*)node)->id.name);
break;
@ -360,14 +372,29 @@ void xp_awk_clrpt (xp_awk_node_t* tree)
xp_free (p);
break;
case XP_AWK_NODE_ARG:
if (((xp_awk_node_var_t*)p)->id.name != XP_NULL)
xp_free (((xp_awk_node_var_t*)p)->id.name);
xp_free (p);
break;
case XP_AWK_NODE_ARGIDX:
xp_awk_clrpt (((xp_awk_node_idx_t*)p)->idx);
if (((xp_awk_node_var_t*)p)->id.name != XP_NULL)
xp_free (((xp_awk_node_var_t*)p)->id.name);
xp_free (p);
break;
case XP_AWK_NODE_VAR:
xp_free (((xp_awk_node_var_t*)p)->id.name);
if (((xp_awk_node_var_t*)p)->id.name != XP_NULL)
xp_free (((xp_awk_node_var_t*)p)->id.name);
xp_free (p);
break;
case XP_AWK_NODE_VARIDX:
xp_awk_clrpt (((xp_awk_node_idx_t*)p)->idx);
xp_free (((xp_awk_node_idx_t*)p)->id.name);
if (((xp_awk_node_var_t*)p)->id.name != XP_NULL)
xp_free (((xp_awk_node_var_t*)p)->id.name);
xp_free (p);
break;

View File

@ -79,8 +79,10 @@ int xp_main (int argc, xp_char_t* argv[])
}
if (xp_awk_parse(&awk) == -1) {
xp_printf (
XP_TEXT("error: cannot parse program - [%d] %s\n"),
xp_awk_geterrnum(&awk), xp_awk_geterrstr(&awk));
xp_awk_close (&awk);
xp_printf (XP_TEXT("error: cannot parse program\n"));
return -1;
}