*** empty log message ***
This commit is contained in:
		| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: awk.c,v 1.5 2005-12-29 12:04:51 bacon Exp $ | ||||
|  * $Id: awk.c,v 1.6 2006-01-09 12:51:46 bacon Exp $ | ||||
|  */ | ||||
|  | ||||
| #include <xp/awk/awk.h> | ||||
| @ -20,6 +20,7 @@ xp_awk_t* xp_awk_open (xp_awk_t* awk) | ||||
| 		return XP_NULL; | ||||
| 	} | ||||
|  | ||||
| 	awk->tree = XP_NULL; | ||||
| 	awk->errnum = XP_AWK_ENOERR; | ||||
|  | ||||
| 	awk->src_func = XP_NULL; | ||||
| @ -38,6 +39,10 @@ xp_awk_t* xp_awk_open (xp_awk_t* awk) | ||||
|  | ||||
| int xp_awk_close (xp_awk_t* awk) | ||||
| { | ||||
| 	/* TODO: collapse the tree */ | ||||
|  | ||||
| 	if (awk->tree != XP_NULL) __collapse_tree (awk->tree); | ||||
|  | ||||
| 	if (xp_awk_detsrc(awk) == -1) return -1; | ||||
| 	xp_str_close (&awk->token.name); | ||||
| 	if (awk->__dynamic) xp_free (awk); | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /*  | ||||
|  * $Id: awk.h,v 1.6 2005-12-29 12:04:51 bacon Exp $ | ||||
|  * $Id: awk.h,v 1.7 2006-01-09 12:51:47 bacon Exp $ | ||||
|  */ | ||||
|  | ||||
| #ifndef _XP_AWK_AWK_H_ | ||||
| @ -8,6 +8,7 @@ | ||||
| #include <xp/types.h> | ||||
| #include <xp/macros.h> | ||||
| #include <xp/bas/str.h> | ||||
| #include <xp/awk/tree.h> | ||||
|  | ||||
| enum | ||||
| { | ||||
| @ -16,8 +17,11 @@ enum | ||||
| 	XP_AWK_ESRCOP, | ||||
| 	XP_AWK_ESRCCL, | ||||
| 	XP_AWK_ESRCDT, /* error in reading source */ | ||||
|  | ||||
| 	XP_AWK_ELXCHR, /* lexer came accross an wrong character */ | ||||
| 	XP_AWK_ELXUNG  /* lexer failed to unget a character */ | ||||
| 	XP_AWK_ELXUNG, /* lexer failed to unget a character */ | ||||
|  | ||||
| 	XP_AWK_ELBRACE /* left brace expected */ | ||||
| }; | ||||
|  | ||||
| /* | ||||
| @ -40,6 +44,9 @@ enum | ||||
|  | ||||
| struct xp_awk_t | ||||
| { | ||||
| 	/* parse tree */ | ||||
| 	xp_awk_node_t* tree; | ||||
|  | ||||
| 	/* io functions */ | ||||
| 	xp_awk_io_t src_func; | ||||
| 	xp_awk_io_t inp_func; | ||||
|  | ||||
							
								
								
									
										212
									
								
								ase/awk/parse.c
									
									
									
									
									
								
							
							
						
						
									
										212
									
								
								ase/awk/parse.c
									
									
									
									
									
								
							| @ -1,8 +1,10 @@ | ||||
| /* | ||||
|  * $Id: parse.c,v 1.9 2005-12-29 12:04:51 bacon Exp $ | ||||
|  * $Id: parse.c,v 1.10 2006-01-09 12:51:47 bacon Exp $ | ||||
|  */ | ||||
|  | ||||
| #include <xp/awk/awk.h> | ||||
| #include <xp/awk/tree.h> | ||||
| #include <xp/awk/tree.h> | ||||
| #include <xp/bas/memory.h> | ||||
| #include <xp/bas/ctype.h> | ||||
| #include <xp/bas/string.h> | ||||
| @ -26,8 +28,8 @@ enum | ||||
| 	TOKEN_RPAREN, | ||||
| 	TOKEN_LBRACE, | ||||
| 	TOKEN_RBRACE, | ||||
| 	TOKEN_LBRAKET, | ||||
| 	TOKEN_RBRAKET, | ||||
| 	TOKEN_LBRACKET, | ||||
| 	TOKEN_RBRACKET, | ||||
|  | ||||
| 	TOKEN_STRING, | ||||
| 	TOKEN_REGEX, | ||||
| @ -37,15 +39,29 @@ enum | ||||
| 	TOKEN_END, | ||||
| 	TOKEN_FUNCTION, | ||||
| 	TOKEN_IF, | ||||
| 	TOKEN_DO, | ||||
| 	TOKEN_WHILE, | ||||
| 	TOKEN_FOR, | ||||
| 	TOKEN_DO, | ||||
| 	TOKEN_BREAK, | ||||
| 	TOKEN_CONTINUE, | ||||
| 	TOKEN_BREAK | ||||
| 	TOKEN_RETURN, | ||||
| 	TOKEN_EXIT, | ||||
| 	TOKEN_DELETE, | ||||
| 	TOKEN_NEXT, | ||||
| 	TOKEN_NEXTFILE | ||||
| }; | ||||
|  | ||||
| static int __parse (xp_awk_t* awk); | ||||
| static int __parse_program (xp_awk_t* awk); | ||||
|  | ||||
| static xp_awk_node_t* __parse_program (xp_awk_t* awk); | ||||
| static xp_awk_node_t* __parse_block (xp_awk_t* awk); | ||||
| static xp_awk_node_t* __parse_if (xp_awk_t* awk); | ||||
| static xp_awk_node_t* __parse_while (xp_awk_t* awk); | ||||
| 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_break (xp_awk_t* awk); | ||||
| static xp_awk_node_t* __parse_continue (xp_awk_t* awk); | ||||
|  | ||||
| static int __get_token (xp_awk_t* awk); | ||||
| static int __get_char (xp_awk_t* awk); | ||||
| static int __unget_char (xp_awk_t* awk, xp_cint_t c); | ||||
| @ -65,11 +81,16 @@ static struct __kwent __kwtab[] = | ||||
| 	{ XP_TEXT("END"),      TOKEN_END }, | ||||
| 	{ XP_TEXT("function"), TOKEN_FUNCTION }, | ||||
| 	{ XP_TEXT("if"),       TOKEN_IF }, | ||||
| 	{ XP_TEXT("do"),       TOKEN_DO }, | ||||
| 	{ XP_TEXT("while"),    TOKEN_WHILE }, | ||||
| 	{ XP_TEXT("for"),      TOKEN_FOR }, | ||||
| 	{ XP_TEXT("continue"), TOKEN_CONTINUE }, | ||||
| 	{ XP_TEXT("do"),       TOKEN_DO }, | ||||
| 	{ XP_TEXT("break"),    TOKEN_BREAK }, | ||||
| 	{ XP_TEXT("continue"), TOKEN_CONTINUE }, | ||||
| 	{ XP_TEXT("return"),   TOKEN_RETURN }, | ||||
| 	{ XP_TEXT("exit"),     TOKEN_EXIT }, | ||||
| 	{ XP_TEXT("delete"),   TOKEN_DELETE }, | ||||
| 	{ XP_TEXT("next"),     TOKEN_NEXT }, | ||||
| 	{ XP_TEXT("nextfile"), TOKEN_NEXTFILE }, | ||||
| 	{ XP_NULL,             0 }, | ||||
| }; | ||||
|  | ||||
| @ -98,20 +119,36 @@ static struct __kwent __kwtab[] = | ||||
| #define GET_TOKEN(awk) \ | ||||
| 	do { if (__get_token(awk) == -1) return -1; } while(0) | ||||
|  | ||||
| #define MATCH(awk,token_type) ((awk)->token.type == (token_type)) | ||||
| #define CONSUME(awk) \ | ||||
| 	do { if (__get_token(awk) == -1) return XP_NULL; } while(0) | ||||
|  | ||||
| #define PANIC(awk,code) do { (awk)->errnum = (code);  return XP_NULL; } while (0); | ||||
|  | ||||
| int xp_awk_parse (xp_awk_t* awk) | ||||
| { | ||||
| 	xp_awk_node_t* node; | ||||
|  | ||||
| 	GET_CHAR (awk); | ||||
| 	GET_TOKEN (awk); | ||||
| 	return __parse_program (awk); | ||||
|  | ||||
| 	node = __parse_program(awk); | ||||
| 	if (node == XP_NULL) return -1; | ||||
|  | ||||
| 	awk->tree = node; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int __parse_program (xp_awk_t* awk) | ||||
| static xp_awk_node_t* __parse_program (xp_awk_t* awk) | ||||
| { | ||||
| 	/* | ||||
| 	pattern { action } | ||||
| 	function name (parameter-list) { statement } | ||||
| 	*/ | ||||
|  | ||||
| 	xp_awk_node_t* node; | ||||
|  | ||||
| 	/* | ||||
| 	while (1) { | ||||
| 		if (awk->token.type == TOKEN_FUNCTION) { | ||||
| 			if (__parse_function_declaration(awk) == -1) return -1; | ||||
| @ -120,16 +157,18 @@ static int __parse_program (xp_awk_t* awk) | ||||
| 			if (__parse_pattern_action(awk) == -1) return -1; | ||||
| 		} | ||||
| 	} | ||||
| 	*/ | ||||
|  | ||||
| 	return 0; | ||||
| 	return node; | ||||
| } | ||||
|  | ||||
| static int __parse_function_declaration (xp_awk_t* awk) | ||||
|  | ||||
| static xp_awk_node_t* __parse_function_declaration (xp_awk_t* awk) | ||||
| { | ||||
| 	return -1; | ||||
| 	return XP_NULL; | ||||
| } | ||||
|  | ||||
| static int __parse_pattern_action (xp_awk_t* awk) | ||||
| static xp_awk_node_t* __parse_pattern_action (xp_awk_t* awk) | ||||
| { | ||||
| 	/*  | ||||
| 	BEGIN | ||||
| @ -143,12 +182,147 @@ static int __parse_pattern_action (xp_awk_t* awk) | ||||
| 	pattern, pattern | ||||
| 	*/ | ||||
|  | ||||
| 	if (awk->token.type == TOKEN_BEGIN) { | ||||
| 	xp_awk_node_t* node; | ||||
|  | ||||
| 	if (MATCH(awk,TOKEN_BEGIN)) { | ||||
| 		CONSUME (awk); | ||||
| 	} | ||||
| 	else if (awk->token.type == TOKEN_END) { | ||||
| 	else if (MATCH(awk,TOKEN_END)) { | ||||
| 		CONSUME (awk); | ||||
| 	} | ||||
| 	/* patterns ... | ||||
| 	 * etc */ | ||||
|  | ||||
| 	if (!MATCH(awk,TOKEN_LBRACE))  { | ||||
| 		PANIC (awk, XP_AWK_ELBRACE); | ||||
| 	} | ||||
|  | ||||
| 	return -1; | ||||
| 	CONSUME (awk); | ||||
| 	node = __parse_block(awk); | ||||
| 	if (node == XP_NULL) return XP_NULL; | ||||
|  | ||||
| 	return node; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* 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_awk_node_block_t* node; | ||||
|  | ||||
| 	node = (xp_awk_node_block_t*) xp_malloc (xp_sizeof(xp_awk_node_block_t)); | ||||
| 	if (node == XP_NULL) { | ||||
| 		/* TODO: do some clean-up */ | ||||
| 		PANIC (awk, XP_AWK_ENOMEM); | ||||
| 	} | ||||
|  | ||||
| 	node->type = XP_AWK_NODE_BLOCK; | ||||
| 	node->sbls = XP_NULL; | ||||
| 	node->body = XP_NULL; | ||||
|  | ||||
| 	while (1) { | ||||
| 		if (MATCH(awk,TOKEN_RBRACE)) { | ||||
| 			/* TODO: should finalize a block */ | ||||
| 			CONSUME (awk); | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		if (MATCH(awk,TOKEN_LBRACE)) { | ||||
| 			/* nested block */ | ||||
| 			CONSUME (awk); | ||||
| 			if (__parse_block(awk) == XP_NULL) return XP_NULL; | ||||
| 		} | ||||
| 		else if (MATCH(awk,TOKEN_IF)) { | ||||
| 			CONSUME (awk); | ||||
| 			if (__parse_if(awk) == XP_NULL) return XP_NULL; | ||||
| 		} | ||||
| 		else if (MATCH(awk,TOKEN_WHILE)) { | ||||
| 			CONSUME (awk); | ||||
| 			if (__parse_while(awk) == XP_NULL) return XP_NULL; | ||||
| 		} | ||||
| 		else if (MATCH(awk,TOKEN_FOR)) { | ||||
| 			CONSUME (awk); | ||||
| 			if (__parse_for(awk) == XP_NULL) return XP_NULL; | ||||
| 		} | ||||
| 		else if (MATCH(awk,TOKEN_DO)) { | ||||
| 			CONSUME (awk); | ||||
| 			if (__parse_do(awk) == XP_NULL) return XP_NULL; | ||||
| 		} | ||||
| 		else if (MATCH(awk,TOKEN_BREAK)) { | ||||
| 			CONSUME (awk); | ||||
| 			node->body = __parse_break(awk); | ||||
| 		} | ||||
| 		else if (MATCH(awk,TOKEN_CONTINUE)) { | ||||
| 			CONSUME (awk); | ||||
| 			node->body = __parse_continue(awk); | ||||
| 		} | ||||
| 		else if (MATCH(awk,TOKEN_RETURN)) { | ||||
| 			CONSUME (awk); | ||||
| 			/* TOOD: */ | ||||
| 		} | ||||
| 		else if (MATCH(awk, TOKEN_EXIT)) { | ||||
| 			CONSUME (awk); | ||||
| 			/* TOOD: */ | ||||
| 		} | ||||
| 		else if (MATCH(awk, TOKEN_DELETE)) { | ||||
| 			CONSUME (awk); | ||||
| 			/* TOOD: */ | ||||
| 		} | ||||
| 		else if (MATCH(awk, TOKEN_NEXT)) { | ||||
| 			CONSUME (awk); | ||||
| 			/* TOOD: */ | ||||
| 		} | ||||
| 		else if (MATCH(awk, TOKEN_NEXTFILE)) { | ||||
| 			CONSUME (awk); | ||||
| 			/* TOOD: */ | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static xp_awk_node_t* __parse_if (xp_awk_t* awk) | ||||
| { | ||||
| 	return XP_NULL; | ||||
| } | ||||
|  | ||||
| static xp_awk_node_t* __parse_while (xp_awk_t* awk) | ||||
| { | ||||
| 	return XP_NULL; | ||||
| } | ||||
|  | ||||
| static xp_awk_node_t* __parse_for (xp_awk_t* awk) | ||||
| { | ||||
| 	return XP_NULL; | ||||
| } | ||||
|  | ||||
| static xp_awk_node_t* __parse_do (xp_awk_t* awk) | ||||
| { | ||||
| 	return XP_NULL; | ||||
| } | ||||
|  | ||||
| static xp_awk_node_t* __parse_break (xp_awk_t* awk) | ||||
| { | ||||
| 	xp_awk_node_t* node; | ||||
|  | ||||
| 	node = (xp_awk_node_t*) xp_malloc (xp_sizeof(xp_awk_node_t)); | ||||
| 	if (node == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); | ||||
| 	node->type = XP_AWK_NODE_BREAK; | ||||
| 	 | ||||
| 	/* TODO: do i have to consume a semicolon here???? */ | ||||
| 	return node; | ||||
| } | ||||
|  | ||||
| static xp_awk_node_t* __parse_continue (xp_awk_t* awk) | ||||
| { | ||||
| 	xp_awk_node_t* node; | ||||
|  | ||||
| 	node = (xp_awk_node_t*) xp_malloc (xp_sizeof(xp_awk_node_t)); | ||||
| 	if (node == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); | ||||
| 	node->type = XP_AWK_NODE_CONTINUE; | ||||
| 	 | ||||
| 	/* TODO: do i have to consume a semicolon here???? */ | ||||
| 	return node; | ||||
| } | ||||
|  | ||||
| static int __get_token (xp_awk_t* awk) | ||||
| @ -266,11 +440,11 @@ static int __get_token (xp_awk_t* awk) | ||||
| 		ADD_TOKEN_CHAR (awk, c); | ||||
| 	} | ||||
| 	else if (c == XP_CHAR('[')) { | ||||
| 		SET_TOKEN_TYPE (awk, TOKEN_LBRAKET); | ||||
| 		SET_TOKEN_TYPE (awk, TOKEN_LBRACKET); | ||||
| 		ADD_TOKEN_CHAR (awk, c); | ||||
| 	} | ||||
| 	else if (c == XP_CHAR(']')) { | ||||
| 		SET_TOKEN_TYPE (awk, TOKEN_RBRAKET); | ||||
| 		SET_TOKEN_TYPE (awk, TOKEN_RBRACKET); | ||||
| 		ADD_TOKEN_CHAR (awk, c); | ||||
| 	} | ||||
| 	else { | ||||
|  | ||||
| @ -1,7 +1,14 @@ | ||||
| /* | ||||
|  * $Id: tree.h,v 1.2 2006-01-09 12:51:47 bacon Exp $ | ||||
|  */ | ||||
|  | ||||
| #ifndef _XP_AWK_TREE_H_ | ||||
| #define _XP_AWK_TREE_H_ | ||||
|  | ||||
| /* | ||||
| enum TokenType | ||||
| { | ||||
| 	IF, END, ID, NUM, READ, WrITE, UNTIL, .... | ||||
| 	IF, END, ID, NUM, READ, WRITE, UNTIL, .... | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -30,3 +37,53 @@ struct treenode | ||||
|  | ||||
| 	exptype type; <- for type checking... | ||||
| }; | ||||
|  | ||||
| struct node_t | ||||
| { | ||||
| 	int type; | ||||
|  | ||||
| }; | ||||
| */ | ||||
|  | ||||
| enum | ||||
| { | ||||
| 	XP_AWK_NODE_BLOCK, | ||||
| 	XP_AWK_NODE_BREAK, | ||||
| 	XP_AWK_NODE_CONTINUE | ||||
| }; | ||||
|  | ||||
| typedef struct xp_awk_node_t xp_awk_node_t; | ||||
| typedef struct xp_awk_node_block_t xp_awk_node_block_t; | ||||
| typedef struct xp_awk_node_if_t xp_awk_node_if_t; | ||||
|  | ||||
| #define XP_AWK_NODE_HDR \ | ||||
| 	int type; \ | ||||
| 	xp_awk_node_t* sbls | ||||
|  | ||||
| struct xp_awk_node_t | ||||
| { | ||||
| 	XP_AWK_NODE_HDR; | ||||
| }; | ||||
|  | ||||
| /* | ||||
| struct xp_awk_node_plain_t | ||||
| { | ||||
| 	XP_AWK_NODE_HDR; | ||||
| }; | ||||
| */ | ||||
|  | ||||
| struct xp_awk_node_block_t | ||||
| { | ||||
| 	XP_AWK_NODE_HDR; | ||||
| 	xp_awk_node_t* body; | ||||
| }; | ||||
|  | ||||
| struct xp_awk_node_if_t | ||||
| { | ||||
| 	XP_AWK_NODE_HDR; | ||||
| 	xp_awk_node_t* cond; | ||||
| 	xp_awk_node_t* if_part; | ||||
| 	xp_awk_node_t* else_part; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|  | ||||
		Reference in New Issue
	
	Block a user