*** empty log message ***
This commit is contained in:
parent
4b2bfa9257
commit
35990d18e5
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user