*** empty log message ***

This commit is contained in:
hyung-hwan 2006-01-14 14:09:52 +00:00
parent e4f41654d6
commit cb8c7535bc
6 changed files with 454 additions and 196 deletions

View File

@ -1,4 +1,4 @@
SRCS = awk.c parse.c SRCS = awk.c parse.c tree.c
OBJS = $(SRCS:.c=.obj) OBJS = $(SRCS:.c=.obj)
OUT = xpawk.lib OUT = xpawk.lib

View File

@ -1,4 +1,4 @@
SRCS = awk.c parse.c SRCS = awk.c parse.c tree.c
OBJS = $(SRCS:.c=.obj) OBJS = $(SRCS:.c=.obj)
OUT = xpawk.lib OUT = xpawk.lib

View File

@ -1,16 +1,14 @@
/* /*
* $Id: parse.c,v 1.18 2006-01-13 14:16:56 bacon Exp $ * $Id: parse.c,v 1.19 2006-01-14 14:08:57 bacon Exp $
*/ */
#include <xp/awk/awk.h> #include <xp/awk/awk.h>
#include <xp/awk/tree.h> #include <xp/awk/tree.h>
#include <xp/awk/tree.h>
#include <xp/bas/memory.h> #include <xp/bas/memory.h>
#include <xp/bas/ctype.h> #include <xp/bas/ctype.h>
#include <xp/bas/string.h> #include <xp/bas/string.h>
#include <xp/bas/assert.h> #include <xp/bas/assert.h>
#include <xp/bas/stdio.h>
enum enum
{ {
TOKEN_EOF, TOKEN_EOF,
@ -68,21 +66,12 @@ enum {
BINOP_MOD BINOP_MOD
}; };
static xp_char_t __binop_char[] =
{
XP_CHAR('+'),
XP_CHAR('-'),
XP_CHAR('*'),
XP_CHAR('/'),
XP_CHAR('%')
};
static xp_awk_node_t* __parse_program (xp_awk_t* awk); 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_funcdcl (xp_awk_t* awk);
static xp_awk_node_t* __parse_patnact (xp_awk_t* awk); static xp_awk_node_t* __parse_patnact (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);
static xp_awk_node_t* __parse_stat (xp_awk_t* awk); static xp_awk_node_t* __parse_statement (xp_awk_t* awk);
static xp_awk_node_t* __parse_expr (xp_awk_t* awk); static xp_awk_node_t* __parse_expression (xp_awk_t* awk);
static xp_awk_node_t* __parse_assignment (xp_awk_t* awk, xp_char_t* ident); static xp_awk_node_t* __parse_assignment (xp_awk_t* awk, xp_char_t* ident);
static xp_awk_node_t* __parse_basic_expr (xp_awk_t* awk, xp_char_t* ident); static xp_awk_node_t* __parse_basic_expr (xp_awk_t* awk, xp_char_t* ident);
static xp_awk_node_t* __parse_additive (xp_awk_t* awk, xp_char_t* ident); static xp_awk_node_t* __parse_additive (xp_awk_t* awk, xp_char_t* ident);
@ -96,6 +85,8 @@ static xp_awk_node_t* __parse_for (xp_awk_t* awk);
static xp_awk_node_t* __parse_do (xp_awk_t* awk); static xp_awk_node_t* __parse_do (xp_awk_t* awk);
static xp_awk_node_t* __parse_break (xp_awk_t* awk); static xp_awk_node_t* __parse_break (xp_awk_t* awk);
static xp_awk_node_t* __parse_continue (xp_awk_t* awk); static xp_awk_node_t* __parse_continue (xp_awk_t* awk);
static xp_awk_node_t* __parse_return (xp_awk_t* awk);
static xp_awk_node_t* __parse_exit (xp_awk_t* awk);
static int __get_token (xp_awk_t* awk); static int __get_token (xp_awk_t* awk);
static int __get_char (xp_awk_t* awk); static int __get_char (xp_awk_t* awk);
@ -160,75 +151,8 @@ 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);
void __print_tabs (int depth) // TODO remove stdio.h
{ #include <xp/bas/stdio.h>
int i;
for (i = 0; i < depth; i++) xp_printf (XP_TEXT("\t"));
}
void __print_parse_tree (xp_awk_node_t* tree, int depth)
{
xp_awk_node_t* p;
p = tree;
while (p != XP_NULL) {
if (p->type == XP_AWK_NODE_BLOCK) {
__print_tabs (depth);
xp_printf (XP_TEXT("{\n"));
__print_parse_tree (((xp_awk_node_block_t*)p)->body, depth + 1);
__print_tabs (depth);
xp_printf (XP_TEXT("}\n"));
}
else if (p->type == XP_AWK_NODE_BREAK) {
__print_tabs (depth);
xp_printf (XP_TEXT("break;\n"));
}
else if (p->type == XP_AWK_NODE_CONTINUE) {
__print_tabs (depth);
xp_printf (XP_TEXT("continue;\n"));
}
else if (p->type == XP_AWK_NODE_ASSIGN) {
__print_tabs (depth);
xp_printf (XP_TEXT("%s = "), ((xp_awk_node_assign_t*)p)->left);
__print_parse_tree (((xp_awk_node_assign_t*)p)->right, 0);
xp_printf (XP_TEXT(";\n"));
}
else if (p->type == XP_AWK_NODE_BINARY) {
xp_printf (XP_TEXT("("));
__print_parse_tree (((xp_awk_node_expr_t*)p)->left, 0);
xp_printf (XP_TEXT(" %c "), __binop_char[((xp_awk_node_expr_t*)p)->opcode]);
__print_parse_tree (((xp_awk_node_expr_t*)p)->right, 0);
xp_printf (XP_TEXT(")"));
}
else if (p->type == XP_AWK_NODE_UNARY) {
xp_printf (XP_TEXT("unary basic expression\n"));
}
else if (p->type == XP_AWK_NODE_STR) {
xp_printf (XP_TEXT("\"%s\""), ((xp_awk_node_term_t*)p)->value);
}
else if (p->type == XP_AWK_NODE_NUM) {
xp_printf (XP_TEXT("%s"), ((xp_awk_node_term_t*)p)->value);
}
else if (p->type == XP_AWK_NODE_VAR) {
xp_printf (XP_TEXT("%s"), ((xp_awk_node_term_t*)p)->value);
}
else if (p->type == XP_AWK_NODE_CALL) {
xp_printf (XP_TEXT("%s ("), ((xp_awk_node_call_t*)p)->name);
__print_parse_tree (((xp_awk_node_call_t*)p)->args, 0); // TODO: improve this... comman-separated...
xp_printf (XP_TEXT(")"));
}
p = p->next;
}
}
void print_parse_tree (xp_awk_node_t* tree)
{
__print_parse_tree (tree, 0);
}
int xp_awk_parse (xp_awk_t* awk) int xp_awk_parse (xp_awk_t* awk)
{ {
@ -272,7 +196,6 @@ break;
return node; return node;
} }
static xp_awk_node_t* __parse_funcdcl (xp_awk_t* awk) static xp_awk_node_t* __parse_funcdcl (xp_awk_t* awk)
{ {
return XP_NULL; return XP_NULL;
@ -295,152 +218,160 @@ static xp_awk_node_t* __parse_patnact (xp_awk_t* awk)
xp_awk_node_t* node; xp_awk_node_t* node;
if (MATCH(awk,TOKEN_BEGIN)) { if (MATCH(awk,TOKEN_BEGIN)) {
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
} }
else if (MATCH(awk,TOKEN_END)) { else if (MATCH(awk,TOKEN_END)) {
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
} }
/* patterns ... /* patterns ...
* etc */ * etc */
if (!MATCH(awk,TOKEN_LBRACE)) { if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, XP_AWK_ELBRACE);
PANIC (awk, XP_AWK_ELBRACE); if (__get_token(awk) == -1) return XP_NULL;
}
CONSUME (awk);
node = __parse_block(awk); node = __parse_block(awk);
if (node == XP_NULL) return XP_NULL; if (node == XP_NULL) return XP_NULL;
return node; return node;
} }
/* TODO: what is the best name for the parsing routine for the outermost block? */ /* 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) static xp_awk_node_t* __parse_block (xp_awk_t* awk)
{ {
xp_awk_node_block_t* blk; xp_awk_node_t* head, * curr, * node;
xp_awk_node_t* node, * prev; xp_awk_node_block_t* block;
blk = (xp_awk_node_block_t*) xp_malloc (xp_sizeof(xp_awk_node_block_t)); head = XP_NULL; curr = XP_NULL;
if (blk == XP_NULL) {
/* TODO: do some clean-up */
PANIC (awk, XP_AWK_ENOMEM);
}
blk->type = XP_AWK_NODE_BLOCK;
blk->next = XP_NULL;
blk->body = prev = XP_NULL;
while (1) { while (1) {
if (MATCH(awk,TOKEN_EOF)) { if (MATCH(awk,TOKEN_EOF)) {
/* TODO: do come clean-up */ if (curr != XP_NULL) xp_awk_clrpt (curr);
PANIC (awk, XP_AWK_EENDSRC); PANIC (awk, XP_AWK_EENDSRC);
} }
if (MATCH(awk,TOKEN_RBRACE)) { if (MATCH(awk,TOKEN_RBRACE)) {
/* TODO: should finalize a block */ if (__get_token(awk) == -1) {
CONSUME (awk); if (curr != XP_NULL) xp_awk_clrpt (curr);
return XP_NULL;
}
break; break;
} }
if (MATCH(awk, TOKEN_SEMICOLON)) { if (MATCH(awk,TOKEN_SEMICOLON)) {
/* null statement */ /* null statement */
CONSUME (awk); if (__get_token(awk) == -1) {
if (curr != XP_NULL) xp_awk_clrpt (curr);
return XP_NULL;
}
continue; continue;
} }
if (MATCH(awk,TOKEN_LBRACE)) { if (MATCH(awk,TOKEN_LBRACE)) {
/* nested block */ /* nested block */
CONSUME (awk); if (__get_token(awk) == -1) {
node = __parse_block(awk); if (curr != XP_NULL) xp_awk_clrpt (curr);
return XP_NULL;
} }
else node = __parse_stat (awk); node = __parse_block (awk);
}
else node = __parse_statement (awk);
if (node == XP_NULL) return XP_NULL; if (node == XP_NULL) {
if (curr != XP_NULL) xp_awk_clrpt (curr);
if (prev == XP_NULL) blk->body = node; return XP_NULL;
else prev->next = node;
prev = node;
} }
return (xp_awk_node_t*)blk; if (curr == XP_NULL) head = node;
else curr->next = node;
curr = node;
}
block = (xp_awk_node_block_t*) xp_malloc (xp_sizeof(xp_awk_node_block_t));
if (block == XP_NULL) {
xp_awk_clrpt (head);
PANIC (awk, XP_AWK_ENOMEM);
}
block->type = XP_AWK_NODE_BLOCK;
block->next = XP_NULL;
block->body = head;
return (xp_awk_node_t*)block;
} }
static xp_awk_node_t* __parse_stat (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;
if (MATCH(awk,TOKEN_IF)) { if (MATCH(awk,TOKEN_IF)) {
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
node = __parse_if(awk); node = __parse_if(awk);
} }
else if (MATCH(awk,TOKEN_WHILE)) { else if (MATCH(awk,TOKEN_WHILE)) {
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
node = __parse_while(awk); node = __parse_while(awk);
} }
else if (MATCH(awk,TOKEN_FOR)) { else if (MATCH(awk,TOKEN_FOR)) {
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
node = __parse_for(awk); node = __parse_for(awk);
} }
else if (MATCH(awk,TOKEN_DO)) { else if (MATCH(awk,TOKEN_DO)) {
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
node = __parse_do(awk); node = __parse_do(awk);
} }
else if (MATCH(awk,TOKEN_BREAK)) { else if (MATCH(awk,TOKEN_BREAK)) {
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
node = __parse_break(awk); node = __parse_break(awk);
} }
else if (MATCH(awk,TOKEN_CONTINUE)) { else if (MATCH(awk,TOKEN_CONTINUE)) {
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
node = __parse_continue(awk); node = __parse_continue(awk);
} }
else if (MATCH(awk,TOKEN_RETURN)) { else if (MATCH(awk,TOKEN_RETURN)) {
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
/* TOOD: */ node = __parse_return(awk);
node = XP_NULL;
} }
else if (MATCH(awk,TOKEN_EXIT)) { else if (MATCH(awk,TOKEN_EXIT)) {
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
/* TOOD: */ node = __parse_exit(awk);
node = XP_NULL;
} }
/*
TODO:
else if (MATCH(awk,TOKEN_DELETE)) { else if (MATCH(awk,TOKEN_DELETE)) {
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
/* TOOD: */
node = XP_NULL; node = XP_NULL;
} }
else if (MATCH(awk,TOKEN_NEXT)) { else if (MATCH(awk,TOKEN_NEXT)) {
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
/* TOOD: */
node = XP_NULL; node = XP_NULL;
} }
else if (MATCH(awk,TOKEN_NEXTFILE)) { else if (MATCH(awk,TOKEN_NEXTFILE)) {
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
/* TOOD: */
node = XP_NULL; node = XP_NULL;
} }
*/
else { else {
node = __parse_expr(awk); node = __parse_expression(awk);
} }
if (node == XP_NULL) { if (node == XP_NULL) return XP_NULL;
// TODO: clean-up
return XP_NULL;
}
/* check if a statement ends with a semicolon */ /* check if a statement ends with a semicolon */
if (!MATCH(awk,TOKEN_SEMICOLON)) { if (!MATCH(awk,TOKEN_SEMICOLON)) {
/* TODO: do some clean-up */ if (node != XP_NULL) xp_awk_clrpt (node);
PANIC (awk, XP_AWK_ESEMICOLON); PANIC (awk, XP_AWK_ESEMICOLON);
} }
/* eat up the semicolon and read in the next token */ /* eat up the semicolon and read in the next token */
CONSUME (awk); if (__get_token(awk) == -1) {
if (node != XP_NULL) xp_awk_clrpt (node);
return XP_NULL;
}
return node; return node;
} }
static xp_awk_node_t* __parse_expr (xp_awk_t* awk) static xp_awk_node_t* __parse_expression (xp_awk_t* awk)
{ {
/* /*
* <expression> ::= <assignment> | <basic expression> * <expression> ::= <assignment> | <basic expression>
@ -448,29 +379,38 @@ static xp_awk_node_t* __parse_expr (xp_awk_t* awk)
* assignmentOperator ::= '=' * assignmentOperator ::= '='
* <basic expression> ::= * <basic expression> ::=
*/ */
xp_awk_node_t* x; xp_awk_node_t* x;
if (MATCH(awk,TOKEN_IDENT)) { if (MATCH(awk,TOKEN_IDENT)) {
// TODO: use a different approach later... /* the expression starts with an identifier */
xp_char_t* ident = xp_strdup (XP_STR_BUF(&awk->token.name));
if (ident == XP_NULL) {
// TODO: memory clean up
PANIC (awk, XP_AWK_ENOMEM);
}
CONSUME (awk); xp_char_t* ident = xp_strdup (XP_STR_BUF(&awk->token.name));
if (ident == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
if (__get_token(awk) == -1) {
xp_free (ident);
return XP_NULL;
}
if (MATCH(awk,TOKEN_ASSIGN)) { if (MATCH(awk,TOKEN_ASSIGN)) {
CONSUME (awk); if (__get_token(awk) == -1) {
x = __parse_assignment(awk, ident); xp_free (ident);
return XP_NULL;
}
x = __parse_assignment (awk, ident);
} }
else x = __parse_basic_expr (awk, ident); else x = __parse_basic_expr (awk, ident);
xp_free (ident); xp_free (ident);
return x; // TODO: anything to clearn when x is XP_NULL???? }
else {
/* the expression starts with a non-identifier */
// TODO: maybe this should be an error ->>> just an expression without assignment */
x = __parse_basic_expr (awk, XP_NULL);
} }
// TODO: maybe this shoudl be an error ->>> just an expression without assignment */ return x;
return __parse_basic_expr (awk, XP_NULL);
} }
static xp_awk_node_t* __parse_assignment (xp_awk_t* awk, xp_char_t* ident) static xp_awk_node_t* __parse_assignment (xp_awk_t* awk, xp_char_t* ident)
@ -535,20 +475,20 @@ static xp_awk_node_t* __parse_additive (xp_awk_t* awk, xp_char_t* ident)
else break; else break;
if (__get_token(awk) == -1) { if (__get_token(awk) == -1) {
// TODO: cleanup left... xp_awk_clrpt (left);
return XP_NULL; return XP_NULL;
} }
right = __parse_multiplicative (awk, XP_NULL); right = __parse_multiplicative (awk, XP_NULL);
if (right == XP_NULL) { if (right == XP_NULL) {
// TOOD: cleanup left if necessary xp_awk_clrpt (left);
return XP_NULL; return XP_NULL;
} }
node = (xp_awk_node_expr_t*)xp_malloc(xp_sizeof(xp_awk_node_expr_t)); node = (xp_awk_node_expr_t*)xp_malloc(xp_sizeof(xp_awk_node_expr_t));
if (node == XP_NULL) { if (node == XP_NULL) {
// TODO: cleanup previous tmp (maybe current left) if necessary xp_awk_clrpt (right);
// TOOD: cleanup left if necessary xp_awk_clrpt (left);
PANIC (awk, XP_AWK_ENOMEM); PANIC (awk, XP_AWK_ENOMEM);
} }
@ -579,17 +519,21 @@ static xp_awk_node_t* __parse_multiplicative (xp_awk_t* awk, xp_char_t* ident)
else if (MATCH(awk,TOKEN_MOD)) opcode = BINOP_MOD; else if (MATCH(awk,TOKEN_MOD)) opcode = BINOP_MOD;
else break; else break;
CONSUME (awk); if (__get_token(awk) == -1) {
xp_awk_clrpt (left);
return XP_NULL;
}
right = __parse_unary (awk, XP_NULL); right = __parse_unary (awk, XP_NULL);
if (right == XP_NULL) { if (right == XP_NULL) {
// TOOD: cleanup left if necessary xp_awk_clrpt (left);
return XP_NULL; return XP_NULL;
} }
node = (xp_awk_node_expr_t*)xp_malloc(xp_sizeof(xp_awk_node_expr_t)); node = (xp_awk_node_expr_t*)xp_malloc(xp_sizeof(xp_awk_node_expr_t));
if (node == XP_NULL) { if (node == XP_NULL) {
// TODO: cleanup previous tmp (maybe current left) if necessary xp_awk_clrpt (right);
// TOOD: cleanup left if necessary xp_awk_clrpt (left);
PANIC (awk, XP_AWK_ENOMEM); PANIC (awk, XP_AWK_ENOMEM);
} }
@ -622,7 +566,11 @@ static xp_awk_node_t* __parse_primary (xp_awk_t* awk, xp_char_t* ident)
else { else {
name = (xp_char_t*)xp_strdup(XP_STR_BUF(&awk->token.name)); name = (xp_char_t*)xp_strdup(XP_STR_BUF(&awk->token.name));
if (name == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); if (name == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
CONSUME (awk); // error handling... replace it by get_token...
if (__get_token(awk) == -1) {
xp_free (name);
return XP_NULL;
}
} }
if (MATCH(awk,TOKEN_LPAREN)) { if (MATCH(awk,TOKEN_LPAREN)) {
@ -663,7 +611,12 @@ static xp_awk_node_t* __parse_primary (xp_awk_t* awk, xp_char_t* ident)
PANIC (awk, XP_AWK_ENOMEM); PANIC (awk, XP_AWK_ENOMEM);
} }
CONSUME (awk); if (__get_token(awk) == -1) {
xp_free (node->value);
xp_free (node);
return XP_NULL;
}
return (xp_awk_node_t*)node; return (xp_awk_node_t*)node;
} }
else if (MATCH(awk,TOKEN_STRING)) { else if (MATCH(awk,TOKEN_STRING)) {
@ -680,21 +633,34 @@ static xp_awk_node_t* __parse_primary (xp_awk_t* awk, xp_char_t* ident)
PANIC (awk, XP_AWK_ENOMEM); PANIC (awk, XP_AWK_ENOMEM);
} }
CONSUME (awk); if (__get_token(awk) == -1) {
xp_free (node->value);
xp_free (node);
return XP_NULL;
}
return (xp_awk_node_t*)node; return (xp_awk_node_t*)node;
} }
else if (MATCH(awk,TOKEN_LPAREN)) { else if (MATCH(awk,TOKEN_LPAREN)) {
xp_awk_node_t* node; xp_awk_node_t* node;
CONSUME (awk); /* eat up the left parenthesis */
node = __parse_expr (awk); if (__get_token(awk) == -1) return XP_NULL;
/* parse the sub-expression inside the parentheses */
node = __parse_expression (awk);
if (node == XP_NULL) return XP_NULL; if (node == XP_NULL) return XP_NULL;
/* check for the closing parenthesis */
if (!MATCH(awk,TOKEN_RPAREN)) { if (!MATCH(awk,TOKEN_RPAREN)) {
// TODO: free tmp... xp_awk_clrpt (node);
PANIC (awk, XP_AWK_ERPAREN); PANIC (awk, XP_AWK_ERPAREN);
} }
CONSUME (awk);
if (__get_token(awk) == -1) {
xp_awk_clrpt (node);
return XP_NULL;
}
return node; return node;
} }
@ -705,9 +671,12 @@ static xp_awk_node_t* __parse_primary (xp_awk_t* awk, xp_char_t* ident)
static xp_awk_node_t* __parse_funcall (xp_awk_t* awk, xp_char_t* name) static xp_awk_node_t* __parse_funcall (xp_awk_t* awk, xp_char_t* name)
{ {
xp_awk_node_t* head, * curr, * tmp;
xp_awk_node_call_t* node; xp_awk_node_call_t* node;
xp_awk_node_t* tmp, * cur;
if (__get_token(awk) == -1) return XP_NULL;
if (MATCH(awk,TOKEN_RPAREN)) {
node = (xp_awk_node_call_t*)xp_malloc (xp_sizeof(xp_awk_node_call_t)); node = (xp_awk_node_call_t*)xp_malloc (xp_sizeof(xp_awk_node_call_t));
if (node == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); if (node == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
@ -716,27 +685,28 @@ static xp_awk_node_t* __parse_funcall (xp_awk_t* awk, xp_char_t* name)
node->name = name; node->name = name;
node->args = XP_NULL; node->args = XP_NULL;
CONSUME (awk); if (__get_token(awk) == -1) return XP_NULL;
if (MATCH(awk,TOKEN_RPAREN)) {
CONSUME (awk);
return (xp_awk_node_t*)node; return (xp_awk_node_t*)node;
} }
cur = XP_NULL; head = curr = XP_NULL;
while (1) { while (1) {
tmp = __parse_expr (awk); tmp = __parse_expression (awk);
if (tmp == XP_NULL) { if (tmp == XP_NULL) {
// TODO: free all other nodes associated into node->args if (cur != XP_NULL) xp_awk_clrpt (cur);
xp_free (node); xp_free (node);
return XP_NULL; return XP_NULL;
} }
if (cur == XP_NULL) node->args = tmp; if (head == XP_NULL) head = tmp;
else cur->next = tmp; else curr->next = tmp;
cur = tmp; curr = tmp;
if (MATCH(awk,TOKEN_RPAREN)) { if (MATCH(awk,TOKEN_RPAREN)) {
CONSUME (awk); if (__get_token(awk) == -1) {
// TODO cleanup.
return XP_NULL;
}
break; break;
} }
@ -746,8 +716,19 @@ static xp_awk_node_t* __parse_funcall (xp_awk_t* awk, xp_char_t* name)
PANIC (awk, XP_AWK_ECOMMA); PANIC (awk, XP_AWK_ECOMMA);
} }
CONSUME (awk); if (__get_token(awk) == -1) {
// TODO cleanup.
return XP_NULL;
} }
}
node = (xp_awk_node_call_t*)xp_malloc (xp_sizeof(xp_awk_node_call_t));
if (node == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
node->type = XP_AWK_NODE_CALL;
node->next = XP_NULL;
node->name = name;
node->args = head;
return (xp_awk_node_t*)node; return (xp_awk_node_t*)node;
} }
@ -781,7 +762,6 @@ static xp_awk_node_t* __parse_break (xp_awk_t* awk)
node->type = XP_AWK_NODE_BREAK; node->type = XP_AWK_NODE_BREAK;
node->next = XP_NULL; node->next = XP_NULL;
/* TODO: do i have to consume a semicolon here???? */
return node; return node;
} }
@ -794,10 +774,49 @@ static xp_awk_node_t* __parse_continue (xp_awk_t* awk)
node->type = XP_AWK_NODE_CONTINUE; node->type = XP_AWK_NODE_CONTINUE;
node->next = XP_NULL; node->next = XP_NULL;
/* TODO: do i have to consume a semicolon here???? */
return node; return node;
} }
static xp_awk_node_t* __parse_return (xp_awk_t* awk)
{
xp_awk_node_block_t* node;
xp_awk_node_t* val;
node = (xp_awk_node_block_t*) xp_malloc (xp_sizeof(xp_awk_node_block_t));
if (node == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
node->type = XP_AWK_NODE_RETURN;
node->next = XP_NULL;
val = __parse_expression (awk);
if (val == XP_NULL) {
xp_free (node);
return XP_NULL;
}
node->body = val;
return (xp_awk_node_t*)node;
}
static xp_awk_node_t* __parse_exit (xp_awk_t* awk)
{
xp_awk_node_block_t* node;
xp_awk_node_t* val;
node = (xp_awk_node_block_t*) xp_malloc (xp_sizeof(xp_awk_node_block_t));
if (node == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
node->type = XP_AWK_NODE_EXIT;
node->next = XP_NULL;
val = __parse_expression (awk);
if (val == XP_NULL) {
xp_free (node);
return XP_NULL;
}
node->body = val;
return (xp_awk_node_t*)node;
}
static int __get_token (xp_awk_t* awk) static int __get_token (xp_awk_t* awk)
{ {
xp_cint_t c; xp_cint_t c;

226
ase/awk/tree.c Normal file
View File

@ -0,0 +1,226 @@
/*
* $Id: tree.c,v 1.1 2006-01-14 14:09:52 bacon Exp $
*/
#include <xp/awk/awk.h>
#include <xp/bas/memory.h>
#include <xp/bas/assert.h>
#include <xp/bas/stdio.h>
static xp_char_t __binop_char[] =
{
XP_CHAR('+'),
XP_CHAR('-'),
XP_CHAR('*'),
XP_CHAR('/'),
XP_CHAR('%')
};
static void __print_tabs (int depth);
static int __print_expr_node (xp_awk_node_t* node);
static int __print_expr_node_list (xp_awk_node_t* tree);
static void __print_statements (xp_awk_node_t* tree, int depth);
static void __print_tabs (int depth)
{
int i;
for (i = 0; i < depth; i++) xp_printf (XP_TEXT("\t"));
}
static int __print_expr_node (xp_awk_node_t* node)
{
switch (node->type) {
case XP_AWK_NODE_ASSIGN:
xp_printf (XP_TEXT("%s = "), ((xp_awk_node_assign_t*)node)->left);
if (__print_expr_node (((xp_awk_node_assign_t*)node)->right) == -1) return -1;
xp_assert ((((xp_awk_node_assign_t*)node)->right)->next == XP_NULL);
break;
case XP_AWK_NODE_BINARY:
xp_printf (XP_TEXT("("));
if (__print_expr_node (((xp_awk_node_expr_t*)node)->left) == -1) return -1;
xp_assert ((((xp_awk_node_expr_t*)node)->left)->next == XP_NULL);
xp_printf (XP_TEXT(" %c "), __binop_char[((xp_awk_node_expr_t*)node)->opcode]);
if (__print_expr_node (((xp_awk_node_expr_t*)node)->right) == -1) return -1;
xp_assert ((((xp_awk_node_expr_t*)node)->right)->next == XP_NULL);
xp_printf (XP_TEXT(")"));
break;
case XP_AWK_NODE_UNARY:
// TODO:
xp_printf (XP_TEXT("unary basic expression\n"));
break;
case XP_AWK_NODE_STR:
xp_printf (XP_TEXT("\"%s\""), ((xp_awk_node_term_t*)node)->value);
break;
case XP_AWK_NODE_NUM:
xp_printf (XP_TEXT("%s"), ((xp_awk_node_term_t*)node)->value);
break;
case XP_AWK_NODE_VAR:
xp_printf (XP_TEXT("%s"), ((xp_awk_node_term_t*)node)->value);
break;
case XP_AWK_NODE_CALL:
xp_printf (XP_TEXT("%s ("), ((xp_awk_node_call_t*)node)->name);
if (__print_expr_node_list (((xp_awk_node_call_t*)node)->args) == -1) return -1;
xp_printf (XP_TEXT(")"));
break;
default:
return -1;
}
return 0;
}
static int __print_expr_node_list (xp_awk_node_t* tree)
{
xp_awk_node_t* p = tree;
while (p != XP_NULL) {
if (__print_expr_node (p) == -1) return -1;
p = p->next;
if (p != XP_NULL) xp_printf (XP_TEXT(","));
}
return 0;
}
static void __print_statements (xp_awk_node_t* tree, int depth)
{
xp_awk_node_t* p = tree;
while (p != XP_NULL) {
switch (p->type) {
case XP_AWK_NODE_BLOCK:
__print_tabs (depth);
xp_printf (XP_TEXT("{\n"));
__print_statements (((xp_awk_node_block_t*)p)->body, depth + 1);
__print_tabs (depth);
xp_printf (XP_TEXT("}\n"));
break;
case XP_AWK_NODE_BREAK:
__print_tabs (depth);
xp_printf (XP_TEXT("break;\n"));
break;
case XP_AWK_NODE_CONTINUE:
__print_tabs (depth);
xp_printf (XP_TEXT("continue;\n"));
break;
case XP_AWK_NODE_RETURN:
__print_tabs (depth);
xp_printf (XP_TEXT("return "));
xp_assert (((xp_awk_node_block_t*)p)->body->next == XP_NULL);
if (__print_expr_node(((xp_awk_node_block_t*)p)->body) == 0) {
xp_printf (XP_TEXT(";\n"));
}
else {
xp_awk_node_block_t* x = (xp_awk_node_block_t*)p;
xp_printf (XP_TEXT("***INTERNAL ERROR: unknown node type - %d\n"), x->type);
}
break;
case XP_AWK_NODE_EXIT:
__print_tabs (depth);
xp_printf (XP_TEXT("exit "));
xp_assert (((xp_awk_node_block_t*)p)->body->next == XP_NULL);
if (__print_expr_node(((xp_awk_node_block_t*)p)->body) == 0) {
xp_printf (XP_TEXT(";\n"));
}
else {
xp_awk_node_block_t* x = (xp_awk_node_block_t*)p;
xp_printf (XP_TEXT("***INTERNAL ERROR: unknown node type - %d\n"), x->type);
}
break;
default:
__print_tabs (depth);
if (__print_expr_node(p) == 0) {
xp_printf (XP_TEXT(";\n"));
}
else {
xp_printf (XP_TEXT("***INTERNAL ERROR: unknown type - %d\n"), p->type);
}
}
p = p->next;
}
}
void xp_awk_prnpt (xp_awk_node_t* tree)
{
__print_statements (tree, 0);
}
void xp_awk_clrpt (xp_awk_node_t* tree)
{
xp_awk_node_t* p = tree;
xp_awk_node_t* next;
while (p != XP_NULL) {
next = p->next;
switch (p->type) {
case XP_AWK_NODE_BLOCK:
xp_awk_clrpt (((xp_awk_node_block_t*)p)->body);
xp_free (p);
break;
case XP_AWK_NODE_BREAK:
case XP_AWK_NODE_CONTINUE:
xp_free (p);
break;
case XP_AWK_NODE_RETURN:
case XP_AWK_NODE_EXIT:
xp_awk_clrpt (((xp_awk_node_block_t*)p)->body);
xp_free (p);
break;
case XP_AWK_NODE_ASSIGN:
xp_free (((xp_awk_node_assign_t*)p)->left);
xp_awk_clrpt (((xp_awk_node_assign_t*)p)->right);
xp_free (p);
break;
case XP_AWK_NODE_BINARY:
xp_assert ((((xp_awk_node_expr_t*)p)->left)->next == XP_NULL);
xp_assert ((((xp_awk_node_expr_t*)p)->right)->next == XP_NULL);
xp_awk_clrpt (((xp_awk_node_expr_t*)p)->left);
xp_awk_clrpt (((xp_awk_node_expr_t*)p)->right);
xp_free (p);
break;
case XP_AWK_NODE_UNARY:
// TODO: clear unary expression...
xp_free (p);
break;
case XP_AWK_NODE_STR:
case XP_AWK_NODE_NUM:
case XP_AWK_NODE_VAR:
xp_free (((xp_awk_node_term_t*)p)->value);
xp_free (p);
break;
case XP_AWK_NODE_CALL:
xp_free (((xp_awk_node_call_t*)p)->name);
xp_awk_clrpt (((xp_awk_node_call_t*)p)->args);
xp_free (p);
break;
default:
xp_assert (XP_TEXT("shoud not happen") == XP_TEXT(" here"));
}
p = next;
}
}

View File

@ -1,5 +1,5 @@
/* /*
* $Id: tree.h,v 1.7 2006-01-13 14:16:56 bacon Exp $ * $Id: tree.h,v 1.8 2006-01-14 14:08:58 bacon Exp $
*/ */
#ifndef _XP_AWK_TREE_H_ #ifndef _XP_AWK_TREE_H_
@ -10,6 +10,8 @@ enum
XP_AWK_NODE_BLOCK, XP_AWK_NODE_BLOCK,
XP_AWK_NODE_BREAK, XP_AWK_NODE_BREAK,
XP_AWK_NODE_CONTINUE, XP_AWK_NODE_CONTINUE,
XP_AWK_NODE_RETURN,
XP_AWK_NODE_EXIT,
XP_AWK_NODE_ASSIGN, XP_AWK_NODE_ASSIGN,
XP_AWK_NODE_BINARY, XP_AWK_NODE_BINARY,
XP_AWK_NODE_UNARY, XP_AWK_NODE_UNARY,
@ -94,4 +96,15 @@ struct xp_awk_node_do_t
xp_awk_node_t* test; xp_awk_node_t* test;
}; };
#ifdef __cplusplus
extern "C" {
#endif
void xp_awk_prnpt (xp_awk_node_t* tree);
void xp_awk_clrpt (xp_awk_node_t* tree);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@ -50,8 +50,8 @@ int xp_main (int argc, xp_char_t* argv[])
return -1; return -1;
} }
xp_printf (XP_TEXT("-----------------------------------------------\n")); xp_printf (XP_TEXT("-----------------------------------------------\n"));
print_parse_tree (awk.tree); xp_awk_prnpt (awk.tree);
xp_awk_close (&awk); xp_awk_close (&awk);
return 0; return 0;