*** empty log message ***
This commit is contained in:
parent
3f31c110cd
commit
a4264220ed
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: awk.c,v 1.16 2006-02-01 02:56:12 bacon Exp $
|
* $Id: awk.c,v 1.17 2006-02-04 19:31:51 bacon Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xp/awk/awk.h>
|
#include <xp/awk/awk.h>
|
||||||
@ -31,9 +31,26 @@ xp_awk_t* xp_awk_open (xp_awk_t* awk)
|
|||||||
return XP_NULL;
|
return XP_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xp_awk_tab_open(&awk->parse.globals) == XP_NULL) {
|
||||||
|
xp_str_close (&awk->token.name);
|
||||||
|
xp_awk_hash_close (&awk->tree.funcs);
|
||||||
|
if (awk->__dynamic) xp_free (awk);
|
||||||
|
return XP_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xp_awk_tab_open(&awk->parse.locals) == XP_NULL) {
|
||||||
|
xp_str_close (&awk->token.name);
|
||||||
|
xp_awk_hash_close (&awk->tree.funcs);
|
||||||
|
xp_awk_tab_close (&awk->parse.globals);
|
||||||
|
if (awk->__dynamic) xp_free (awk);
|
||||||
|
return XP_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (xp_awk_tab_open(&awk->parse.params) == XP_NULL) {
|
if (xp_awk_tab_open(&awk->parse.params) == XP_NULL) {
|
||||||
xp_str_close (&awk->token.name);
|
xp_str_close (&awk->token.name);
|
||||||
xp_awk_hash_close (&awk->tree.funcs);
|
xp_awk_hash_close (&awk->tree.funcs);
|
||||||
|
xp_awk_tab_close (&awk->parse.globals);
|
||||||
|
xp_awk_tab_close (&awk->parse.locals);
|
||||||
if (awk->__dynamic) xp_free (awk);
|
if (awk->__dynamic) xp_free (awk);
|
||||||
return XP_NULL;
|
return XP_NULL;
|
||||||
}
|
}
|
||||||
@ -50,6 +67,8 @@ xp_awk_t* xp_awk_open (xp_awk_t* awk)
|
|||||||
awk->in_arg = XP_NULL;
|
awk->in_arg = XP_NULL;
|
||||||
awk->out_arg = XP_NULL;
|
awk->out_arg = XP_NULL;
|
||||||
|
|
||||||
|
awk->parse.nlocals_max = 0;
|
||||||
|
|
||||||
awk->tree.begin = XP_NULL;
|
awk->tree.begin = XP_NULL;
|
||||||
awk->tree.end = XP_NULL;
|
awk->tree.end = XP_NULL;
|
||||||
awk->tree.unnamed = XP_NULL;
|
awk->tree.unnamed = XP_NULL;
|
||||||
@ -66,6 +85,8 @@ int xp_awk_close (xp_awk_t* awk)
|
|||||||
if (xp_awk_detsrc(awk) == -1) return -1;
|
if (xp_awk_detsrc(awk) == -1) return -1;
|
||||||
|
|
||||||
xp_awk_hash_close (&awk->tree.funcs);
|
xp_awk_hash_close (&awk->tree.funcs);
|
||||||
|
xp_awk_tab_close (&awk->parse.globals);
|
||||||
|
xp_awk_tab_close (&awk->parse.locals);
|
||||||
xp_awk_tab_close (&awk->parse.params);
|
xp_awk_tab_close (&awk->parse.params);
|
||||||
xp_str_close (&awk->token.name);
|
xp_str_close (&awk->token.name);
|
||||||
|
|
||||||
@ -108,6 +129,7 @@ const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk)
|
|||||||
XP_TEXT("duplicate END"),
|
XP_TEXT("duplicate END"),
|
||||||
XP_TEXT("duplicate function name"),
|
XP_TEXT("duplicate function name"),
|
||||||
XP_TEXT("duplicate parameter name"),
|
XP_TEXT("duplicate parameter name"),
|
||||||
|
XP_TEXT("duplicate variable name"),
|
||||||
XP_TEXT("duplicate name"),
|
XP_TEXT("duplicate name"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -124,6 +146,11 @@ const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk)
|
|||||||
|
|
||||||
void xp_awk_clear (xp_awk_t* awk)
|
void xp_awk_clear (xp_awk_t* awk)
|
||||||
{
|
{
|
||||||
|
xp_awk_tab_clear (&awk->parse.globals);
|
||||||
|
xp_awk_tab_clear (&awk->parse.locals);
|
||||||
|
xp_awk_tab_clear (&awk->parse.params);
|
||||||
|
awk->parse.nlocals_max = 0;
|
||||||
|
|
||||||
/* clear parse trees */
|
/* clear parse trees */
|
||||||
xp_awk_hash_clear (&awk->tree.funcs);
|
xp_awk_hash_clear (&awk->tree.funcs);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: awk.h,v 1.23 2006-01-31 16:57:45 bacon Exp $
|
* $Id: awk.h,v 1.24 2006-02-04 19:31:51 bacon Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _XP_AWK_AWK_H_
|
#ifndef _XP_AWK_AWK_H_
|
||||||
@ -45,6 +45,7 @@ enum
|
|||||||
XP_AWK_EDUPEND, /* duplicate END */
|
XP_AWK_EDUPEND, /* duplicate END */
|
||||||
XP_AWK_EDUPFUNC, /* duplicate function name */
|
XP_AWK_EDUPFUNC, /* duplicate function name */
|
||||||
XP_AWK_EDUPPARAM, /* duplicate parameter name */
|
XP_AWK_EDUPPARAM, /* duplicate parameter name */
|
||||||
|
XP_AWK_EDUPVAR, /* duplicate variable name */
|
||||||
XP_AWK_EDUPNAME /* duplicate name - function, variable, etc */
|
XP_AWK_EDUPNAME /* duplicate name - function, variable, etc */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -71,7 +72,8 @@ enum
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
XP_AWK_EXPLICIT = (1 << 0), /* variable requires explicit declaration */
|
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 */
|
XP_AWK_UNIQUE = (1 << 1), /* a function name should not coincide to be a variable name */
|
||||||
|
XP_AWK_SHADING = (1 << 2) /* allow variable shading */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xp_awk_t
|
struct xp_awk_t
|
||||||
@ -104,9 +106,10 @@ struct xp_awk_t
|
|||||||
/* temporary information that the parser needs */
|
/* temporary information that the parser needs */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
// TODO: locals, globals???
|
xp_awk_tab_t globals;
|
||||||
//xp_awk_tab_t vars; /* global and local variable names... */
|
xp_awk_tab_t locals;
|
||||||
xp_awk_tab_t params;
|
xp_awk_tab_t params;
|
||||||
|
xp_size_t nlocals_max;
|
||||||
} parse;
|
} parse;
|
||||||
|
|
||||||
/* source buffer management */
|
/* source buffer management */
|
||||||
|
249
ase/awk/parse.c
249
ase/awk/parse.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: parse.c,v 1.42 2006-02-01 02:56:12 bacon Exp $
|
* $Id: parse.c,v 1.43 2006-02-04 19:31:51 bacon Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xp/awk/awk.h>
|
#include <xp/awk/awk.h>
|
||||||
@ -87,7 +87,8 @@ 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_begin (xp_awk_t* awk);
|
||||||
static xp_awk_node_t* __parse_end (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_action (xp_awk_t* awk);
|
||||||
static xp_awk_node_t* __parse_block (xp_awk_t* awk);
|
static xp_awk_node_t* __parse_block (xp_awk_t* awk, xp_bool_t is_top);
|
||||||
|
static xp_awk_t* __collect_locals (xp_awk_t* awk, xp_size_t nlocals);
|
||||||
static xp_awk_node_t* __parse_statement (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);
|
static xp_awk_node_t* __parse_statement_nb (xp_awk_t* awk);
|
||||||
static xp_awk_node_t* __parse_expression (xp_awk_t* awk);
|
static xp_awk_node_t* __parse_expression (xp_awk_t* awk);
|
||||||
@ -114,43 +115,42 @@ static int __get_char (xp_awk_t* awk);
|
|||||||
static int __unget_char (xp_awk_t* awk, xp_cint_t c);
|
static int __unget_char (xp_awk_t* awk, xp_cint_t c);
|
||||||
static int __skip_spaces (xp_awk_t* awk);
|
static int __skip_spaces (xp_awk_t* awk);
|
||||||
static int __skip_comment (xp_awk_t* awk);
|
static int __skip_comment (xp_awk_t* awk);
|
||||||
static int __classfy_ident (const xp_char_t* ident);
|
static int __classify_ident (xp_awk_t* awk, const xp_char_t* ident);
|
||||||
|
|
||||||
static xp_long_t __str_to_long (const xp_char_t* name);
|
static xp_long_t __str_to_long (const xp_char_t* name);
|
||||||
|
|
||||||
static INLINE xp_size_t __find_func_arg (xp_awk_t* awk, const xp_char_t* name);
|
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);
|
static INLINE xp_size_t __find_variable (xp_awk_t* awk, const xp_char_t* name);
|
||||||
|
|
||||||
|
|
||||||
struct __kwent
|
struct __kwent
|
||||||
{
|
{
|
||||||
const xp_char_t* name;
|
const xp_char_t* name;
|
||||||
int type;
|
int type;
|
||||||
|
int valid; /* the entry is valid when this option is set */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct __kwent __kwtab[] =
|
static struct __kwent __kwtab[] =
|
||||||
{
|
{
|
||||||
{ XP_TEXT("BEGIN"), TOKEN_BEGIN },
|
{ XP_TEXT("BEGIN"), TOKEN_BEGIN, 0 },
|
||||||
{ XP_TEXT("END"), TOKEN_END },
|
{ XP_TEXT("END"), TOKEN_END, 0 },
|
||||||
{ XP_TEXT("function"), TOKEN_FUNCTION },
|
{ XP_TEXT("function"), TOKEN_FUNCTION, 0 },
|
||||||
{ XP_TEXT("if"), TOKEN_IF },
|
{ XP_TEXT("if"), TOKEN_IF, 0 },
|
||||||
{ XP_TEXT("else"), TOKEN_ELSE },
|
{ XP_TEXT("else"), TOKEN_ELSE, 0 },
|
||||||
{ XP_TEXT("while"), TOKEN_WHILE },
|
{ XP_TEXT("while"), TOKEN_WHILE, 0 },
|
||||||
{ XP_TEXT("for"), TOKEN_FOR },
|
{ XP_TEXT("for"), TOKEN_FOR, 0 },
|
||||||
{ XP_TEXT("do"), TOKEN_DO },
|
{ XP_TEXT("do"), TOKEN_DO, 0 },
|
||||||
{ XP_TEXT("break"), TOKEN_BREAK },
|
{ XP_TEXT("break"), TOKEN_BREAK, 0 },
|
||||||
{ XP_TEXT("continue"), TOKEN_CONTINUE },
|
{ XP_TEXT("continue"), TOKEN_CONTINUE, 0 },
|
||||||
{ XP_TEXT("return"), TOKEN_RETURN },
|
{ XP_TEXT("return"), TOKEN_RETURN, 0 },
|
||||||
{ XP_TEXT("exit"), TOKEN_EXIT },
|
{ XP_TEXT("exit"), TOKEN_EXIT, 0 },
|
||||||
{ XP_TEXT("delete"), TOKEN_DELETE },
|
{ XP_TEXT("delete"), TOKEN_DELETE, 0 },
|
||||||
{ XP_TEXT("next"), TOKEN_NEXT },
|
{ XP_TEXT("next"), TOKEN_NEXT, 0 },
|
||||||
{ XP_TEXT("nextfile"), TOKEN_NEXTFILE },
|
{ XP_TEXT("nextfile"), TOKEN_NEXTFILE, 0 },
|
||||||
|
|
||||||
// TODO: don't return TOKEN_LOCAL & TOKEN_GLOBAL when explicit variable declaration is disabled.
|
{ XP_TEXT("local"), TOKEN_LOCAL, XP_AWK_EXPLICIT },
|
||||||
{ XP_TEXT("local"), TOKEN_LOCAL },
|
{ XP_TEXT("global"), TOKEN_GLOBAL, XP_AWK_EXPLICIT },
|
||||||
{ XP_TEXT("global"), TOKEN_GLOBAL },
|
|
||||||
|
|
||||||
{ XP_NULL, 0 },
|
{ XP_NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GET_CHAR(awk) \
|
#define GET_CHAR(awk) \
|
||||||
@ -184,7 +184,6 @@ static struct __kwent __kwtab[] =
|
|||||||
|
|
||||||
#define PANIC(awk,code) do { (awk)->errnum = (code); return XP_NULL; } while (0);
|
#define PANIC(awk,code) do { (awk)->errnum = (code); return XP_NULL; } while (0);
|
||||||
|
|
||||||
|
|
||||||
// TODO: remove stdio.h
|
// TODO: remove stdio.h
|
||||||
#ifndef __STAND_ALONE
|
#ifndef __STAND_ALONE
|
||||||
#include <xp/bas/stdio.h>
|
#include <xp/bas/stdio.h>
|
||||||
@ -215,6 +214,8 @@ static void __dump (xp_awk_t* awk)
|
|||||||
xp_printf (XP_TEXT("END "));
|
xp_printf (XP_TEXT("END "));
|
||||||
xp_awk_prnpt (awk->tree.end);
|
xp_awk_prnpt (awk->tree.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: dump unmaed top-level blocks...
|
||||||
}
|
}
|
||||||
|
|
||||||
int xp_awk_parse (xp_awk_t* awk)
|
int xp_awk_parse (xp_awk_t* awk)
|
||||||
@ -307,8 +308,8 @@ static xp_awk_node_t* __parse_function (xp_awk_t* awk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (awk->opt.parse & XP_AWK_UNIQUE) {
|
if (awk->opt.parse & XP_AWK_UNIQUE) {
|
||||||
/* check if it coincides to be a variable name */
|
/* check if it coincides to be a global variable name */
|
||||||
if (__find_variable(awk,name) != (xp_size_t)-1) {
|
if (xp_awk_tab_find(&awk->parse.globals, name, 0) != (xp_size_t)-1) {
|
||||||
PANIC (awk, XP_AWK_EDUPNAME);
|
PANIC (awk, XP_AWK_EDUPNAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,24 +350,41 @@ static xp_awk_node_t* __parse_function (xp_awk_t* awk)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
while (1) {
|
while (1) {
|
||||||
|
xp_char_t* param;
|
||||||
|
|
||||||
if (!MATCH(awk,TOKEN_IDENT)) {
|
if (!MATCH(awk,TOKEN_IDENT)) {
|
||||||
xp_free (name_dup);
|
xp_free (name_dup);
|
||||||
xp_awk_tab_clear (&awk->parse.params);
|
xp_awk_tab_clear (&awk->parse.params);
|
||||||
PANIC (awk, XP_AWK_EIDENT);
|
PANIC (awk, XP_AWK_EIDENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check duplicates againt variables if shading is not supported
|
param = XP_STR_BUF(&awk->token.name);
|
||||||
// global x; function f (x) { print x; } -> x in print x is a parameter
|
|
||||||
|
|
||||||
if (xp_awk_tab_find (&awk->parse.params,
|
if (awk->opt.parse & XP_AWK_UNIQUE) {
|
||||||
XP_STR_BUF(&awk->token.name), 0) != (xp_size_t)-1) {
|
/* check if a parameter conflicts with a function */
|
||||||
|
if (xp_strcmp(name_dup, param) == 0 ||
|
||||||
|
xp_awk_hash_get(&awk->tree.funcs, param) != XP_NULL) {
|
||||||
|
xp_free (name_dup);
|
||||||
|
xp_awk_tab_clear (&awk->parse.params);
|
||||||
|
PANIC (awk, XP_AWK_EDUPNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: the following is not a conflict
|
||||||
|
* global x;
|
||||||
|
* function f (x) { print x; }
|
||||||
|
* x in print x is a parameter
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if a parameter conflicts with other parameters */
|
||||||
|
if (xp_awk_tab_find(&awk->parse.params, param, 0) != (xp_size_t)-1) {
|
||||||
xp_free (name_dup);
|
xp_free (name_dup);
|
||||||
xp_awk_tab_clear (&awk->parse.params);
|
xp_awk_tab_clear (&awk->parse.params);
|
||||||
PANIC (awk, XP_AWK_EDUPPARAM);
|
PANIC (awk, XP_AWK_EDUPPARAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xp_awk_tab_adddatum (&awk->parse.params,
|
/* push the parameter to the parameter list */
|
||||||
XP_STR_BUF(&awk->token.name)) == (xp_size_t)-1) {
|
if (xp_awk_tab_adddatum(&awk->parse.params, param) == (xp_size_t)-1) {
|
||||||
xp_free (name_dup);
|
xp_free (name_dup);
|
||||||
xp_awk_tab_clear (&awk->parse.params);
|
xp_awk_tab_clear (&awk->parse.params);
|
||||||
PANIC (awk, XP_AWK_ENOMEM);
|
PANIC (awk, XP_AWK_ENOMEM);
|
||||||
@ -413,7 +431,7 @@ static xp_awk_node_t* __parse_function (xp_awk_t* awk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* actual function body */
|
/* actual function body */
|
||||||
body = __parse_block (awk);
|
body = __parse_block (awk, xp_true);
|
||||||
if (body == XP_NULL) {
|
if (body == XP_NULL) {
|
||||||
xp_free (name_dup);
|
xp_free (name_dup);
|
||||||
xp_awk_tab_clear (&awk->parse.params);
|
xp_awk_tab_clear (&awk->parse.params);
|
||||||
@ -479,106 +497,164 @@ static xp_awk_node_t* __parse_action (xp_awk_t* awk)
|
|||||||
{
|
{
|
||||||
if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, XP_AWK_ELBRACE);
|
if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, XP_AWK_ELBRACE);
|
||||||
if (__get_token(awk) == -1) return XP_NULL;
|
if (__get_token(awk) == -1) return XP_NULL;
|
||||||
return __parse_block(awk);
|
return __parse_block(awk, xp_true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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, xp_bool_t is_top)
|
||||||
static xp_awk_node_t* __parse_block (xp_awk_t* awk)
|
|
||||||
{
|
{
|
||||||
xp_awk_node_t* head, * curr, * node;
|
xp_awk_node_t* head, * curr, * node;
|
||||||
xp_awk_node_block_t* block;
|
xp_awk_node_block_t* block;
|
||||||
xp_size_t lvc = 0;
|
xp_size_t nlocals, tmp;
|
||||||
|
|
||||||
/* local variable declaration */
|
nlocals = xp_awk_tab_getsize(&awk->parse.locals);
|
||||||
//TODO: if (awk->opt & XP_AWK_VARDECL) {
|
|
||||||
while (1) {
|
/* local variable declarations */
|
||||||
if (MATCH(awk,TOKEN_EOF)) {
|
if (awk->opt.parse & XP_AWK_EXPLICIT) {
|
||||||
// cleanup the variable name list...
|
while (1) {
|
||||||
PANIC (awk, XP_AWK_EENDSRC);
|
if (!MATCH(awk,TOKEN_LOCAL)) break;
|
||||||
}
|
|
||||||
|
|
||||||
if (MATCH(awk,TOKEN_RBRACE)) {
|
|
||||||
if (__get_token(awk) == -1) {
|
if (__get_token(awk) == -1) {
|
||||||
// TODO: cleanup the variable name list...
|
xp_awk_tab_remrange (
|
||||||
|
&awk->parse.locals, nlocals - 1,
|
||||||
|
xp_awk_tab_getsize(&awk->parse.locals) - nlocals);
|
||||||
return XP_NULL;
|
return XP_NULL;
|
||||||
}
|
}
|
||||||
head = XP_NULL;
|
|
||||||
goto skip_block_body;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!MATCH(awk,TOKEN_LOCAL)) break;
|
if (__collect_locals(awk, nlocals) == XP_NULL) {
|
||||||
|
xp_awk_tab_remrange (
|
||||||
if (__get_token(awk) == -1) {
|
&awk->parse.locals, nlocals - 1,
|
||||||
// TODO: cleanup the variable name list...
|
xp_awk_tab_getsize(&awk->parse.locals) - nlocals);
|
||||||
return XP_NULL;
|
return XP_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// TODO: collect variables...
|
|
||||||
// TODO: check duplicates with locals and globals, and maybe with the function names also depending on the awk options....
|
|
||||||
}
|
}
|
||||||
// TODO: }
|
|
||||||
|
|
||||||
/* block body */
|
/* block body */
|
||||||
head = XP_NULL; curr = XP_NULL;
|
head = XP_NULL; curr = XP_NULL;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (MATCH(awk,TOKEN_EOF)) {
|
if (MATCH(awk,TOKEN_EOF)) {
|
||||||
// TODO: cleanup the variable name list...
|
xp_awk_tab_remrange (
|
||||||
|
&awk->parse.locals, nlocals - 1,
|
||||||
|
xp_awk_tab_getsize(&awk->parse.locals) - nlocals);
|
||||||
if (head != XP_NULL) xp_awk_clrpt (head);
|
if (head != XP_NULL) xp_awk_clrpt (head);
|
||||||
PANIC (awk, XP_AWK_EENDSRC);
|
PANIC (awk, XP_AWK_EENDSRC);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MATCH(awk,TOKEN_RBRACE)) {
|
if (MATCH(awk,TOKEN_RBRACE)) {
|
||||||
if (__get_token(awk) == -1) {
|
if (__get_token(awk) == -1) {
|
||||||
// TODO: cleanup the variable name list...
|
xp_awk_tab_remrange (
|
||||||
|
&awk->parse.locals, nlocals - 1,
|
||||||
|
xp_awk_tab_getsize(&awk->parse.locals) - nlocals);
|
||||||
if (head != XP_NULL) xp_awk_clrpt (head);
|
if (head != XP_NULL) xp_awk_clrpt (head);
|
||||||
return XP_NULL;
|
return XP_NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: if you want to remove top-level null statement... get it here... */
|
|
||||||
/*
|
|
||||||
if (MATCH(awk,TOKEN_SEMICOLON)) {
|
|
||||||
if (__get_token(awk) == -1) {
|
|
||||||
// TODO: cleanup the variable name list...
|
|
||||||
if (head != XP_NULL) xp_awk_clrpt (head);
|
|
||||||
return XP_NULL;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
node = __parse_statement (awk);
|
node = __parse_statement (awk);
|
||||||
if (node == XP_NULL) {
|
if (node == XP_NULL) {
|
||||||
// TODO: cleanup the variable name list...
|
xp_awk_tab_remrange (
|
||||||
|
&awk->parse.locals, nlocals - 1,
|
||||||
|
xp_awk_tab_getsize(&awk->parse.locals) - nlocals);
|
||||||
if (head != XP_NULL) xp_awk_clrpt (head);
|
if (head != XP_NULL) xp_awk_clrpt (head);
|
||||||
return XP_NULL;
|
return XP_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* remove unnecessary statements */
|
||||||
|
if (node->type == XP_AWK_NODE_NULL ||
|
||||||
|
(node->type == XP_AWK_NODE_BLOCK &&
|
||||||
|
((xp_awk_node_block_t*)node)->body == XP_NULL)) continue;
|
||||||
|
|
||||||
if (curr == XP_NULL) head = node;
|
if (curr == XP_NULL) head = node;
|
||||||
else curr->next = node;
|
else curr->next = node;
|
||||||
curr = node;
|
curr = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_block_body:
|
|
||||||
|
|
||||||
block = (xp_awk_node_block_t*) xp_malloc (xp_sizeof(xp_awk_node_block_t));
|
block = (xp_awk_node_block_t*) xp_malloc (xp_sizeof(xp_awk_node_block_t));
|
||||||
if (block == XP_NULL) {
|
if (block == XP_NULL) {
|
||||||
// TODO: cleanup the variable name list...
|
xp_awk_tab_remrange (
|
||||||
|
&awk->parse.locals, nlocals - 1,
|
||||||
|
xp_awk_tab_getsize(&awk->parse.locals) - nlocals);
|
||||||
xp_awk_clrpt (head);
|
xp_awk_clrpt (head);
|
||||||
PANIC (awk, XP_AWK_ENOMEM);
|
PANIC (awk, XP_AWK_ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove empty block such as { } { ;;;; }, or { local a, b, c; ;;; }. etc
|
tmp = xp_awk_tab_getsize(&awk->parse.locals);
|
||||||
|
xp_awk_tab_remrange (
|
||||||
|
&awk->parse.locals, nlocals - 1, tmp - nlocals);
|
||||||
|
|
||||||
|
/* adjust number of locals for a block without any statements */
|
||||||
|
if (head == NULL) tmp = 0;
|
||||||
|
|
||||||
block->type = XP_AWK_NODE_BLOCK;
|
block->type = XP_AWK_NODE_BLOCK;
|
||||||
block->next = XP_NULL;
|
block->next = XP_NULL;
|
||||||
block->lvc = lvc;
|
|
||||||
block->body = head;
|
block->body = head;
|
||||||
|
|
||||||
// TODO: cleanup the variable name list...
|
if (is_top) {
|
||||||
|
block->nlocals = awk->parse.nlocals_max - nlocals;
|
||||||
|
awk->parse.nlocals_max = nlocals;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
block->nlocals = 0;
|
||||||
|
if (tmp > awk->parse.nlocals_max) awk->parse.nlocals_max = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
return (xp_awk_node_t*)block;
|
return (xp_awk_node_t*)block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static xp_awk_t* __collect_locals (xp_awk_t* awk, xp_size_t nlocals)
|
||||||
|
{
|
||||||
|
xp_char_t* local;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (!MATCH(awk,TOKEN_IDENT)) {
|
||||||
|
PANIC (awk, XP_AWK_EIDENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
local = XP_STR_BUF(&awk->token.name);
|
||||||
|
|
||||||
|
/* NOTE: it is not checked againt globals names */
|
||||||
|
|
||||||
|
if (awk->opt.parse & XP_AWK_UNIQUE) {
|
||||||
|
/* check if it conflict with a function name */
|
||||||
|
if (xp_awk_hash_get(&awk->tree.funcs, local) != XP_NULL) {
|
||||||
|
PANIC (awk, XP_AWK_EDUPNAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if it conflicts with a paremeter name */
|
||||||
|
if (xp_awk_tab_find(&awk->parse.params, local, 0) != (xp_size_t)-1) {
|
||||||
|
PANIC (awk, XP_AWK_EDUPNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if it conflicts with other local variable names */
|
||||||
|
if (xp_awk_tab_find(&awk->parse.locals, local,
|
||||||
|
((awk->opt.parse & XP_AWK_SHADING)? nlocals: 0)) != (xp_size_t)-1) {
|
||||||
|
PANIC (awk, XP_AWK_EDUPVAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xp_awk_tab_adddatum(&awk->parse.locals, local) == (xp_size_t)-1) {
|
||||||
|
PANIC (awk, XP_AWK_ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (__get_token(awk) == -1) return XP_NULL;
|
||||||
|
|
||||||
|
if (MATCH(awk,TOKEN_SEMICOLON)) break;
|
||||||
|
|
||||||
|
if (!MATCH(awk,TOKEN_COMMA)) {
|
||||||
|
PANIC (awk, XP_AWK_ECOMMA);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (__get_token(awk) == -1) return XP_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip a semicolon */
|
||||||
|
if (__get_token(awk) == -1) return XP_NULL;
|
||||||
|
|
||||||
|
return awk;
|
||||||
|
}
|
||||||
|
|
||||||
static xp_awk_node_t* __parse_statement (xp_awk_t* awk)
|
static xp_awk_node_t* __parse_statement (xp_awk_t* awk)
|
||||||
{
|
{
|
||||||
xp_awk_node_t* node;
|
xp_awk_node_t* node;
|
||||||
@ -598,7 +674,7 @@ static xp_awk_node_t* __parse_statement (xp_awk_t* awk)
|
|||||||
}
|
}
|
||||||
else if (MATCH(awk,TOKEN_LBRACE)) {
|
else if (MATCH(awk,TOKEN_LBRACE)) {
|
||||||
if (__get_token(awk) == -1) return XP_NULL;
|
if (__get_token(awk) == -1) return XP_NULL;
|
||||||
node = __parse_block (awk);
|
node = __parse_block (awk, xp_false);
|
||||||
}
|
}
|
||||||
else node = __parse_statement_nb (awk);
|
else node = __parse_statement_nb (awk);
|
||||||
|
|
||||||
@ -1561,7 +1637,7 @@ static int __get_token (xp_awk_t* awk)
|
|||||||
GET_CHAR_TO (awk, c);
|
GET_CHAR_TO (awk, c);
|
||||||
} while (xp_isalpha(c) || c == XP_CHAR('_') || xp_isdigit(c));
|
} while (xp_isalpha(c) || c == XP_CHAR('_') || xp_isdigit(c));
|
||||||
|
|
||||||
SET_TOKEN_TYPE (awk, __classfy_ident(XP_STR_BUF(&awk->token.name)));
|
SET_TOKEN_TYPE (awk, __classify_ident(awk, XP_STR_BUF(&awk->token.name)));
|
||||||
}
|
}
|
||||||
else if (c == XP_CHAR('\"')) {
|
else if (c == XP_CHAR('\"')) {
|
||||||
/* string */
|
/* string */
|
||||||
@ -1780,13 +1856,13 @@ static int __skip_comment (xp_awk_t* awk)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __classfy_ident (const xp_char_t* ident)
|
static int __classify_ident (xp_awk_t* awk, const xp_char_t* ident)
|
||||||
{
|
{
|
||||||
struct __kwent* p = __kwtab;
|
struct __kwent* p = __kwtab;
|
||||||
|
|
||||||
while (p->name != XP_NULL) {
|
for (p = __kwtab; p->name != XP_NULL; p++) {
|
||||||
|
if (p->valid != 0 && (awk->opt.parse & p->valid) == 0) continue;
|
||||||
if (xp_strcmp(p->name, ident) == 0) return p->type;
|
if (xp_strcmp(p->name, ident) == 0) return p->type;
|
||||||
p++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TOKEN_IDENT;
|
return TOKEN_IDENT;
|
||||||
@ -1806,18 +1882,13 @@ static xp_long_t __str_to_long (const xp_char_t* name)
|
|||||||
|
|
||||||
static INLINE xp_size_t __find_func_arg (xp_awk_t* awk, const xp_char_t* name)
|
static INLINE xp_size_t __find_func_arg (xp_awk_t* awk, const xp_char_t* name)
|
||||||
{
|
{
|
||||||
/*
|
// TODO:
|
||||||
if (awk->curfunc != XP_NULL) {
|
|
||||||
|
|
||||||
// TODO: finish this....
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
return (xp_size_t)-1;
|
return (xp_size_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static xp_size_t __find_variable (xp_awk_t* awk, const xp_char_t* name)
|
static xp_size_t __find_variable (xp_awk_t* awk, const xp_char_t* name)
|
||||||
{
|
{
|
||||||
|
// TODO:
|
||||||
return (xp_size_t)-1;
|
return (xp_size_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: tree.c,v 1.15 2006-02-01 02:56:12 bacon Exp $
|
* $Id: tree.c,v 1.16 2006-02-04 19:31:51 bacon Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xp/awk/awk.h>
|
#include <xp/awk/awk.h>
|
||||||
@ -133,6 +133,11 @@ static void __print_statements (xp_awk_node_t* tree, int depth)
|
|||||||
case XP_AWK_NODE_BLOCK:
|
case XP_AWK_NODE_BLOCK:
|
||||||
__print_tabs (depth);
|
__print_tabs (depth);
|
||||||
xp_printf (XP_TEXT("{\n"));
|
xp_printf (XP_TEXT("{\n"));
|
||||||
|
if (((xp_awk_node_block_t*)p)->nlocals > 0) {
|
||||||
|
__print_tabs (depth + 1);
|
||||||
|
xp_printf (XP_TEXT("NLOCALS=>%u;\n"),
|
||||||
|
(unsigned int)((xp_awk_node_block_t*)p)->nlocals);
|
||||||
|
}
|
||||||
__print_statements (((xp_awk_node_block_t*)p)->body, depth + 1);
|
__print_statements (((xp_awk_node_block_t*)p)->body, depth + 1);
|
||||||
__print_tabs (depth);
|
__print_tabs (depth);
|
||||||
xp_printf (XP_TEXT("}\n"));
|
xp_printf (XP_TEXT("}\n"));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: tree.h,v 1.20 2006-02-01 02:56:12 bacon Exp $
|
* $Id: tree.h,v 1.21 2006-02-04 19:31:51 bacon Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _XP_AWK_TREE_H_
|
#ifndef _XP_AWK_TREE_H_
|
||||||
@ -74,7 +74,7 @@ struct xp_awk_node_sgv_t
|
|||||||
struct xp_awk_node_block_t
|
struct xp_awk_node_block_t
|
||||||
{
|
{
|
||||||
XP_AWK_NODE_HDR;
|
XP_AWK_NODE_HDR;
|
||||||
xp_size_t lvc; /* local variable count */
|
xp_size_t nlocals;
|
||||||
xp_awk_node_t* body;
|
xp_awk_node_t* body;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ int xp_main (int argc, xp_char_t* argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
awk.opt.parse = XP_AWK_EXPLICIT | XP_AWK_UNIQUE;
|
||||||
if (xp_awk_parse(&awk) == -1) {
|
if (xp_awk_parse(&awk) == -1) {
|
||||||
xp_printf (
|
xp_printf (
|
||||||
XP_TEXT("error: cannot parse program - [%d] %s\n"),
|
XP_TEXT("error: cannot parse program - [%d] %s\n"),
|
||||||
|
Loading…
Reference in New Issue
Block a user