qse/ase/awk/parse.c

2903 lines
59 KiB
C
Raw Normal View History

2005-11-06 12:01:29 +00:00
/*
2006-04-16 16:30:59 +00:00
* $Id: parse.c,v 1.83 2006-04-16 16:30:59 bacon Exp $
2005-11-06 12:01:29 +00:00
*/
2006-03-31 16:35:37 +00:00
#include <xp/awk/awk_i.h>
2006-01-18 15:16:01 +00:00
2006-04-16 04:31:38 +00:00
#ifndef XP_AWK_STAND_ALONE
2005-11-14 15:23:54 +00:00
#include <xp/bas/memory.h>
#include <xp/bas/ctype.h>
2005-12-29 12:04:51 +00:00
#include <xp/bas/string.h>
2006-03-27 11:43:17 +00:00
#include <xp/bas/stdlib.h>
2006-01-11 11:52:17 +00:00
#include <xp/bas/assert.h>
2006-01-18 15:16:01 +00:00
#endif
2005-11-06 12:01:29 +00:00
2005-11-14 15:23:54 +00:00
enum
{
TOKEN_EOF,
2005-11-15 15:32:39 +00:00
2005-11-14 15:23:54 +00:00
TOKEN_ASSIGN,
2006-04-11 15:44:30 +00:00
TOKEN_PLUS_ASSIGN,
TOKEN_MINUS_ASSIGN,
TOKEN_MUL_ASSIGN,
TOKEN_DIV_ASSIGN,
TOKEN_MOD_ASSIGN,
TOKEN_EXP_ASSIGN,
2005-11-14 15:23:54 +00:00
TOKEN_EQ,
TOKEN_NE,
2006-02-08 16:14:31 +00:00
TOKEN_LE,
TOKEN_LT,
TOKEN_GE,
TOKEN_GT,
2006-04-11 15:44:30 +00:00
TOKEN_NM, /* not match */
2005-11-14 15:23:54 +00:00
TOKEN_NOT,
TOKEN_PLUS,
2006-03-31 12:04:14 +00:00
TOKEN_PLUSPLUS,
2005-11-14 15:23:54 +00:00
TOKEN_MINUS,
2006-03-31 12:04:14 +00:00
TOKEN_MINUSMINUS,
2006-01-10 13:57:54 +00:00
TOKEN_MUL,
TOKEN_DIV,
TOKEN_MOD,
2006-03-29 16:39:04 +00:00
TOKEN_LOR,
TOKEN_LAND,
TOKEN_BOR,
2006-03-30 16:24:10 +00:00
TOKEN_BXOR,
2006-03-29 16:39:04 +00:00
TOKEN_BAND,
2006-04-12 03:54:12 +00:00
TOKEN_TILDE, /* used for unary bitwise-not and regex match */
2006-04-11 15:44:30 +00:00
TOKEN_RSHIFT,
TOKEN_LSHIFT,
TOKEN_EXP,
2005-11-14 15:23:54 +00:00
2005-11-15 15:32:39 +00:00
TOKEN_LPAREN,
TOKEN_RPAREN,
TOKEN_LBRACE,
TOKEN_RBRACE,
2006-01-19 16:28:21 +00:00
TOKEN_LBRACK,
TOKEN_RBRACK,
2005-11-15 15:32:39 +00:00
2006-01-25 14:50:57 +00:00
TOKEN_DOLLAR,
2006-01-13 14:16:56 +00:00
TOKEN_COMMA,
2006-04-16 04:31:38 +00:00
TOKEN_PERIOD,
2006-01-09 16:03:56 +00:00
TOKEN_SEMICOLON,
2006-04-10 15:52:07 +00:00
TOKEN_COLON,
TOKEN_QUEST,
2006-01-09 16:03:56 +00:00
2006-03-31 12:04:14 +00:00
TOKEN_INT,
TOKEN_REAL,
2006-04-07 04:23:11 +00:00
TOKEN_STR,
2005-11-15 15:59:23 +00:00
TOKEN_REGEX,
2005-11-14 15:23:54 +00:00
TOKEN_IDENT,
2005-12-29 12:04:51 +00:00
TOKEN_BEGIN,
2005-11-14 15:23:54 +00:00
TOKEN_END,
2005-11-16 16:09:53 +00:00
TOKEN_FUNCTION,
TOKEN_IF,
2006-01-14 16:09:58 +00:00
TOKEN_ELSE,
2005-11-16 16:09:53 +00:00
TOKEN_WHILE,
TOKEN_FOR,
2006-01-09 12:51:47 +00:00
TOKEN_DO,
TOKEN_BREAK,
2005-11-16 16:09:53 +00:00
TOKEN_CONTINUE,
2006-01-09 12:51:47 +00:00
TOKEN_RETURN,
TOKEN_EXIT,
TOKEN_DELETE,
TOKEN_NEXT,
2006-01-15 06:11:22 +00:00
TOKEN_NEXTFILE,
2006-01-25 16:11:43 +00:00
TOKEN_LOCAL,
TOKEN_GLOBAL,
2006-04-11 15:44:30 +00:00
TOKEN_IN,
2006-01-15 06:11:22 +00:00
__TOKEN_COUNT__
2005-11-14 15:23:54 +00:00
};
2006-03-30 16:24:10 +00:00
typedef struct __binmap_t __binmap_t;
struct __binmap_t
{
int token;
int binop;
};
2006-01-29 18:28:14 +00:00
2006-03-29 16:39:04 +00:00
static xp_awk_t* __parse_progunit (xp_awk_t* awk);
static xp_awk_t* __collect_globals (xp_awk_t* awk);
static xp_awk_t* __collect_locals (xp_awk_t* awk, xp_size_t nlocals);
2006-02-05 16:08:23 +00:00
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_function (xp_awk_t* awk);
static xp_awk_nde_t* __parse_begin (xp_awk_t* awk);
static xp_awk_nde_t* __parse_end (xp_awk_t* awk);
static xp_awk_nde_t* __parse_patternless (xp_awk_t* awk);
static xp_awk_nde_t* __parse_action (xp_awk_t* awk);
static xp_awk_nde_t* __parse_block (xp_awk_t* awk, xp_bool_t is_top);
static xp_awk_nde_t* __parse_statement (xp_awk_t* awk);
static xp_awk_nde_t* __parse_statement_nb (xp_awk_t* awk);
static xp_awk_nde_t* __parse_expression (xp_awk_t* awk);
2006-03-30 16:24:10 +00:00
2006-04-10 15:52:07 +00:00
static xp_awk_nde_t* __parse_basic_expr (xp_awk_t* awk);
2006-03-30 16:24:10 +00:00
static xp_awk_nde_t* __parse_binary_expr (
xp_awk_t* awk, const __binmap_t* binmap,
xp_awk_nde_t*(*next_level_func)(xp_awk_t*));
2006-03-29 16:39:04 +00:00
static xp_awk_nde_t* __parse_logical_or (xp_awk_t* awk);
static xp_awk_nde_t* __parse_logical_and (xp_awk_t* awk);
2006-04-12 03:54:12 +00:00
static xp_awk_nde_t* __parse_regex_match (xp_awk_t* awk);
2006-03-29 16:39:04 +00:00
static xp_awk_nde_t* __parse_bitwise_or (xp_awk_t* awk);
static xp_awk_nde_t* __parse_bitwise_xor (xp_awk_t* awk);
2006-03-31 12:04:14 +00:00
static xp_awk_nde_t* __parse_bitwise_and (xp_awk_t* awk);
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_equality (xp_awk_t* awk);
static xp_awk_nde_t* __parse_relational (xp_awk_t* awk);
static xp_awk_nde_t* __parse_shift (xp_awk_t* awk);
static xp_awk_nde_t* __parse_additive (xp_awk_t* awk);
static xp_awk_nde_t* __parse_multiplicative (xp_awk_t* awk);
2006-04-10 15:52:07 +00:00
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_unary (xp_awk_t* awk);
2006-04-02 12:45:04 +00:00
static xp_awk_nde_t* __parse_increment (xp_awk_t* awk);
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_primary (xp_awk_t* awk);
2006-04-10 15:52:07 +00:00
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_hashidx (xp_awk_t* awk, xp_char_t* name);
static xp_awk_nde_t* __parse_funcall (xp_awk_t* awk, xp_char_t* name);
static xp_awk_nde_t* __parse_if (xp_awk_t* awk);
static xp_awk_nde_t* __parse_while (xp_awk_t* awk);
static xp_awk_nde_t* __parse_for (xp_awk_t* awk);
static xp_awk_nde_t* __parse_dowhile (xp_awk_t* awk);
static xp_awk_nde_t* __parse_break (xp_awk_t* awk);
static xp_awk_nde_t* __parse_continue (xp_awk_t* awk);
static xp_awk_nde_t* __parse_return (xp_awk_t* awk);
static xp_awk_nde_t* __parse_exit (xp_awk_t* awk);
2006-03-31 16:35:37 +00:00
static xp_awk_nde_t* __parse_delete (xp_awk_t* awk);
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_next (xp_awk_t* awk);
static xp_awk_nde_t* __parse_nextfile (xp_awk_t* awk);
2006-01-09 12:51:47 +00:00
2005-11-14 15:23:54 +00:00
static int __get_token (xp_awk_t* awk);
2006-04-04 06:26:56 +00:00
static int __get_number (xp_awk_t* awk);
2006-04-07 04:23:11 +00:00
static int __get_string (xp_awk_t* awk);
2005-11-14 15:23:54 +00:00
static int __get_char (xp_awk_t* awk);
static int __unget_char (xp_awk_t* awk, xp_cint_t c);
static int __skip_spaces (xp_awk_t* awk);
static int __skip_comment (xp_awk_t* awk);
2006-02-04 19:31:51 +00:00
static int __classify_ident (xp_awk_t* awk, const xp_char_t* ident);
2006-04-14 16:26:00 +00:00
static int __assign_to_opcode (xp_awk_t* awk);
2005-11-15 15:32:39 +00:00
2005-12-29 12:04:51 +00:00
struct __kwent
{
const xp_char_t* name;
2005-11-15 15:32:39 +00:00
int type;
2006-02-04 19:31:51 +00:00
int valid; /* the entry is valid when this option is set */
2005-11-15 15:32:39 +00:00
};
static struct __kwent __kwtab[] =
{
2006-02-04 19:31:51 +00:00
{ XP_TEXT("BEGIN"), TOKEN_BEGIN, 0 },
{ XP_TEXT("END"), TOKEN_END, 0 },
2006-04-11 15:44:30 +00:00
2006-02-04 19:31:51 +00:00
{ XP_TEXT("function"), TOKEN_FUNCTION, 0 },
2006-03-25 17:04:36 +00:00
{ XP_TEXT("func"), TOKEN_FUNCTION, 0 },
2006-02-04 19:31:51 +00:00
{ XP_TEXT("if"), TOKEN_IF, 0 },
{ XP_TEXT("else"), TOKEN_ELSE, 0 },
{ XP_TEXT("while"), TOKEN_WHILE, 0 },
{ XP_TEXT("for"), TOKEN_FOR, 0 },
{ XP_TEXT("do"), TOKEN_DO, 0 },
{ XP_TEXT("break"), TOKEN_BREAK, 0 },
{ XP_TEXT("continue"), TOKEN_CONTINUE, 0 },
{ XP_TEXT("return"), TOKEN_RETURN, 0 },
{ XP_TEXT("exit"), TOKEN_EXIT, 0 },
{ XP_TEXT("delete"), TOKEN_DELETE, 0 },
{ XP_TEXT("next"), TOKEN_NEXT, 0 },
{ XP_TEXT("nextfile"), TOKEN_NEXTFILE, 0 },
{ XP_TEXT("local"), TOKEN_LOCAL, XP_AWK_EXPLICIT },
{ XP_TEXT("global"), TOKEN_GLOBAL, XP_AWK_EXPLICIT },
2006-04-11 15:44:30 +00:00
{ XP_TEXT("in"), TOKEN_IN, 0 },
2006-02-04 19:31:51 +00:00
{ XP_NULL, 0, 0 }
2005-11-15 15:32:39 +00:00
};
2005-11-14 15:23:54 +00:00
2006-04-16 04:31:38 +00:00
/* TODO:
static struct __kwent __bvtab[] =
{
{ XP_TEXT("ARGC"), TOKEN_ARGC, 0 },
{ XP_TEXT("ARGIND"), TOKEN_ARGIND, 0 },
{ XP_TEXT("ARGV"), TOKEN_ARGV, 0 },
{ XP_TEXT("CONVFMT"), TOKEN_CONVFMT, 0 },
{ XP_TEXT("FIELDWIDTHS"), TOKEN_FIELDWIDTHS, 0 },
{ XP_TEXT("ENVIRON"), TOKEN_ENVIRON, 0 },
{ XP_TEXT("ERRNO"), TOKEN_ERRNO, 0 },
{ XP_TEXT("FILENAME"), TOKEN_FILENAME, 0 },
{ XP_TEXT("FNR"), TOKEN_FNR, 0 },
{ XP_TEXT("FS"), TOKEN_FS, 0 },
{ XP_TEXT("IGNORECASE"), TOKEN_IGNORECASE, 0 },
{ XP_TEXT("NF"), TOKEN_NF, 0 },
{ XP_TEXT("NR"), TOKEN_NR, 0 },
{ XP_TEXT("OFMT"), TOKEN_OFMT, 0 },
{ XP_TEXT("OFS"), TOKEN_OFS, 0 },
{ XP_TEXT("ORS"), TOKEN_ORS, 0 },
{ XP_TEXT("RS"), TOKEN_RS, 0 },
{ XP_TEXT("RT"), TOKEN_RT, 0 },
{ XP_TEXT("RSTART"), TOKEN_RSTART, 0 },
{ XP_TEXT("RLENGTH"), TOKEN_RLENGTH, 0 },
{ XP_TEXT("SUBSEP"), TOKEN_SUBSEP, 0 },
{ XP_NULL, 0, 0 }
};
*/
2005-11-14 15:23:54 +00:00
#define GET_CHAR(awk) \
do { if (__get_char(awk) == -1) return -1; } while(0)
2006-03-04 10:08:13 +00:00
#define GET_CHAR_TO(awk,c) \
do { \
2005-11-14 15:23:54 +00:00
if (__get_char(awk) == -1) return -1; \
2005-12-29 12:04:51 +00:00
c = (awk)->lex.curc; \
2005-11-14 15:23:54 +00:00
} while(0)
#define SET_TOKEN_TYPE(awk,code) ((awk)->token.type = code)
2006-03-04 10:08:13 +00:00
#define ADD_TOKEN_CHAR(awk,c) \
do { \
2006-01-12 14:20:17 +00:00
if (xp_str_ccat(&(awk)->token.name,(c)) == (xp_size_t)-1) { \
2005-11-14 15:23:54 +00:00
(awk)->errnum = XP_AWK_ENOMEM; return -1; \
} \
} while (0)
2006-03-04 10:08:13 +00:00
#define ADD_TOKEN_STR(awk,str) \
do { \
2006-01-12 14:20:17 +00:00
if (xp_str_cat(&(awk)->token.name,(str)) == (xp_size_t)-1) { \
2005-11-14 15:23:54 +00:00
(awk)->errnum = XP_AWK_ENOMEM; return -1; \
2005-12-29 12:04:51 +00:00
} \
2005-11-14 15:23:54 +00:00
} while (0)
2005-11-06 12:01:29 +00:00
2005-12-29 12:04:51 +00:00
#define GET_TOKEN(awk) \
2006-04-14 16:26:00 +00:00
do { if (__get_token(awk) == -1) return -1; } while (0)
2005-11-15 15:59:23 +00:00
2006-01-09 12:51:47 +00:00
#define MATCH(awk,token_type) ((awk)->token.type == (token_type))
2006-04-14 16:26:00 +00:00
2006-01-09 12:51:47 +00:00
#define CONSUME(awk) \
2006-04-14 16:26:00 +00:00
do { if (__get_token(awk) == -1) return XP_NULL; } while (0)
2006-01-09 12:51:47 +00:00
2006-04-14 16:26:00 +00:00
#define PANIC(awk,code) \
do { (awk)->errnum = (code); return XP_NULL; } while (0)
2006-01-09 12:51:47 +00:00
2006-04-14 10:56:42 +00:00
/* TODO: remove stdio.h */
2006-04-16 04:31:38 +00:00
#ifndef XP_AWK_STAND_ALONE
2006-01-30 14:45:12 +00:00
#include <xp/bas/stdio.h>
#endif
2006-01-30 14:34:47 +00:00
static int __dump_func (xp_awk_pair_t* pair)
{
2006-03-05 17:07:33 +00:00
xp_awk_func_t* func = (xp_awk_func_t*)pair->val;
2006-02-05 13:45:59 +00:00
xp_size_t i;
2006-01-30 14:34:47 +00:00
xp_assert (xp_strcmp(pair->key, func->name) == 0);
2006-02-05 13:45:59 +00:00
xp_printf (XP_TEXT("function %s ("), func->name);
2006-03-04 10:08:13 +00:00
for (i = 0; i < func->nargs; )
{
2006-02-05 13:45:59 +00:00
xp_printf (XP_TEXT("__arg%lu"), (unsigned long)i++);
if (i >= func->nargs) break;
xp_printf (XP_TEXT(", "));
}
xp_printf (XP_TEXT(")\n"));
2006-01-30 14:34:47 +00:00
xp_awk_prnpt (func->body);
xp_printf (XP_TEXT("\n"));
return 0;
}
static void __dump (xp_awk_t* awk)
{
2006-02-07 15:28:05 +00:00
xp_awk_chain_t* chain;
2006-03-04 10:08:13 +00:00
if (awk->tree.nglobals > 0)
{
2006-02-05 16:00:33 +00:00
xp_size_t i;
xp_printf (XP_TEXT("global "));
2006-03-04 10:08:13 +00:00
for (i = 0; i < awk->tree.nglobals - 1; i++)
{
2006-02-05 16:00:33 +00:00
xp_printf (XP_TEXT("__global%lu, "), (unsigned long)i);
}
2006-02-05 16:08:23 +00:00
xp_printf (XP_TEXT("__global%lu;\n\n"), (unsigned long)i);
2006-02-05 16:00:33 +00:00
}
2006-03-02 15:10:59 +00:00
xp_awk_map_walk (&awk->tree.funcs, __dump_func);
2006-01-30 14:34:47 +00:00
2006-03-04 10:08:13 +00:00
if (awk->tree.begin != XP_NULL)
{
2006-01-30 14:34:47 +00:00
xp_printf (XP_TEXT("BEGIN "));
xp_awk_prnpt (awk->tree.begin);
xp_printf (XP_TEXT("\n"));
}
2006-02-07 15:28:05 +00:00
chain = awk->tree.chain;
2006-03-04 10:08:13 +00:00
while (chain != XP_NULL)
{
2006-02-07 15:28:05 +00:00
if (chain->pattern != XP_NULL) xp_awk_prnpt (chain->pattern);
if (chain->action != XP_NULL) xp_awk_prnpt (chain->action);
xp_printf (XP_TEXT("\n"));
chain = chain->next;
}
2006-03-04 10:08:13 +00:00
if (awk->tree.end != XP_NULL)
{
2006-01-30 14:34:47 +00:00
xp_printf (XP_TEXT("END "));
xp_awk_prnpt (awk->tree.end);
}
}
2005-11-06 12:01:29 +00:00
int xp_awk_parse (xp_awk_t* awk)
{
2006-01-24 16:14:28 +00:00
/* if you want to parse anew, call xp_awk_clear first.
* otherwise, the result is appened to the accumulated result */
2006-01-09 12:51:47 +00:00
2005-11-14 15:23:54 +00:00
GET_CHAR (awk);
2005-11-15 15:59:23 +00:00
GET_TOKEN (awk);
2006-01-09 12:51:47 +00:00
2006-03-04 10:08:13 +00:00
while (1)
{
2006-01-22 15:11:17 +00:00
if (MATCH(awk,TOKEN_EOF)) break;
2006-03-04 10:08:13 +00:00
if (__parse_progunit(awk) == XP_NULL)
{
2006-04-14 10:56:42 +00:00
/* TODO: cleanup the parse tree created so far....
function tables also etc... */
2006-01-22 15:11:17 +00:00
return -1;
}
2006-01-09 16:03:56 +00:00
}
2006-01-09 12:51:47 +00:00
2006-02-07 15:28:05 +00:00
awk->tree.nglobals = xp_awk_tab_getsize(&awk->parse.globals);
2006-01-30 14:34:47 +00:00
xp_printf (XP_TEXT("-----------------------------\n"));
__dump (awk);
2006-01-09 12:51:47 +00:00
return 0;
2005-11-14 15:23:54 +00:00
}
2006-02-05 16:00:33 +00:00
static xp_awk_t* __parse_progunit (xp_awk_t* awk)
2005-11-14 15:23:54 +00:00
{
2005-11-21 15:46:47 +00:00
/*
pattern { action }
function name (parameter-list) { statement }
*/
2006-01-09 12:51:47 +00:00
2006-03-04 10:08:13 +00:00
if ((awk->opt.parse & XP_AWK_EXPLICIT) && MATCH(awk,TOKEN_GLOBAL))
{
2006-02-05 16:00:33 +00:00
xp_size_t nglobals;
if (__get_token(awk) == -1) return XP_NULL;
nglobals = xp_awk_tab_getsize(&awk->parse.globals);
2006-03-04 10:08:13 +00:00
if (__collect_globals(awk) == XP_NULL)
{
2006-03-07 15:55:14 +00:00
xp_awk_tab_remove (
2006-02-05 16:00:33 +00:00
&awk->parse.globals, nglobals,
xp_awk_tab_getsize(&awk->parse.globals) - nglobals);
return XP_NULL;
}
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_FUNCTION))
{
2006-02-05 16:00:33 +00:00
if (__parse_function(awk) == XP_NULL) return XP_NULL;
2006-01-22 15:11:17 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_BEGIN))
{
2006-02-05 16:00:33 +00:00
if (__parse_begin(awk) == XP_NULL) return XP_NULL;
2006-01-22 15:11:17 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk, TOKEN_END))
{
2006-02-05 16:00:33 +00:00
if (__parse_end(awk) == XP_NULL) return XP_NULL;
2006-01-22 15:11:17 +00:00
}
/* TODO: process patterns and expressions */
/*
expressions
/regular expression/
pattern && pattern
pattern || pattern
!pattern
(pattern)
pattern, pattern
*/
2006-03-04 10:08:13 +00:00
else
{
2006-02-07 15:28:05 +00:00
if (__parse_patternless(awk) == XP_NULL) return XP_NULL;
2005-11-15 15:59:23 +00:00
}
2006-02-05 16:00:33 +00:00
return awk;
2005-11-16 16:09:53 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_function (xp_awk_t* awk)
2005-11-16 16:09:53 +00:00
{
2006-01-20 07:33:46 +00:00
xp_char_t* name;
2006-01-29 18:28:14 +00:00
xp_char_t* name_dup;
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* body;
2006-01-30 14:34:47 +00:00
xp_awk_func_t* func;
2006-01-31 16:57:45 +00:00
xp_size_t nargs;
2006-01-20 07:33:46 +00:00
2006-01-31 16:57:45 +00:00
/* eat up the keyword 'function' and get the next token */
2006-01-20 07:33:46 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-01-22 15:11:17 +00:00
2006-01-31 16:57:45 +00:00
/* match a function name */
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_IDENT))
{
2006-01-31 16:57:45 +00:00
/* cannot find a valid identifier for a function name */
PANIC (awk, XP_AWK_EIDENT);
}
2006-01-20 07:33:46 +00:00
2006-01-29 18:28:14 +00:00
name = XP_STR_BUF(&awk->token.name);
2006-03-04 10:08:13 +00:00
if (xp_awk_map_get(&awk->tree.funcs, name) != XP_NULL)
{
2006-01-31 16:57:45 +00:00
/* the function is defined previously */
PANIC (awk, XP_AWK_EDUPFUNC);
2006-01-29 18:28:14 +00:00
}
2006-03-04 10:08:13 +00:00
if (awk->opt.parse & XP_AWK_UNIQUE)
{
2006-02-04 19:31:51 +00:00
/* check if it coincides to be a global variable name */
2006-03-04 10:08:13 +00:00
if (xp_awk_tab_find(&awk->parse.globals, name, 0) != (xp_size_t)-1)
{
2006-01-31 16:57:45 +00:00
PANIC (awk, XP_AWK_EDUPNAME);
}
}
2006-01-29 18:28:14 +00:00
2006-01-31 16:57:45 +00:00
/* clone the function name before it is overwritten */
2006-01-29 18:28:14 +00:00
name_dup = xp_strdup (name);
2006-01-31 16:57:45 +00:00
if (name_dup == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
2006-01-20 07:33:46 +00:00
2006-01-31 16:57:45 +00:00
/* get the next token */
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
2006-01-20 07:33:46 +00:00
return XP_NULL;
}
2006-01-31 16:57:45 +00:00
/* match a left parenthesis */
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_LPAREN))
{
2006-01-31 16:57:45 +00:00
/* a function name is not followed by a left parenthesis */
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
2006-01-20 07:33:46 +00:00
PANIC (awk, XP_AWK_ELPAREN);
}
2006-01-31 16:57:45 +00:00
/* get the next token */
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
2006-01-20 07:33:46 +00:00
return XP_NULL;
}
2006-01-31 16:57:45 +00:00
/* make sure that parameter table is empty */
xp_assert (xp_awk_tab_getsize(&awk->parse.params) == 0);
/* read parameter list */
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_RPAREN))
{
2006-01-31 16:57:45 +00:00
/* no function parameter found. get the next token */
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
2006-01-20 07:33:46 +00:00
return XP_NULL;
}
}
2006-03-04 10:08:13 +00:00
else
{
while (1)
{
2006-02-04 19:31:51 +00:00
xp_char_t* param;
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_IDENT))
{
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
2006-01-31 16:57:45 +00:00
xp_awk_tab_clear (&awk->parse.params);
2006-01-20 07:33:46 +00:00
PANIC (awk, XP_AWK_EIDENT);
}
2006-02-04 19:31:51 +00:00
param = XP_STR_BUF(&awk->token.name);
2006-03-04 10:08:13 +00:00
if (awk->opt.parse & XP_AWK_UNIQUE)
{
2006-02-04 19:31:51 +00:00
/* check if a parameter conflicts with a function */
if (xp_strcmp(name_dup, param) == 0 ||
2006-03-04 10:08:13 +00:00
xp_awk_map_get(&awk->tree.funcs, param) != XP_NULL)
{
2006-02-04 19:31:51 +00:00
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
*/
}
2006-01-31 16:57:45 +00:00
2006-02-04 19:31:51 +00:00
/* check if a parameter conflicts with other parameters */
2006-03-04 10:08:13 +00:00
if (xp_awk_tab_find(&awk->parse.params, param, 0) != (xp_size_t)-1)
{
2006-01-31 16:57:45 +00:00
xp_free (name_dup);
xp_awk_tab_clear (&awk->parse.params);
PANIC (awk, XP_AWK_EDUPPARAM);
}
2006-02-04 19:31:51 +00:00
/* push the parameter to the parameter list */
2006-03-07 15:55:14 +00:00
if (xp_awk_tab_add(&awk->parse.params, param) == (xp_size_t)-1)
2006-03-04 10:08:13 +00:00
{
2006-01-31 16:57:45 +00:00
xp_free (name_dup);
xp_awk_tab_clear (&awk->parse.params);
PANIC (awk, XP_AWK_ENOMEM);
}
2006-01-29 18:28:14 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
2006-01-31 16:57:45 +00:00
xp_awk_tab_clear (&awk->parse.params);
2006-01-20 07:33:46 +00:00
return XP_NULL;
}
if (MATCH(awk,TOKEN_RPAREN)) break;
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_COMMA))
{
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
2006-01-31 16:57:45 +00:00
xp_awk_tab_clear (&awk->parse.params);
2006-01-20 07:33:46 +00:00
PANIC (awk, XP_AWK_ECOMMA);
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
2006-01-31 16:57:45 +00:00
xp_awk_tab_clear (&awk->parse.params);
2006-01-20 07:33:46 +00:00
return XP_NULL;
}
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
2006-01-31 16:57:45 +00:00
xp_awk_tab_clear (&awk->parse.params);
2006-01-20 07:33:46 +00:00
return XP_NULL;
}
}
2006-01-29 18:28:14 +00:00
/* check if the function body starts with a left brace */
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_LBRACE))
{
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
2006-01-31 16:57:45 +00:00
xp_awk_tab_clear (&awk->parse.params);
2006-01-20 07:33:46 +00:00
PANIC (awk, XP_AWK_ELBRACE);
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
2006-01-31 16:57:45 +00:00
xp_awk_tab_clear (&awk->parse.params);
2006-01-20 07:33:46 +00:00
return XP_NULL;
}
2006-01-29 18:28:14 +00:00
/* actual function body */
2006-02-04 19:31:51 +00:00
body = __parse_block (awk, xp_true);
2006-03-04 10:08:13 +00:00
if (body == XP_NULL)
{
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
2006-01-31 16:57:45 +00:00
xp_awk_tab_clear (&awk->parse.params);
2006-01-20 07:33:46 +00:00
return XP_NULL;
}
2006-04-14 10:56:42 +00:00
/* TODO: consider if the parameters should be saved for some reasons.. */
2006-01-31 16:57:45 +00:00
nargs = xp_awk_tab_getsize(&awk->parse.params);
/* parameter names are not required anymore. clear them */
xp_awk_tab_clear (&awk->parse.params);
2006-03-05 17:07:33 +00:00
func = (xp_awk_func_t*)xp_malloc(xp_sizeof(xp_awk_func_t));
2006-03-04 10:08:13 +00:00
if (func == XP_NULL)
{
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
2006-01-22 15:11:17 +00:00
xp_awk_clrpt (body);
return XP_NULL;
}
2006-01-29 18:28:14 +00:00
func->name = name_dup;
func->nargs = nargs;
func->body = body;
2006-03-02 15:10:59 +00:00
xp_assert (xp_awk_map_get(&awk->tree.funcs, name_dup) == XP_NULL);
2006-03-04 10:08:13 +00:00
if (xp_awk_map_put(&awk->tree.funcs, name_dup, func) == XP_NULL)
{
2006-01-29 18:28:14 +00:00
xp_free (name_dup);
xp_awk_clrpt (body);
xp_free (func);
PANIC (awk, XP_AWK_ENOMEM);
}
2006-01-22 15:11:17 +00:00
2006-01-20 07:33:46 +00:00
return body;
2005-11-14 15:23:54 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_begin (xp_awk_t* awk)
2005-11-15 15:59:23 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* nde;
2006-01-09 12:51:47 +00:00
2006-01-22 15:11:17 +00:00
if (awk->tree.begin != XP_NULL) PANIC (awk, XP_AWK_EDUPBEGIN);
if (__get_token(awk) == -1) return XP_NULL;
2006-01-09 12:51:47 +00:00
2006-03-03 11:45:45 +00:00
nde = __parse_action (awk);
if (nde == XP_NULL) return XP_NULL;
2006-01-22 15:11:17 +00:00
2006-03-03 11:45:45 +00:00
awk->tree.begin = nde;
return nde;
2006-01-22 15:11:17 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_end (xp_awk_t* awk)
2006-01-22 15:11:17 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* nde;
2006-01-22 15:11:17 +00:00
if (awk->tree.end != XP_NULL) PANIC (awk, XP_AWK_EDUPEND);
2006-01-14 14:09:52 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2005-11-15 15:59:23 +00:00
2006-03-03 11:45:45 +00:00
nde = __parse_action (awk);
if (nde == XP_NULL) return XP_NULL;
2006-01-09 12:51:47 +00:00
2006-03-03 11:45:45 +00:00
awk->tree.end = nde;
return nde;
2006-01-09 12:51:47 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_patternless (xp_awk_t* awk)
2006-02-07 15:28:05 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* nde;
2006-02-07 15:28:05 +00:00
xp_awk_chain_t* chain;
2006-03-03 11:45:45 +00:00
nde = __parse_action (awk);
if (nde == XP_NULL) return XP_NULL;
2006-02-07 15:28:05 +00:00
2006-03-05 17:07:33 +00:00
chain = (xp_awk_chain_t*)xp_malloc(xp_sizeof(xp_awk_chain_t));
2006-03-04 10:08:13 +00:00
if (chain == XP_NULL)
{
2006-03-03 11:45:45 +00:00
xp_awk_clrpt (nde);
2006-02-07 15:28:05 +00:00
PANIC (awk, XP_AWK_ENOMEM);
}
chain->pattern = XP_NULL;
2006-03-03 11:45:45 +00:00
chain->action = nde;
2006-02-07 15:28:05 +00:00
chain->next = XP_NULL;
2006-03-04 10:08:13 +00:00
if (awk->tree.chain == XP_NULL)
{
2006-02-07 15:28:05 +00:00
awk->tree.chain = chain;
awk->tree.chain_tail = chain;
}
2006-03-04 10:08:13 +00:00
else
{
2006-02-07 15:28:05 +00:00
awk->tree.chain_tail->next = chain;
awk->tree.chain_tail = chain;
}
2006-03-03 11:45:45 +00:00
return nde;
2006-02-07 15:28:05 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_action (xp_awk_t* awk)
2006-01-22 15:11:17 +00:00
{
if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, XP_AWK_ELBRACE);
if (__get_token(awk) == -1) return XP_NULL;
2006-02-04 19:31:51 +00:00
return __parse_block(awk, xp_true);
2006-01-22 15:11:17 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_block (xp_awk_t* awk, xp_bool_t is_top)
2006-01-09 12:51:47 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* head, * curr, * nde;
2006-03-05 17:07:33 +00:00
xp_awk_nde_blk_t* block;
2006-02-05 06:10:43 +00:00
xp_size_t nlocals, nlocals_max, tmp;
2006-01-25 16:11:43 +00:00
2006-02-04 19:31:51 +00:00
nlocals = xp_awk_tab_getsize(&awk->parse.locals);
2006-02-05 06:10:43 +00:00
nlocals_max = awk->parse.nlocals_max;
2006-02-04 19:31:51 +00:00
/* local variable declarations */
2006-03-04 10:08:13 +00:00
if (awk->opt.parse & XP_AWK_EXPLICIT)
{
while (1)
{
2006-02-04 19:31:51 +00:00
if (!MATCH(awk,TOKEN_LOCAL)) break;
2006-01-09 12:51:47 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-03-07 15:55:14 +00:00
xp_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals,
2006-02-04 19:31:51 +00:00
xp_awk_tab_getsize(&awk->parse.locals) - nlocals);
return XP_NULL;
2006-01-25 16:11:43 +00:00
}
2006-03-04 10:08:13 +00:00
if (__collect_locals(awk, nlocals) == XP_NULL)
{
2006-03-07 15:55:14 +00:00
xp_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals,
2006-02-04 19:31:51 +00:00
xp_awk_tab_getsize(&awk->parse.locals) - nlocals);
return XP_NULL;
}
2006-01-25 16:11:43 +00:00
}
}
/* block body */
2006-01-14 14:09:52 +00:00
head = XP_NULL; curr = XP_NULL;
2006-01-09 12:51:47 +00:00
2006-03-04 10:08:13 +00:00
while (1)
{
if (MATCH(awk,TOKEN_EOF))
{
2006-03-07 15:55:14 +00:00
xp_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals,
2006-02-04 19:31:51 +00:00
xp_awk_tab_getsize(&awk->parse.locals) - nlocals);
2006-01-14 16:09:58 +00:00
if (head != XP_NULL) xp_awk_clrpt (head);
2006-01-09 16:03:56 +00:00
PANIC (awk, XP_AWK_EENDSRC);
}
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_RBRACE))
{
if (__get_token(awk) == -1)
{
2006-03-07 15:55:14 +00:00
xp_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals,
2006-02-04 19:31:51 +00:00
xp_awk_tab_getsize(&awk->parse.locals) - nlocals);
2006-01-14 16:09:58 +00:00
if (head != XP_NULL) xp_awk_clrpt (head);
2006-01-14 14:09:52 +00:00
return XP_NULL;
}
2006-01-09 12:51:47 +00:00
break;
}
2006-03-03 11:45:45 +00:00
nde = __parse_statement (awk);
2006-03-04 10:08:13 +00:00
if (nde == XP_NULL)
{
2006-03-07 15:55:14 +00:00
xp_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals,
2006-02-04 19:31:51 +00:00
xp_awk_tab_getsize(&awk->parse.locals) - nlocals);
2006-01-14 16:09:58 +00:00
if (head != XP_NULL) xp_awk_clrpt (head);
2006-01-14 14:09:52 +00:00
return XP_NULL;
}
2006-02-04 19:31:51 +00:00
/* remove unnecessary statements */
2006-03-03 11:45:45 +00:00
if (nde->type == XP_AWK_NDE_NULL ||
2006-03-05 17:07:33 +00:00
(nde->type == XP_AWK_NDE_BLK &&
((xp_awk_nde_blk_t*)nde)->body == XP_NULL)) continue;
2006-02-04 19:31:51 +00:00
2006-03-03 11:45:45 +00:00
if (curr == XP_NULL) head = nde;
else curr->next = nde;
curr = nde;
2006-01-14 14:09:52 +00:00
}
2006-01-10 13:57:54 +00:00
2006-03-05 17:07:33 +00:00
block = (xp_awk_nde_blk_t*)xp_malloc(xp_sizeof(xp_awk_nde_blk_t));
2006-03-04 10:08:13 +00:00
if (block == XP_NULL)
{
2006-03-07 15:55:14 +00:00
xp_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals,
2006-02-04 19:31:51 +00:00
xp_awk_tab_getsize(&awk->parse.locals) - nlocals);
2006-01-14 14:09:52 +00:00
xp_awk_clrpt (head);
PANIC (awk, XP_AWK_ENOMEM);
2006-01-09 12:51:47 +00:00
}
2006-02-04 19:31:51 +00:00
tmp = xp_awk_tab_getsize(&awk->parse.locals);
2006-02-05 06:10:43 +00:00
if (tmp > awk->parse.nlocals_max) awk->parse.nlocals_max = tmp;
2006-03-07 15:55:14 +00:00
xp_awk_tab_remove (
2006-02-05 14:21:18 +00:00
&awk->parse.locals, nlocals, tmp - nlocals);
2006-02-04 19:31:51 +00:00
2006-04-10 14:53:48 +00:00
/* adjust the number of locals for a block without any statements */
/* if (head == XP_NULL) tmp = 0; */
2006-02-04 19:31:51 +00:00
2006-03-05 17:07:33 +00:00
block->type = XP_AWK_NDE_BLK;
2006-01-14 14:09:52 +00:00
block->next = XP_NULL;
block->body = head;
2006-04-05 15:56:20 +00:00
/* TODO: not only local variables but also nested blocks,
2006-02-05 16:12:50 +00:00
unless it is part of other constructs such as if, can be promoted
and merged to top-level block */
2006-02-05 06:10:43 +00:00
/* migrate all block-local variables to a top-level block */
2006-03-04 10:08:13 +00:00
if (is_top)
{
2006-02-04 19:31:51 +00:00
block->nlocals = awk->parse.nlocals_max - nlocals;
2006-02-05 06:10:43 +00:00
awk->parse.nlocals_max = nlocals_max;
2006-02-04 19:31:51 +00:00
}
2006-03-04 10:08:13 +00:00
else
{
2006-02-05 06:10:43 +00:00
/*block->nlocals = tmp - nlocals;*/
2006-02-04 19:31:51 +00:00
block->nlocals = 0;
}
2006-01-25 16:11:43 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)block;
2006-01-09 12:51:47 +00:00
}
2006-02-05 16:00:33 +00:00
static xp_awk_t* __collect_globals (xp_awk_t* awk)
{
xp_char_t* global;
2006-03-04 10:08:13 +00:00
while (1)
{
if (!MATCH(awk,TOKEN_IDENT))
{
2006-02-05 16:00:33 +00:00
PANIC (awk, XP_AWK_EIDENT);
}
global = XP_STR_BUF(&awk->token.name);
2006-03-04 10:08:13 +00:00
if (awk->opt.parse & XP_AWK_UNIQUE)
{
2006-02-05 16:00:33 +00:00
/* check if it conflict with a function name */
2006-03-04 10:08:13 +00:00
if (xp_awk_map_get(&awk->tree.funcs, global) != XP_NULL)
{
2006-02-05 16:00:33 +00:00
PANIC (awk, XP_AWK_EDUPNAME);
}
}
/* check if it conflicts with other global variable names */
2006-03-04 10:08:13 +00:00
if (xp_awk_tab_find(&awk->parse.globals, global, 0) != (xp_size_t)-1)
{
2006-02-05 16:00:33 +00:00
PANIC (awk, XP_AWK_EDUPVAR);
}
2006-03-07 15:55:14 +00:00
if (xp_awk_tab_add(&awk->parse.globals, global) == (xp_size_t)-1)
2006-03-04 10:08:13 +00:00
{
2006-02-05 16:00:33 +00:00
PANIC (awk, XP_AWK_ENOMEM);
}
if (__get_token(awk) == -1) return XP_NULL;
if (MATCH(awk,TOKEN_SEMICOLON)) break;
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_COMMA))
{
2006-02-05 16:00:33 +00:00
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;
}
2006-02-04 19:31:51 +00:00
static xp_awk_t* __collect_locals (xp_awk_t* awk, xp_size_t nlocals)
{
xp_char_t* local;
2006-03-04 10:08:13 +00:00
while (1)
{
if (!MATCH(awk,TOKEN_IDENT))
{
2006-02-04 19:31:51 +00:00
PANIC (awk, XP_AWK_EIDENT);
}
local = XP_STR_BUF(&awk->token.name);
/* NOTE: it is not checked againt globals names */
2006-03-04 10:08:13 +00:00
if (awk->opt.parse & XP_AWK_UNIQUE)
{
2006-02-04 19:31:51 +00:00
/* check if it conflict with a function name */
2006-03-04 10:08:13 +00:00
if (xp_awk_map_get(&awk->tree.funcs, local) != XP_NULL)
{
2006-02-04 19:31:51 +00:00
PANIC (awk, XP_AWK_EDUPNAME);
}
}
/* check if it conflicts with a paremeter name */
2006-03-04 10:08:13 +00:00
if (xp_awk_tab_find(&awk->parse.params, local, 0) != (xp_size_t)-1)
{
2006-02-04 19:31:51 +00:00
PANIC (awk, XP_AWK_EDUPNAME);
}
/* check if it conflicts with other local variable names */
if (xp_awk_tab_find(&awk->parse.locals, local,
2006-04-05 15:56:20 +00:00
((awk->opt.parse & XP_AWK_SHADING)? nlocals: 0)) != (xp_size_t)-1)
{
2006-02-04 19:31:51 +00:00
PANIC (awk, XP_AWK_EDUPVAR);
}
2006-03-07 15:55:14 +00:00
if (xp_awk_tab_add(&awk->parse.locals, local) == (xp_size_t)-1)
2006-03-04 10:08:13 +00:00
{
2006-02-04 19:31:51 +00:00
PANIC (awk, XP_AWK_ENOMEM);
}
if (__get_token(awk) == -1) return XP_NULL;
if (MATCH(awk,TOKEN_SEMICOLON)) break;
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_COMMA))
{
2006-02-04 19:31:51 +00:00
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;
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_statement (xp_awk_t* awk)
2006-01-10 13:57:54 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* nde;
2006-01-10 13:57:54 +00:00
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_SEMICOLON))
{
2006-01-18 16:12:59 +00:00
/* null statement */
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_t*)xp_malloc(xp_sizeof(xp_awk_nde_t));
2006-03-03 11:45:45 +00:00
if (nde == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
2006-01-18 16:12:59 +00:00
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_NULL;
nde->next = XP_NULL;
2006-01-18 16:12:59 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-03-03 11:45:45 +00:00
xp_free (nde);
2006-01-18 16:12:59 +00:00
return XP_NULL;
}
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_LBRACE))
{
2006-01-14 16:09:58 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-03-03 11:45:45 +00:00
nde = __parse_block (awk, xp_false);
2006-01-14 16:09:58 +00:00
}
2006-03-03 11:45:45 +00:00
else nde = __parse_statement_nb (awk);
2006-01-14 16:09:58 +00:00
2006-03-03 11:45:45 +00:00
return nde;
2006-01-14 16:09:58 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_statement_nb (xp_awk_t* awk)
2006-01-14 16:09:58 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* nde;
2006-01-14 16:09:58 +00:00
2006-01-15 06:11:22 +00:00
/*
* keywords that don't require any terminating semicolon
*/
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_IF))
{
2006-01-14 14:09:52 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-01-18 16:12:59 +00:00
return __parse_if (awk);
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_WHILE))
{
2006-01-14 14:09:52 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-01-18 16:12:59 +00:00
return __parse_while (awk);
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_FOR))
{
2006-01-14 14:09:52 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-01-18 16:12:59 +00:00
return __parse_for (awk);
2006-01-10 13:57:54 +00:00
}
2006-01-15 06:11:22 +00:00
/*
* keywords that require a terminating semicolon
*/
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_DO))
{
2006-01-19 10:56:35 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-03-03 11:45:45 +00:00
nde = __parse_dowhile (awk);
2006-01-19 10:56:35 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_BREAK))
{
2006-01-14 14:09:52 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-03-03 11:45:45 +00:00
nde = __parse_break(awk);
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_CONTINUE))
{
2006-01-14 14:09:52 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-03-03 11:45:45 +00:00
nde = __parse_continue(awk);
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_RETURN))
{
2006-01-14 14:09:52 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-03-03 11:45:45 +00:00
nde = __parse_return(awk);
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_EXIT))
{
2006-01-14 14:09:52 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-03-03 11:45:45 +00:00
nde = __parse_exit(awk);
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_DELETE))
{
2006-01-14 14:09:52 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-03-03 11:45:45 +00:00
nde = __parse_delete(awk);
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_NEXT))
{
2006-01-14 14:09:52 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-03-03 11:45:45 +00:00
nde = __parse_next(awk);
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_NEXTFILE))
{
2006-01-14 14:09:52 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-03-03 11:45:45 +00:00
nde = __parse_nextfile(awk);
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else
{
2006-03-03 11:45:45 +00:00
nde = __parse_expression(awk);
2006-01-10 13:57:54 +00:00
}
2006-03-03 11:45:45 +00:00
if (nde == XP_NULL) return XP_NULL;
2006-01-13 14:16:56 +00:00
2006-01-11 11:52:17 +00:00
/* check if a statement ends with a semicolon */
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_SEMICOLON))
{
2006-03-03 11:45:45 +00:00
if (nde != XP_NULL) xp_awk_clrpt (nde);
2006-01-11 11:52:17 +00:00
PANIC (awk, XP_AWK_ESEMICOLON);
}
/* eat up the semicolon and read in the next token */
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-03-03 11:45:45 +00:00
if (nde != XP_NULL) xp_awk_clrpt (nde);
2006-01-14 14:09:52 +00:00
return XP_NULL;
}
2006-01-11 11:52:17 +00:00
2006-03-03 11:45:45 +00:00
return nde;
2006-01-10 13:57:54 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_expression (xp_awk_t* awk)
2006-01-10 13:57:54 +00:00
{
2006-01-11 11:52:17 +00:00
/*
* <expression> ::= <assignment> | <basic expression>
* <assignment> ::= <assignment target> assignmentOperator <basic expression>
* assignmentOperator ::= '='
* <basic expression> ::=
*/
2006-01-14 14:09:52 +00:00
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* x, * y;
xp_awk_nde_ass_t* nde;
2006-04-14 16:26:00 +00:00
int opcode;
2006-01-20 07:33:46 +00:00
2006-01-25 14:50:57 +00:00
x = __parse_basic_expr (awk);
2006-01-20 07:33:46 +00:00
if (x == XP_NULL) return XP_NULL;
2006-04-14 16:26:00 +00:00
opcode = __assign_to_opcode (awk);
if (opcode == -1) return x;
2006-01-20 07:33:46 +00:00
xp_assert (x->next == XP_NULL);
2006-03-03 11:45:45 +00:00
if (x->type != XP_AWK_NDE_ARG &&
x->type != XP_AWK_NDE_ARGIDX &&
x->type != XP_AWK_NDE_NAMED &&
x->type != XP_AWK_NDE_NAMEDIDX &&
x->type != XP_AWK_NDE_GLOBAL &&
x->type != XP_AWK_NDE_GLOBALIDX &&
x->type != XP_AWK_NDE_LOCAL &&
x->type != XP_AWK_NDE_LOCALIDX &&
2006-03-04 10:08:13 +00:00
x->type != XP_AWK_NDE_POS)
{
2006-01-20 07:33:46 +00:00
xp_awk_clrpt (x);
2006-03-04 15:54:37 +00:00
PANIC (awk, XP_AWK_EASSIGNMENT);
2006-01-20 07:33:46 +00:00
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-20 07:33:46 +00:00
xp_awk_clrpt (x);
return XP_NULL;
}
2006-01-25 14:50:57 +00:00
y = __parse_basic_expr (awk);
2006-03-04 10:08:13 +00:00
if (y == XP_NULL)
{
2006-01-20 07:33:46 +00:00
xp_awk_clrpt (x);
return XP_NULL;
}
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_ass_t*)xp_malloc(xp_sizeof(xp_awk_nde_ass_t));
2006-03-04 10:08:13 +00:00
if (nde == XP_NULL)
{
2006-01-20 07:33:46 +00:00
xp_awk_clrpt (x);
xp_awk_clrpt (y);
PANIC (awk, XP_AWK_ENOMEM);
}
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_ASS;
nde->next = XP_NULL;
2006-04-14 16:26:00 +00:00
nde->opcode = opcode;
2006-03-03 11:45:45 +00:00
nde->left = x;
nde->right = y;
2006-01-20 07:33:46 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-01-11 11:52:17 +00:00
}
2006-04-10 15:52:07 +00:00
static xp_awk_nde_t* __parse_basic_expr (xp_awk_t* awk)
{
xp_awk_nde_t* nde, * n1, * n2;
nde = __parse_logical_or (awk);
if (nde == XP_NULL) return XP_NULL;
if (MATCH(awk,TOKEN_QUEST))
{
2006-04-11 09:16:20 +00:00
xp_awk_nde_cnd_t* tmp;
2006-04-10 15:52:07 +00:00
if (__get_token(awk) == -1) return XP_NULL;
n1 = __parse_basic_expr (awk);
if (n1 == XP_NULL)
{
2006-04-11 09:16:20 +00:00
xp_awk_clrpt (nde);
return XP_NULL;
2006-04-10 15:52:07 +00:00
}
if (!MATCH(awk,TOKEN_COLON)) PANIC (awk, XP_AWK_ECOLON);
if (__get_token(awk) == -1) return XP_NULL;
n2 = __parse_basic_expr (awk);
if (n2 == XP_NULL)
{
2006-04-11 09:16:20 +00:00
xp_awk_clrpt (nde);
xp_awk_clrpt (n1);
return XP_NULL;
}
tmp = (xp_awk_nde_cnd_t*)xp_malloc(xp_sizeof(xp_awk_nde_cnd_t));
if (tmp == XP_NULL)
{
xp_awk_clrpt (nde);
xp_awk_clrpt (n1);
xp_awk_clrpt (n2);
return XP_NULL;
2006-04-10 15:52:07 +00:00
}
2006-04-11 09:16:20 +00:00
tmp->type = XP_AWK_NDE_CND;
tmp->next = XP_NULL;
tmp->test = nde;
tmp->left = n1;
tmp->right = n2;
nde = (xp_awk_nde_t*)tmp;
2006-04-10 15:52:07 +00:00
}
return nde;
}
2006-03-30 16:24:10 +00:00
static xp_awk_nde_t* __parse_binary_expr (
xp_awk_t* awk, const __binmap_t* binmap,
xp_awk_nde_t*(*next_level_func)(xp_awk_t*))
2006-03-29 16:39:04 +00:00
{
xp_awk_nde_exp_t* nde;
xp_awk_nde_t* left, * right;
int opcode;
2006-03-30 16:24:10 +00:00
left = next_level_func (awk);
2006-03-29 16:39:04 +00:00
if (left == XP_NULL) return XP_NULL;
while (1)
{
2006-03-30 16:24:10 +00:00
const __binmap_t* p = binmap;
xp_bool_t matched = xp_false;
while (p->token != TOKEN_EOF)
{
if (MATCH(awk,p->token))
{
opcode = p->binop;
matched = xp_true;
break;
}
p++;
}
if (!matched) break;
2006-03-29 16:39:04 +00:00
if (__get_token(awk) == -1)
{
xp_awk_clrpt (left);
return XP_NULL;
}
2006-03-30 16:24:10 +00:00
right = next_level_func (awk);
2006-03-29 16:39:04 +00:00
if (right == XP_NULL)
{
xp_awk_clrpt (left);
return XP_NULL;
}
2006-03-31 16:35:37 +00:00
/* TODO: enhance constant folding. do it in a better way */
/* TODO: differentiate different types of numbers ... */
if (left->type == XP_AWK_NDE_INT &&
right->type == XP_AWK_NDE_INT)
{
xp_long_t l, r;
2006-03-29 16:39:04 +00:00
2006-03-31 16:35:37 +00:00
l = ((xp_awk_nde_int_t*)left)->val;
r = ((xp_awk_nde_int_t*)right)->val;
/* TODO: more operators */
if (opcode == XP_AWK_BINOP_PLUS) l += r;
else if (opcode == XP_AWK_BINOP_MINUS) l -= r;
else if (opcode == XP_AWK_BINOP_MUL) l *= r;
2006-04-05 15:56:20 +00:00
else if (opcode == XP_AWK_BINOP_DIV && r != 0) l /= r;
else if (opcode == XP_AWK_BINOP_MOD && r != 0) l %= r;
2006-03-31 16:35:37 +00:00
else goto skip_constant_folding;
xp_awk_clrpt (right);
((xp_awk_nde_int_t*)left)->val = l;
continue;
}
else if (left->type == XP_AWK_NDE_REAL &&
right->type == XP_AWK_NDE_REAL)
{
2006-04-05 15:56:20 +00:00
xp_real_t l, r;
l = ((xp_awk_nde_real_t*)left)->val;
r = ((xp_awk_nde_real_t*)right)->val;
/* TODO: more operators */
if (opcode == XP_AWK_BINOP_PLUS) l += r;
else if (opcode == XP_AWK_BINOP_MINUS) l -= r;
else if (opcode == XP_AWK_BINOP_MUL) l *= r;
else if (opcode == XP_AWK_BINOP_DIV) l /= r;
else goto skip_constant_folding;
xp_awk_clrpt (right);
((xp_awk_nde_real_t*)left)->val = l;
continue;
2006-03-31 16:35:37 +00:00
}
2006-04-14 10:56:42 +00:00
/* TODO: enhance constant folding more... */
2006-03-31 16:35:37 +00:00
skip_constant_folding:
2006-04-10 15:52:07 +00:00
nde = (xp_awk_nde_exp_t*)
xp_malloc (xp_sizeof(xp_awk_nde_exp_t));
2006-03-29 16:39:04 +00:00
if (nde == XP_NULL)
{
xp_awk_clrpt (right);
xp_awk_clrpt (left);
PANIC (awk, XP_AWK_ENOMEM);
}
nde->type = XP_AWK_NDE_EXP_BIN;
nde->next = XP_NULL;
nde->opcode = opcode;
nde->left = left;
nde->right = right;
left = (xp_awk_nde_t*)nde;
}
return left;
}
2006-03-30 16:24:10 +00:00
static xp_awk_nde_t* __parse_logical_or (xp_awk_t* awk)
{
__binmap_t map[] =
2006-03-29 16:39:04 +00:00
{
2006-03-30 16:24:10 +00:00
{ TOKEN_LOR, XP_AWK_BINOP_LOR },
{ TOKEN_EOF, 0 }
};
2006-03-29 16:39:04 +00:00
2006-03-30 16:31:50 +00:00
return __parse_binary_expr (awk, map, __parse_logical_and);
2006-03-30 16:24:10 +00:00
}
2006-03-29 16:39:04 +00:00
2006-03-30 16:24:10 +00:00
static xp_awk_nde_t* __parse_logical_and (xp_awk_t* awk)
{
__binmap_t map[] =
{
{ TOKEN_LAND, XP_AWK_BINOP_LAND },
2006-04-12 03:54:12 +00:00
{ TOKEN_EOF, 0 }
};
return __parse_binary_expr (awk, map, __parse_regex_match);
}
static xp_awk_nde_t* __parse_regex_match (xp_awk_t* awk)
{
__binmap_t map[] =
{
{ TOKEN_TILDE, XP_AWK_BINOP_MA },
{ TOKEN_NM, XP_AWK_BINOP_NM },
{ TOKEN_EOF, 0 },
2006-03-30 16:24:10 +00:00
};
2006-03-29 16:39:04 +00:00
2006-03-30 16:31:50 +00:00
return __parse_binary_expr (awk, map, __parse_bitwise_or);
2006-03-29 16:39:04 +00:00
}
static xp_awk_nde_t* __parse_bitwise_or (xp_awk_t* awk)
{
2006-03-30 16:24:10 +00:00
__binmap_t map[] =
2006-03-29 16:39:04 +00:00
{
2006-03-30 16:24:10 +00:00
{ TOKEN_BOR, XP_AWK_BINOP_BOR },
{ TOKEN_EOF, 0 }
};
2006-03-29 16:39:04 +00:00
2006-03-30 16:31:50 +00:00
return __parse_binary_expr (awk, map, __parse_bitwise_xor);
2006-03-29 16:39:04 +00:00
}
static xp_awk_nde_t* __parse_bitwise_xor (xp_awk_t* awk)
{
2006-03-30 16:24:10 +00:00
__binmap_t map[] =
{
{ TOKEN_BXOR, XP_AWK_BINOP_BXOR },
2006-04-12 03:54:12 +00:00
{ TOKEN_EOF, 0 }
2006-03-30 16:24:10 +00:00
};
2006-03-31 12:04:14 +00:00
return __parse_binary_expr (awk, map, __parse_bitwise_and);
}
static xp_awk_nde_t* __parse_bitwise_and (xp_awk_t* awk)
{
__binmap_t map[] =
{
{ TOKEN_BAND, XP_AWK_BINOP_BAND },
2006-04-12 03:54:12 +00:00
{ TOKEN_EOF, 0 }
2006-03-31 12:04:14 +00:00
};
2006-03-30 16:31:50 +00:00
return __parse_binary_expr (awk, map, __parse_equality);
2006-01-10 13:57:54 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_equality (xp_awk_t* awk)
2006-02-08 16:14:31 +00:00
{
2006-03-30 16:38:51 +00:00
__binmap_t map[] =
2006-03-04 10:08:13 +00:00
{
2006-03-30 16:38:51 +00:00
{ TOKEN_EQ, XP_AWK_BINOP_EQ },
{ TOKEN_NE, XP_AWK_BINOP_NE },
{ TOKEN_EOF, 0 }
};
2006-02-08 16:14:31 +00:00
2006-03-30 16:38:51 +00:00
return __parse_binary_expr (awk, map, __parse_relational);
2006-02-08 16:14:31 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_relational (xp_awk_t* awk)
2006-02-08 16:14:31 +00:00
{
2006-03-31 12:04:14 +00:00
__binmap_t map[] =
2006-03-04 10:08:13 +00:00
{
2006-03-31 12:04:14 +00:00
{ TOKEN_GT, XP_AWK_BINOP_GT },
{ TOKEN_GE, XP_AWK_BINOP_GE },
{ TOKEN_LT, XP_AWK_BINOP_LT },
{ TOKEN_LE, XP_AWK_BINOP_LE },
{ TOKEN_EOF, 0 }
};
2006-02-08 16:14:31 +00:00
2006-03-31 12:04:14 +00:00
return __parse_binary_expr (awk, map, __parse_shift);
2006-02-08 16:14:31 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_shift (xp_awk_t* awk)
2006-02-08 16:14:31 +00:00
{
2006-03-31 12:04:14 +00:00
__binmap_t map[] =
2006-03-04 10:08:13 +00:00
{
2006-03-31 12:04:14 +00:00
{ TOKEN_LSHIFT, XP_AWK_BINOP_LSHIFT },
{ TOKEN_RSHIFT, XP_AWK_BINOP_RSHIFT },
{ TOKEN_EOF, 0 }
};
2006-02-08 16:14:31 +00:00
2006-03-31 12:04:14 +00:00
return __parse_binary_expr (awk, map, __parse_additive);
2006-02-08 16:14:31 +00:00
}
2006-01-12 14:20:17 +00:00
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_additive (xp_awk_t* awk)
2006-01-10 13:57:54 +00:00
{
2006-03-31 12:04:14 +00:00
__binmap_t map[] =
2006-03-04 10:08:13 +00:00
{
2006-03-31 12:04:14 +00:00
{ TOKEN_PLUS, XP_AWK_BINOP_PLUS },
{ TOKEN_MINUS, XP_AWK_BINOP_MINUS },
{ TOKEN_EOF, 0 }
};
2006-01-10 13:57:54 +00:00
2006-03-31 12:04:14 +00:00
return __parse_binary_expr (awk, map, __parse_multiplicative);
2006-01-10 13:57:54 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_multiplicative (xp_awk_t* awk)
2006-01-10 13:57:54 +00:00
{
2006-03-31 12:04:14 +00:00
__binmap_t map[] =
{
{ TOKEN_MUL, XP_AWK_BINOP_MUL },
{ TOKEN_DIV, XP_AWK_BINOP_DIV },
{ TOKEN_MOD, XP_AWK_BINOP_MOD },
2006-04-11 15:44:30 +00:00
{ TOKEN_EXP, XP_AWK_BINOP_EXP },
2006-03-31 12:04:14 +00:00
{ TOKEN_EOF, 0 }
};
return __parse_binary_expr (awk, map, __parse_unary);
2006-04-02 12:45:04 +00:00
}
static xp_awk_nde_t* __parse_unary (xp_awk_t* awk)
{
xp_awk_nde_exp_t* nde;
xp_awk_nde_t* left;
2006-01-12 14:20:17 +00:00
int opcode;
2006-01-10 13:57:54 +00:00
2006-04-02 12:45:04 +00:00
opcode = (MATCH(awk,TOKEN_PLUS))? XP_AWK_UNROP_PLUS:
(MATCH(awk,TOKEN_MINUS))? XP_AWK_UNROP_MINUS:
(MATCH(awk,TOKEN_NOT))? XP_AWK_UNROP_NOT:
2006-04-12 03:54:12 +00:00
(MATCH(awk,TOKEN_TILDE))? XP_AWK_UNROP_BNOT: -1;
2006-04-02 12:45:04 +00:00
if (opcode == -1) return __parse_increment (awk);
if (__get_token(awk) == -1) return XP_NULL;
2006-01-25 14:50:57 +00:00
left = __parse_unary (awk);
2006-01-10 13:57:54 +00:00
if (left == XP_NULL) return XP_NULL;
2006-04-02 12:45:04 +00:00
nde = (xp_awk_nde_exp_t*)
xp_malloc (xp_sizeof(xp_awk_nde_exp_t));
if (nde == XP_NULL)
2006-03-04 10:08:13 +00:00
{
2006-04-02 12:45:04 +00:00
xp_awk_clrpt (left);
PANIC (awk, XP_AWK_ENOMEM);
}
2006-01-10 13:57:54 +00:00
2006-04-02 12:45:04 +00:00
nde->type = XP_AWK_NDE_EXP_UNR;
nde->next = XP_NULL;
nde->opcode = opcode;
nde->left = left;
nde->right = XP_NULL;
2006-01-14 14:09:52 +00:00
2006-04-02 12:45:04 +00:00
return (xp_awk_nde_t*)nde;
}
2006-01-12 14:20:17 +00:00
2006-04-02 12:45:04 +00:00
static xp_awk_nde_t* __parse_increment (xp_awk_t* awk)
{
xp_awk_nde_exp_t* nde;
xp_awk_nde_t* left;
int type, opcode, opcode1, opcode2;
2006-01-25 04:27:01 +00:00
2006-04-02 12:45:04 +00:00
opcode1 = MATCH(awk,TOKEN_PLUSPLUS)? XP_AWK_INCOP_PLUS:
MATCH(awk,TOKEN_MINUSMINUS)? XP_AWK_INCOP_MINUS: -1;
2006-01-25 04:27:01 +00:00
2006-04-02 12:45:04 +00:00
if (opcode1 != -1)
{
if (__get_token(awk) == -1) return XP_NULL;
}
2006-01-25 04:27:01 +00:00
2006-04-02 12:45:04 +00:00
left = __parse_primary (awk);
if (left == XP_NULL) return XP_NULL;
2006-01-12 14:20:17 +00:00
2006-04-02 12:45:04 +00:00
opcode2 = MATCH(awk,TOKEN_PLUSPLUS)? XP_AWK_INCOP_PLUS:
MATCH(awk,TOKEN_MINUSMINUS)? XP_AWK_INCOP_MINUS: -1;
2006-01-12 14:20:17 +00:00
2006-04-02 12:45:04 +00:00
if (opcode1 != -1 && opcode2 != -1)
{
xp_awk_clrpt (left);
PANIC (awk, XP_AWK_ELVALUE);
}
else if (opcode1 == -1 && opcode2 == -1)
{
return left;
2006-01-10 13:57:54 +00:00
}
2006-04-02 12:45:04 +00:00
else if (opcode1 != -1)
{
type = XP_AWK_NDE_EXP_INCPRE;
opcode = opcode1;
}
else if (opcode2 != -1)
{
type = XP_AWK_NDE_EXP_INCPST;
opcode = opcode2;
2006-01-10 13:57:54 +00:00
2006-04-02 12:45:04 +00:00
if (__get_token(awk) == -1) return XP_NULL;
}
2006-01-10 13:57:54 +00:00
2006-04-02 12:45:04 +00:00
nde = (xp_awk_nde_exp_t*)
xp_malloc (xp_sizeof(xp_awk_nde_exp_t));
if (nde == XP_NULL)
2006-03-31 12:04:14 +00:00
{
2006-04-02 12:45:04 +00:00
xp_awk_clrpt (left);
PANIC (awk, XP_AWK_ENOMEM);
2006-03-31 12:04:14 +00:00
}
2006-04-02 12:45:04 +00:00
nde->type = type;
nde->next = XP_NULL;
nde->opcode = opcode;
nde->left = left;
nde->right = XP_NULL;
return (xp_awk_nde_t*)nde;
2006-01-10 13:57:54 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_primary (xp_awk_t* awk)
2006-01-10 13:57:54 +00:00
{
2006-04-05 15:56:20 +00:00
if (MATCH(awk,TOKEN_IDENT))
{
2006-01-31 16:57:45 +00:00
xp_char_t* name_dup;
2006-01-13 14:16:56 +00:00
2006-01-31 16:57:45 +00:00
name_dup = (xp_char_t*)xp_strdup(XP_STR_BUF(&awk->token.name));
if (name_dup == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
2006-01-14 14:09:52 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-31 16:57:45 +00:00
xp_free (name_dup);
2006-01-25 14:50:57 +00:00
return XP_NULL;
2006-01-13 14:16:56 +00:00
}
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_LBRACK))
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* nde;
nde = __parse_hashidx (awk, name_dup);
if (nde == XP_NULL) xp_free (name_dup);
return (xp_awk_nde_t*)nde;
2006-01-19 16:28:21 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_LPAREN))
{
2006-01-13 14:16:56 +00:00
/* function call */
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* nde;
nde = __parse_funcall (awk, name_dup);
if (nde == XP_NULL) xp_free (name_dup);
return (xp_awk_nde_t*)nde;
2006-01-13 14:16:56 +00:00
}
2006-03-04 10:08:13 +00:00
else
{
2006-01-13 14:16:56 +00:00
/* normal variable */
2006-03-03 11:45:45 +00:00
xp_awk_nde_var_t* nde;
2006-01-24 16:14:28 +00:00
xp_size_t idxa;
2006-01-13 14:16:56 +00:00
2006-03-03 11:45:45 +00:00
nde = (xp_awk_nde_var_t*)xp_malloc(xp_sizeof(xp_awk_nde_var_t));
2006-03-04 10:08:13 +00:00
if (nde == XP_NULL)
{
2006-01-31 16:57:45 +00:00
xp_free (name_dup);
2006-01-13 14:16:56 +00:00
PANIC (awk, XP_AWK_ENOMEM);
}
2006-01-31 16:57:45 +00:00
/* search the parameter name list */
2006-02-01 02:56:12 +00:00
idxa = xp_awk_tab_find(&awk->parse.params, name_dup, 0);
2006-03-04 10:08:13 +00:00
if (idxa != (xp_size_t)-1)
{
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_ARG;
nde->next = XP_NULL;
2006-04-14 10:56:42 +00:00
/*nde->id.name = XP_NULL;*/
2006-03-03 11:45:45 +00:00
nde->id.name = name_dup;
nde->id.idxa = idxa;
2006-04-16 16:30:59 +00:00
nde->idx = XP_NULL;
2006-01-31 16:57:45 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-01-31 16:57:45 +00:00
}
2006-02-05 13:45:59 +00:00
/* search the local variable list */
2006-02-05 14:21:18 +00:00
idxa = xp_awk_tab_rrfind(&awk->parse.locals, name_dup, 0);
2006-03-04 10:08:13 +00:00
if (idxa != (xp_size_t)-1)
{
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_LOCAL;
nde->next = XP_NULL;
2006-04-14 10:56:42 +00:00
/*nde->id.name = XP_NULL;*/
2006-03-03 11:45:45 +00:00
nde->id.name = name_dup;
nde->id.idxa = idxa;
2006-04-16 16:30:59 +00:00
nde->idx = XP_NULL;
2006-02-05 13:45:59 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-01-24 16:14:28 +00:00
}
2006-01-13 14:16:56 +00:00
2006-02-05 13:45:59 +00:00
/* search the global variable list */
2006-02-05 16:00:33 +00:00
idxa = xp_awk_tab_rrfind(&awk->parse.globals, name_dup, 0);
2006-03-04 10:08:13 +00:00
if (idxa != (xp_size_t)-1)
{
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_GLOBAL;
nde->next = XP_NULL;
2006-04-14 10:56:42 +00:00
/*nde->id.name = XP_NULL;*/
2006-03-03 11:45:45 +00:00
nde->id.name = name_dup;
nde->id.idxa = idxa;
2006-04-16 16:30:59 +00:00
nde->idx = XP_NULL;
2006-02-05 16:00:33 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-02-05 16:00:33 +00:00
}
2006-02-05 13:45:59 +00:00
2006-03-04 10:08:13 +00:00
if (awk->opt.parse & XP_AWK_IMPLICIT)
{
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_NAMED;
nde->next = XP_NULL;
nde->id.name = name_dup;
nde->id.idxa = (xp_size_t)-1;
2006-04-16 16:30:59 +00:00
nde->idx = XP_NULL;
2006-02-05 16:00:33 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-02-05 13:45:59 +00:00
}
/* undefined variable */
xp_free (name_dup);
2006-03-03 11:45:45 +00:00
xp_free (nde);
2006-02-05 13:45:59 +00:00
PANIC (awk, XP_AWK_EUNDEF);
2006-01-13 14:16:56 +00:00
}
}
2006-03-31 12:04:14 +00:00
else if (MATCH(awk,TOKEN_INT))
2006-03-04 10:08:13 +00:00
{
2006-03-05 17:07:33 +00:00
xp_awk_nde_int_t* nde;
2006-01-13 14:16:56 +00:00
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_int_t*)xp_malloc(xp_sizeof(xp_awk_nde_int_t));
2006-03-03 11:45:45 +00:00
if (nde == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
2006-01-10 13:57:54 +00:00
2006-03-05 17:07:33 +00:00
nde->type = XP_AWK_NDE_INT;
2006-03-03 11:45:45 +00:00
nde->next = XP_NULL;
2006-04-16 04:31:38 +00:00
nde->val = xp_awk_strtolong (
XP_STR_BUF(&awk->token.name), 0, XP_NULL);
2006-03-05 17:07:33 +00:00
xp_assert (
XP_STR_LEN(&awk->token.name) ==
xp_strlen(XP_STR_BUF(&awk->token.name)));
2006-01-10 13:57:54 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-03-03 11:45:45 +00:00
xp_free (nde);
2006-01-14 14:09:52 +00:00
return XP_NULL;
}
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-01-10 13:57:54 +00:00
}
2006-04-05 15:56:20 +00:00
else if (MATCH(awk,TOKEN_REAL))
{
2006-03-31 12:04:14 +00:00
xp_awk_nde_real_t* nde;
nde = (xp_awk_nde_real_t*)
xp_malloc (xp_sizeof(xp_awk_nde_real_t));
if (nde == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
nde->type = XP_AWK_NDE_REAL;
nde->next = XP_NULL;
2006-04-04 16:03:14 +00:00
nde->val = xp_awk_strtoreal (XP_STR_BUF(&awk->token.name));
2006-03-31 12:04:14 +00:00
xp_assert (
XP_STR_LEN(&awk->token.name) ==
xp_strlen(XP_STR_BUF(&awk->token.name)));
if (__get_token(awk) == -1)
{
xp_free (nde);
return XP_NULL;
}
return (xp_awk_nde_t*)nde;
2006-03-05 17:07:33 +00:00
}
2006-04-07 04:23:11 +00:00
else if (MATCH(awk,TOKEN_STR))
2006-04-05 15:56:20 +00:00
{
2006-03-05 17:07:33 +00:00
xp_awk_nde_str_t* nde;
2006-01-13 11:25:52 +00:00
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_str_t*)xp_malloc(xp_sizeof(xp_awk_nde_str_t));
2006-03-03 11:45:45 +00:00
if (nde == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
2006-01-10 13:57:54 +00:00
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_STR;
nde->next = XP_NULL;
2006-03-05 17:07:33 +00:00
nde->len = XP_STR_LEN(&awk->token.name);
nde->buf = xp_strxdup(XP_STR_BUF(&awk->token.name), nde->len);
if (nde->buf == XP_NULL)
2006-03-04 10:08:13 +00:00
{
2006-03-03 11:45:45 +00:00
xp_free (nde);
2006-01-12 14:20:17 +00:00
PANIC (awk, XP_AWK_ENOMEM);
}
2006-01-10 13:57:54 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-03-05 17:07:33 +00:00
xp_free (nde->buf);
2006-03-03 11:45:45 +00:00
xp_free (nde);
2006-01-14 14:09:52 +00:00
return XP_NULL;
}
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-01-10 13:57:54 +00:00
}
2006-04-10 15:52:07 +00:00
else if (MATCH(awk,TOKEN_REGEX))
{
2006-04-14 10:56:42 +00:00
/* TODO: .... */
2006-04-10 15:52:07 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_DOLLAR))
{
2006-03-04 15:54:37 +00:00
xp_awk_nde_pos_t* nde;
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* prim;
2006-01-25 14:50:57 +00:00
if (__get_token(awk)) return XP_NULL;
prim = __parse_primary (awk);
if (prim == XP_NULL) return XP_NULL;
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_pos_t*)xp_malloc(xp_sizeof(xp_awk_nde_pos_t));
2006-03-04 10:08:13 +00:00
if (nde == XP_NULL)
{
2006-01-25 14:50:57 +00:00
xp_awk_clrpt (prim);
PANIC (awk, XP_AWK_ENOMEM);
}
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_POS;
nde->next = XP_NULL;
2006-03-05 17:07:33 +00:00
nde->val = prim;
2006-01-25 14:50:57 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-01-25 14:50:57 +00:00
}
2006-03-04 10:08:13 +00:00
else if (MATCH(awk,TOKEN_LPAREN))
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* nde;
2006-01-10 13:57:54 +00:00
2006-01-14 14:09:52 +00:00
/* eat up the left parenthesis */
if (__get_token(awk) == -1) return XP_NULL;
/* parse the sub-expression inside the parentheses */
2006-03-03 11:45:45 +00:00
nde = __parse_expression (awk);
if (nde == XP_NULL) return XP_NULL;
2006-01-10 13:57:54 +00:00
2006-01-14 14:09:52 +00:00
/* check for the closing parenthesis */
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_RPAREN))
{
2006-03-03 11:45:45 +00:00
xp_awk_clrpt (nde);
2006-01-13 11:25:52 +00:00
PANIC (awk, XP_AWK_ERPAREN);
2006-01-11 14:03:17 +00:00
}
2006-01-14 14:09:52 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-03-03 11:45:45 +00:00
xp_awk_clrpt (nde);
2006-01-14 14:09:52 +00:00
return XP_NULL;
}
2006-01-11 14:03:17 +00:00
2006-03-03 11:45:45 +00:00
return nde;
2006-01-10 13:57:54 +00:00
}
/* valid expression introducer is expected */
2006-03-04 15:54:37 +00:00
PANIC (awk, XP_AWK_EEXPRESSION);
2006-01-10 13:57:54 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_hashidx (xp_awk_t* awk, xp_char_t* name)
2006-01-19 16:28:21 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* idx;
2006-04-16 16:30:59 +00:00
xp_awk_nde_var_t* nde;
2006-01-31 16:57:45 +00:00
xp_size_t idxa;
2006-01-19 16:28:21 +00:00
if (__get_token(awk) == -1) return XP_NULL;
idx = __parse_expression (awk);
if (idx == XP_NULL) return XP_NULL;
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_RBRACK))
{
2006-01-19 16:28:21 +00:00
xp_awk_clrpt (idx);
PANIC (awk, XP_AWK_ERBRACK);
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-19 16:28:21 +00:00
xp_awk_clrpt (idx);
return XP_NULL;
}
2006-04-16 16:30:59 +00:00
nde = (xp_awk_nde_var_t*)xp_malloc(xp_sizeof(xp_awk_nde_var_t));
2006-03-04 10:08:13 +00:00
if (nde == XP_NULL)
{
2006-01-19 16:28:21 +00:00
xp_awk_clrpt (idx);
PANIC (awk, XP_AWK_ENOMEM);
}
2006-01-31 16:57:45 +00:00
/* search the parameter name list */
2006-02-05 14:21:18 +00:00
idxa = xp_awk_tab_find(&awk->parse.params, name, 0);
2006-03-04 10:08:13 +00:00
if (idxa != (xp_size_t)-1)
{
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_ARGIDX;
nde->next = XP_NULL;
2006-04-14 10:56:42 +00:00
/*nde->id.name = XP_NULL; */
2006-03-03 11:45:45 +00:00
nde->id.name = name;
nde->id.idxa = idxa;
nde->idx = idx;
2006-01-31 16:57:45 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-01-31 16:57:45 +00:00
}
2006-02-05 14:21:18 +00:00
/* search the local variable list */
idxa = xp_awk_tab_rrfind(&awk->parse.locals, name, 0);
2006-03-04 10:08:13 +00:00
if (idxa != (xp_size_t)-1)
{
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_LOCALIDX;
nde->next = XP_NULL;
2006-04-14 10:56:42 +00:00
/*nde->id.name = XP_NULL; */
2006-03-03 11:45:45 +00:00
nde->id.name = name;
nde->id.idxa = idxa;
nde->idx = idx;
2006-01-19 16:28:21 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-02-05 14:21:18 +00:00
}
/* search the global variable list */
2006-02-05 16:00:33 +00:00
idxa = xp_awk_tab_rrfind(&awk->parse.globals, name, 0);
2006-03-04 10:08:13 +00:00
if (idxa != (xp_size_t)-1)
{
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_GLOBALIDX;
nde->next = XP_NULL;
2006-04-14 10:56:42 +00:00
/*nde->id.name = XP_NULL;*/
2006-03-03 11:45:45 +00:00
nde->id.name = name;
nde->id.idxa = idxa;
2006-04-16 16:30:59 +00:00
nde->idx = idx;
2006-02-05 16:00:33 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-02-05 16:00:33 +00:00
}
2006-02-05 14:21:18 +00:00
2006-03-04 10:08:13 +00:00
if (awk->opt.parse & XP_AWK_IMPLICIT)
{
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_NAMEDIDX;
nde->next = XP_NULL;
nde->id.name = name;
nde->id.idxa = (xp_size_t)-1;
nde->idx = idx;
2006-02-05 16:00:33 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-02-05 14:21:18 +00:00
}
/* undefined variable */
xp_awk_clrpt (idx);
2006-03-03 11:45:45 +00:00
xp_free (nde);
2006-02-05 14:21:18 +00:00
PANIC (awk, XP_AWK_EUNDEF);
2006-01-19 16:28:21 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_funcall (xp_awk_t* awk, xp_char_t* name)
2006-01-13 14:16:56 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* head, * curr, * nde;
xp_awk_nde_call_t* call;
2006-01-13 14:16:56 +00:00
2006-01-14 14:09:52 +00:00
if (__get_token(awk) == -1) return XP_NULL;
2006-01-14 16:09:58 +00:00
head = curr = XP_NULL;
2006-01-13 14:16:56 +00:00
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_RPAREN))
{
2006-01-18 16:12:59 +00:00
/* no parameters to the function call */
if (__get_token(awk) == -1) return XP_NULL;
}
2006-03-04 10:08:13 +00:00
else
{
while (1)
{
2006-03-03 11:45:45 +00:00
nde = __parse_expression (awk);
2006-03-04 10:08:13 +00:00
if (nde == XP_NULL)
{
2006-01-14 16:09:58 +00:00
if (head != XP_NULL) xp_awk_clrpt (head);
return XP_NULL;
}
2006-03-03 11:45:45 +00:00
if (head == XP_NULL) head = nde;
else curr->next = nde;
curr = nde;
2006-01-14 16:09:58 +00:00
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_RPAREN))
{
if (__get_token(awk) == -1)
{
2006-01-14 16:09:58 +00:00
if (head != XP_NULL) xp_awk_clrpt (head);
return XP_NULL;
}
break;
}
2006-01-13 14:16:56 +00:00
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_COMMA))
{
2006-01-14 16:09:58 +00:00
if (head != XP_NULL) xp_awk_clrpt (head);
PANIC (awk, XP_AWK_ECOMMA);
}
2006-01-13 14:16:56 +00:00
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-14 16:09:58 +00:00
if (head != XP_NULL) xp_awk_clrpt (head);
2006-01-14 14:09:52 +00:00
return XP_NULL;
}
2006-01-13 14:16:56 +00:00
}
2006-01-14 16:09:58 +00:00
}
2006-03-05 17:07:33 +00:00
call = (xp_awk_nde_call_t*)xp_malloc(xp_sizeof(xp_awk_nde_call_t));
2006-03-04 10:08:13 +00:00
if (call == XP_NULL)
{
2006-01-14 16:09:58 +00:00
if (head != XP_NULL) xp_awk_clrpt (head);
PANIC (awk, XP_AWK_ENOMEM);
}
2006-03-03 11:45:45 +00:00
call->type = XP_AWK_NDE_CALL;
2006-01-14 16:09:58 +00:00
call->next = XP_NULL;
call->name = name;
call->args = head;
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)call;
2006-01-14 16:09:58 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_if (xp_awk_t* awk)
2006-01-14 16:09:58 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* test;
xp_awk_nde_t* then_part;
xp_awk_nde_t* else_part;
xp_awk_nde_if_t* nde;
2006-01-14 16:09:58 +00:00
if (!MATCH(awk,TOKEN_LPAREN)) PANIC (awk, XP_AWK_ELPAREN);
if (__get_token(awk) == -1) return XP_NULL;
2006-01-13 14:16:56 +00:00
2006-01-14 16:09:58 +00:00
test = __parse_expression (awk);
if (test == XP_NULL) return XP_NULL;
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_RPAREN))
{
2006-01-14 16:09:58 +00:00
xp_awk_clrpt (test);
PANIC (awk, XP_AWK_ERPAREN);
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-14 16:09:58 +00:00
xp_awk_clrpt (test);
return XP_NULL;
}
then_part = __parse_statement (awk);
2006-03-04 10:08:13 +00:00
if (then_part == XP_NULL)
{
2006-01-14 16:09:58 +00:00
xp_awk_clrpt (test);
return XP_NULL;
}
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_ELSE))
{
if (__get_token(awk) == -1)
{
2006-01-14 16:09:58 +00:00
xp_awk_clrpt (then_part);
xp_awk_clrpt (test);
return XP_NULL;
}
else_part = __parse_statement (awk);
2006-03-04 10:08:13 +00:00
if (else_part == XP_NULL)
{
2006-01-14 16:09:58 +00:00
xp_awk_clrpt (then_part);
xp_awk_clrpt (test);
2006-01-14 14:09:52 +00:00
return XP_NULL;
}
2006-01-13 14:16:56 +00:00
}
2006-01-14 16:09:58 +00:00
else else_part = XP_NULL;
2006-01-13 14:16:56 +00:00
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_if_t*)xp_malloc(xp_sizeof(xp_awk_nde_if_t));
2006-03-04 10:08:13 +00:00
if (nde == XP_NULL)
{
2006-01-14 16:09:58 +00:00
xp_awk_clrpt (else_part);
xp_awk_clrpt (then_part);
xp_awk_clrpt (test);
PANIC (awk, XP_AWK_ENOMEM);
}
2006-01-14 14:09:52 +00:00
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_IF;
nde->next = XP_NULL;
nde->test = test;
nde->then_part = then_part;
nde->else_part = else_part;
2006-01-14 14:09:52 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-01-13 14:16:56 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_while (xp_awk_t* awk)
2006-01-09 12:51:47 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* test, * body;
xp_awk_nde_while_t* nde;
2006-01-18 16:12:59 +00:00
if (!MATCH(awk,TOKEN_LPAREN)) PANIC (awk, XP_AWK_ELPAREN);
if (__get_token(awk) == -1) return XP_NULL;
test = __parse_expression (awk);
if (test == XP_NULL) return XP_NULL;
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_RPAREN))
{
2006-01-18 16:12:59 +00:00
xp_awk_clrpt (test);
PANIC (awk, XP_AWK_ERPAREN);
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-18 16:12:59 +00:00
xp_awk_clrpt (test);
return XP_NULL;
}
body = __parse_statement (awk);
2006-03-04 10:08:13 +00:00
if (body == XP_NULL)
{
2006-01-18 16:12:59 +00:00
xp_awk_clrpt (test);
return XP_NULL;
}
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_while_t*)xp_malloc(xp_sizeof(xp_awk_nde_while_t));
2006-03-04 10:08:13 +00:00
if (nde == XP_NULL)
{
2006-01-18 16:12:59 +00:00
xp_awk_clrpt (body);
xp_awk_clrpt (test);
PANIC (awk, XP_AWK_ENOMEM);
}
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_WHILE;
nde->next = XP_NULL;
nde->test = test;
nde->body = body;
2006-01-18 16:12:59 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-01-09 12:51:47 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_for (xp_awk_t* awk)
2006-01-09 12:51:47 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* init, * test, * incr, * body;
xp_awk_nde_for_t* nde;
2006-01-19 13:28:29 +00:00
2006-04-14 10:56:42 +00:00
/* TODO: parse for (x in list) ... */
2006-01-25 04:41:56 +00:00
2006-01-19 13:28:29 +00:00
if (!MATCH(awk,TOKEN_LPAREN)) PANIC (awk, XP_AWK_ELPAREN);
if (__get_token(awk) == -1) return XP_NULL;
if (MATCH(awk,TOKEN_SEMICOLON)) init = XP_NULL;
2006-03-04 10:08:13 +00:00
else
{
2006-01-19 13:28:29 +00:00
init = __parse_expression (awk);
if (init == XP_NULL) return XP_NULL;
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_SEMICOLON))
{
2006-01-19 13:28:29 +00:00
xp_awk_clrpt (init);
PANIC (awk, XP_AWK_ESEMICOLON);
}
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-19 13:28:29 +00:00
xp_awk_clrpt (init);
return XP_NULL;
}
if (MATCH(awk,TOKEN_SEMICOLON)) test = XP_NULL;
2006-03-04 10:08:13 +00:00
else
{
2006-01-19 13:28:29 +00:00
test = __parse_expression (awk);
2006-03-04 10:08:13 +00:00
if (test == XP_NULL)
{
2006-01-19 13:28:29 +00:00
xp_awk_clrpt (init);
return XP_NULL;
}
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_SEMICOLON))
{
2006-01-19 13:28:29 +00:00
xp_awk_clrpt (init);
xp_awk_clrpt (test);
PANIC (awk, XP_AWK_ESEMICOLON);
}
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-19 13:28:29 +00:00
xp_awk_clrpt (init);
xp_awk_clrpt (test);
return XP_NULL;
}
if (MATCH(awk,TOKEN_RPAREN)) incr = XP_NULL;
2006-03-04 10:08:13 +00:00
else
{
2006-01-19 13:28:29 +00:00
incr = __parse_expression (awk);
2006-03-04 10:08:13 +00:00
if (incr == XP_NULL)
{
2006-01-19 13:28:29 +00:00
xp_awk_clrpt (init);
xp_awk_clrpt (test);
return XP_NULL;
}
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_RPAREN))
{
2006-01-19 13:28:29 +00:00
xp_awk_clrpt (init);
xp_awk_clrpt (test);
xp_awk_clrpt (incr);
PANIC (awk, XP_AWK_ERPAREN);
}
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-19 13:28:29 +00:00
xp_awk_clrpt (init);
xp_awk_clrpt (test);
xp_awk_clrpt (incr);
return XP_NULL;
}
body = __parse_statement (awk);
2006-03-04 10:08:13 +00:00
if (body == XP_NULL)
{
2006-01-19 13:28:29 +00:00
xp_awk_clrpt (init);
xp_awk_clrpt (test);
xp_awk_clrpt (incr);
return XP_NULL;
}
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_for_t*)xp_malloc(xp_sizeof(xp_awk_nde_for_t));
2006-03-04 10:08:13 +00:00
if (nde == XP_NULL)
{
2006-01-19 13:28:29 +00:00
xp_awk_clrpt (init);
xp_awk_clrpt (test);
xp_awk_clrpt (incr);
xp_awk_clrpt (body);
PANIC (awk, XP_AWK_ENOMEM);
}
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_FOR;
nde->next = XP_NULL;
nde->init = init;
nde->test = test;
nde->incr = incr;
nde->body = body;
2006-01-19 13:28:29 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-01-09 12:51:47 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_dowhile (xp_awk_t* awk)
2006-01-09 12:51:47 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* test, * body;
xp_awk_nde_while_t* nde;
2006-01-19 10:56:35 +00:00
body = __parse_statement (awk);
if (body == XP_NULL) return XP_NULL;
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_WHILE))
{
2006-01-19 10:56:35 +00:00
xp_awk_clrpt (body);
PANIC (awk, XP_AWK_EWHILE);
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-19 10:56:35 +00:00
xp_awk_clrpt (body);
return XP_NULL;
}
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_LPAREN))
{
2006-01-19 10:56:35 +00:00
xp_awk_clrpt (body);
PANIC (awk, XP_AWK_ELPAREN);
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-19 10:56:35 +00:00
xp_awk_clrpt (body);
return XP_NULL;
}
test = __parse_expression (awk);
2006-03-04 10:08:13 +00:00
if (test == XP_NULL)
{
2006-01-19 10:56:35 +00:00
xp_awk_clrpt (body);
return XP_NULL;
}
2006-03-04 10:08:13 +00:00
if (!MATCH(awk,TOKEN_RPAREN))
{
2006-01-19 10:56:35 +00:00
xp_awk_clrpt (body);
xp_awk_clrpt (test);
PANIC (awk, XP_AWK_ERPAREN);
}
2006-03-04 10:08:13 +00:00
if (__get_token(awk) == -1)
{
2006-01-19 10:56:35 +00:00
xp_awk_clrpt (body);
xp_awk_clrpt (test);
return XP_NULL;
}
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_while_t*)xp_malloc(xp_sizeof(xp_awk_nde_while_t));
2006-03-04 10:08:13 +00:00
if (nde == XP_NULL)
{
2006-01-19 10:56:35 +00:00
xp_awk_clrpt (body);
xp_awk_clrpt (test);
PANIC (awk, XP_AWK_ENOMEM);
}
2006-03-03 11:45:45 +00:00
nde->type = XP_AWK_NDE_DOWHILE;
nde->next = XP_NULL;
nde->test = test;
nde->body = body;
2006-01-19 10:56:35 +00:00
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-01-09 12:51:47 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_break (xp_awk_t* awk)
2006-01-09 12:51:47 +00:00
{
2006-03-04 15:54:37 +00:00
xp_awk_nde_break_t* nde;
2006-01-09 12:51:47 +00:00
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_break_t*)xp_malloc(xp_sizeof(xp_awk_nde_break_t));
2006-03-03 11:45:45 +00:00
if (nde == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
nde->type = XP_AWK_NDE_BREAK;
nde->next = XP_NULL;
2006-01-09 12:51:47 +00:00
2006-03-04 15:54:37 +00:00
return (xp_awk_nde_t*)nde;
2006-01-09 12:51:47 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_continue (xp_awk_t* awk)
2006-01-09 12:51:47 +00:00
{
2006-03-04 15:54:37 +00:00
xp_awk_nde_continue_t* nde;
2006-01-09 12:51:47 +00:00
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_continue_t*)xp_malloc(xp_sizeof(xp_awk_nde_continue_t));
2006-03-03 11:45:45 +00:00
if (nde == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
nde->type = XP_AWK_NDE_CONTINUE;
nde->next = XP_NULL;
2006-01-09 12:51:47 +00:00
2006-03-04 15:54:37 +00:00
return (xp_awk_nde_t*)nde;
2005-11-15 15:59:23 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_return (xp_awk_t* awk)
2006-01-14 14:09:52 +00:00
{
2006-03-04 15:54:37 +00:00
xp_awk_nde_return_t* nde;
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* val;
2006-01-14 14:09:52 +00:00
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_return_t*)xp_malloc(xp_sizeof(xp_awk_nde_return_t));
2006-03-03 11:45:45 +00:00
if (nde == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
nde->type = XP_AWK_NDE_RETURN;
nde->next = XP_NULL;
2006-01-14 14:09:52 +00:00
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_SEMICOLON))
{
2006-01-28 06:38:01 +00:00
/* no return value */
val = XP_NULL;
}
2006-03-04 10:08:13 +00:00
else
{
2006-01-28 06:38:01 +00:00
val = __parse_expression (awk);
2006-03-04 10:08:13 +00:00
if (val == XP_NULL)
{
2006-03-03 11:45:45 +00:00
xp_free (nde);
2006-01-28 06:38:01 +00:00
return XP_NULL;
}
2006-01-14 14:09:52 +00:00
}
2006-03-05 17:07:33 +00:00
nde->val = val;
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-01-14 14:09:52 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_exit (xp_awk_t* awk)
2006-01-14 14:09:52 +00:00
{
2006-03-04 15:54:37 +00:00
xp_awk_nde_exit_t* nde;
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* val;
2006-01-14 14:09:52 +00:00
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_exit_t*)xp_malloc(xp_sizeof(xp_awk_nde_exit_t));
2006-03-03 11:45:45 +00:00
if (nde == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
nde->type = XP_AWK_NDE_EXIT;
nde->next = XP_NULL;
2006-01-14 14:09:52 +00:00
2006-03-04 10:08:13 +00:00
if (MATCH(awk,TOKEN_SEMICOLON))
{
2006-01-28 06:38:01 +00:00
/* no exit code */
val = XP_NULL;
}
2006-03-04 10:08:13 +00:00
else
{
2006-01-28 06:38:01 +00:00
val = __parse_expression (awk);
2006-03-04 10:08:13 +00:00
if (val == XP_NULL)
{
2006-03-03 11:45:45 +00:00
xp_free (nde);
2006-01-28 06:38:01 +00:00
return XP_NULL;
}
2006-01-14 14:09:52 +00:00
}
2006-03-05 17:07:33 +00:00
nde->val = val;
2006-03-03 11:45:45 +00:00
return (xp_awk_nde_t*)nde;
2006-01-14 14:09:52 +00:00
}
2006-03-31 16:35:37 +00:00
static xp_awk_nde_t* __parse_delete (xp_awk_t* awk)
{
2006-04-14 10:56:42 +00:00
/* TODO: implement this... */
2006-03-31 16:35:37 +00:00
return XP_NULL;
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_next (xp_awk_t* awk)
2006-01-20 07:33:46 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* nde;
2006-01-20 07:33:46 +00:00
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_t*)xp_malloc(xp_sizeof(xp_awk_nde_t));
2006-03-03 11:45:45 +00:00
if (nde == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
nde->type = XP_AWK_NDE_NEXT;
nde->next = XP_NULL;
2006-01-20 07:33:46 +00:00
2006-03-03 11:45:45 +00:00
return nde;
2006-01-20 07:33:46 +00:00
}
2006-03-03 11:45:45 +00:00
static xp_awk_nde_t* __parse_nextfile (xp_awk_t* awk)
2006-01-20 07:33:46 +00:00
{
2006-03-03 11:45:45 +00:00
xp_awk_nde_t* nde;
2006-01-20 07:33:46 +00:00
2006-03-05 17:07:33 +00:00
nde = (xp_awk_nde_t*)xp_malloc(xp_sizeof(xp_awk_nde_t));
2006-03-03 11:45:45 +00:00
if (nde == XP_NULL) PANIC (awk, XP_AWK_ENOMEM);
nde->type = XP_AWK_NDE_NEXTFILE;
nde->next = XP_NULL;
2006-01-20 07:33:46 +00:00
2006-03-03 11:45:45 +00:00
return nde;
2006-01-20 07:33:46 +00:00
}
2005-11-14 15:23:54 +00:00
static int __get_token (xp_awk_t* awk)
{
xp_cint_t c;
int n;
2006-04-07 04:23:11 +00:00
do
{
2005-11-14 15:23:54 +00:00
if (__skip_spaces(awk) == -1) return -1;
if ((n = __skip_comment(awk)) == -1) return -1;
2006-04-07 04:23:11 +00:00
}
while (n == 1);
2005-11-14 15:23:54 +00:00
xp_str_clear (&awk->token.name);
c = awk->lex.curc;
2006-03-04 10:08:13 +00:00
if (c == XP_CHAR_EOF)
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_EOF);
}
2006-03-04 10:08:13 +00:00
else if (xp_isdigit(c))
{
2006-04-04 06:26:56 +00:00
if (__get_number(awk) == -1) return -1;
2005-11-14 15:23:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (xp_isalpha(c) || c == XP_CHAR('_'))
{
2005-11-15 15:32:39 +00:00
/* identifier */
2006-04-07 04:23:11 +00:00
do
{
2005-11-15 15:32:39 +00:00
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
2006-04-07 04:23:11 +00:00
}
while (xp_isalpha(c) || c == XP_CHAR('_') || xp_isdigit(c));
2005-11-15 15:32:39 +00:00
2006-04-07 16:52:42 +00:00
SET_TOKEN_TYPE (awk, __classify_ident(awk,XP_STR_BUF(&awk->token.name)));
2005-11-14 15:23:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('\"'))
{
2006-04-07 04:23:11 +00:00
SET_TOKEN_TYPE (awk, TOKEN_STR);
2006-01-11 14:03:17 +00:00
2006-04-07 04:23:11 +00:00
if (__get_string(awk) == -1) return -1;
while (1)
{
do
{
if (__skip_spaces(awk) == -1) return -1;
if ((n = __skip_comment(awk)) == -1) return -1;
}
while (n == 1);
c = awk->lex.curc;
if (c != XP_CHAR('\"')) break;
if (__get_string(awk) == -1) return -1;
}
2005-11-15 15:32:39 +00:00
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('='))
{
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-03-04 10:08:13 +00:00
if (c == XP_CHAR('='))
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_EQ);
ADD_TOKEN_STR (awk, XP_TEXT("=="));
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_ASSIGN);
ADD_TOKEN_STR (awk, XP_TEXT("="));
}
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('!'))
{
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-03-04 10:08:13 +00:00
if (c == XP_CHAR('='))
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_NE);
ADD_TOKEN_STR (awk, XP_TEXT("!="));
GET_CHAR_TO (awk, c);
}
2006-04-12 03:54:12 +00:00
else if (c == XP_CHAR('~'))
2006-04-11 15:44:30 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_NM);
2006-04-12 03:54:12 +00:00
ADD_TOKEN_STR (awk, XP_TEXT("!~"));
2006-04-11 15:44:30 +00:00
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_NOT);
ADD_TOKEN_STR (awk, XP_TEXT("!"));
}
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('>'))
{
2006-02-08 16:14:31 +00:00
GET_CHAR_TO (awk, c);
2006-03-04 10:08:13 +00:00
if ((awk->opt.parse & XP_AWK_SHIFT) && c == XP_CHAR('>'))
{
2006-02-08 16:14:31 +00:00
SET_TOKEN_TYPE (awk, TOKEN_RSHIFT);
ADD_TOKEN_STR (awk, XP_TEXT(">>"));
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('='))
{
2006-02-08 16:14:31 +00:00
SET_TOKEN_TYPE (awk, TOKEN_GE);
ADD_TOKEN_STR (awk, XP_TEXT(">="));
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2006-02-08 16:14:31 +00:00
SET_TOKEN_TYPE (awk, TOKEN_GT);
ADD_TOKEN_STR (awk, XP_TEXT(">"));
}
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('<'))
{
2006-02-08 16:14:31 +00:00
GET_CHAR_TO (awk, c);
2006-03-04 10:08:13 +00:00
if ((awk->opt.parse & XP_AWK_SHIFT) && c == XP_CHAR('<'))
{
2006-02-08 16:14:31 +00:00
SET_TOKEN_TYPE (awk, TOKEN_LSHIFT);
ADD_TOKEN_STR (awk, XP_TEXT("<<"));
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('='))
{
2006-02-08 16:14:31 +00:00
SET_TOKEN_TYPE (awk, TOKEN_LE);
ADD_TOKEN_STR (awk, XP_TEXT("<="));
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2006-02-08 16:14:31 +00:00
SET_TOKEN_TYPE (awk, TOKEN_LT);
ADD_TOKEN_STR (awk, XP_TEXT("<"));
}
}
2006-03-29 16:39:04 +00:00
else if (c == XP_CHAR('|'))
{
GET_CHAR_TO (awk, c);
if (c == XP_CHAR('|'))
{
SET_TOKEN_TYPE (awk, TOKEN_LOR);
ADD_TOKEN_STR (awk, XP_TEXT("||"));
GET_CHAR_TO (awk, c);
}
else
{
SET_TOKEN_TYPE (awk, TOKEN_BOR);
ADD_TOKEN_STR (awk, XP_TEXT("|"));
}
}
else if (c == XP_CHAR('&'))
{
GET_CHAR_TO (awk, c);
2006-03-30 16:24:10 +00:00
if (c == XP_CHAR('&'))
2006-03-29 16:39:04 +00:00
{
SET_TOKEN_TYPE (awk, TOKEN_LAND);
ADD_TOKEN_STR (awk, XP_TEXT("&&"));
GET_CHAR_TO (awk, c);
}
else
{
SET_TOKEN_TYPE (awk, TOKEN_BAND);
ADD_TOKEN_STR (awk, XP_TEXT("&"));
}
}
2006-03-31 12:04:14 +00:00
else if (c == XP_CHAR('~'))
{
2006-04-12 03:54:12 +00:00
SET_TOKEN_TYPE (awk, TOKEN_TILDE);
2006-03-31 12:04:14 +00:00
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-04-11 15:44:30 +00:00
else if (c == XP_CHAR('^'))
{
SET_TOKEN_TYPE (awk, TOKEN_BXOR);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('+'))
{
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-03-04 10:08:13 +00:00
if (c == XP_CHAR('+'))
{
2006-03-31 12:04:14 +00:00
SET_TOKEN_TYPE (awk, TOKEN_PLUSPLUS);
2005-11-14 15:23:54 +00:00
ADD_TOKEN_STR (awk, XP_TEXT("++"));
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('='))
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_PLUS_ASSIGN);
ADD_TOKEN_STR (awk, XP_TEXT("+="));
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_PLUS);
ADD_TOKEN_STR (awk, XP_TEXT("+"));
}
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('-'))
{
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-03-04 10:08:13 +00:00
if (c == XP_CHAR('-'))
{
2006-03-31 12:04:14 +00:00
SET_TOKEN_TYPE (awk, TOKEN_MINUSMINUS);
2005-11-14 15:23:54 +00:00
ADD_TOKEN_STR (awk, XP_TEXT("--"));
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('='))
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_MINUS_ASSIGN);
ADD_TOKEN_STR (awk, XP_TEXT("-="));
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2005-11-14 15:23:54 +00:00
SET_TOKEN_TYPE (awk, TOKEN_MINUS);
ADD_TOKEN_STR (awk, XP_TEXT("-"));
}
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('*'))
{
2006-01-10 13:57:54 +00:00
GET_CHAR_TO (awk, c);
2006-04-11 15:44:30 +00:00
if (c == XP_CHAR('='))
{
SET_TOKEN_TYPE (awk, TOKEN_MUL_ASSIGN);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
else if (c == XP_CHAR('*'))
{
GET_CHAR_TO (awk, c);
if (c == XP_CHAR('='))
{
SET_TOKEN_TYPE (awk, TOKEN_EXP_ASSIGN);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
else
{
SET_TOKEN_TYPE (awk, TOKEN_EXP);
ADD_TOKEN_CHAR (awk, c);
}
}
else
{
SET_TOKEN_TYPE (awk, TOKEN_MUL);
ADD_TOKEN_CHAR (awk, c);
}
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('/'))
{
2006-04-14 10:56:42 +00:00
/* TODO: handle regular expression here... /^pattern$/ */
2006-01-10 13:57:54 +00:00
GET_CHAR_TO (awk, c);
2006-04-11 15:44:30 +00:00
if (c == XP_CHAR('='))
{
SET_TOKEN_TYPE (awk, TOKEN_DIV_ASSIGN);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
else
{
SET_TOKEN_TYPE (awk, TOKEN_DIV);
ADD_TOKEN_CHAR (awk, c);
}
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('%'))
{
2006-01-10 13:57:54 +00:00
GET_CHAR_TO (awk, c);
2006-04-11 15:44:30 +00:00
if (c == XP_CHAR('='))
{
SET_TOKEN_TYPE (awk, TOKEN_MOD_ASSIGN);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
else
{
SET_TOKEN_TYPE (awk, TOKEN_MOD);
ADD_TOKEN_CHAR (awk, c);
}
2006-01-10 13:57:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('('))
{
2005-11-15 15:32:39 +00:00
SET_TOKEN_TYPE (awk, TOKEN_LPAREN);
2005-12-29 12:04:51 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-01-09 16:03:56 +00:00
GET_CHAR_TO (awk, c);
2005-11-15 15:32:39 +00:00
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR(')'))
{
2005-11-15 15:32:39 +00:00
SET_TOKEN_TYPE (awk, TOKEN_RPAREN);
2005-12-29 12:04:51 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-01-09 16:03:56 +00:00
GET_CHAR_TO (awk, c);
2005-11-15 15:32:39 +00:00
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('{'))
{
2005-11-15 15:32:39 +00:00
SET_TOKEN_TYPE (awk, TOKEN_LBRACE);
2005-12-29 12:04:51 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-01-09 16:03:56 +00:00
GET_CHAR_TO (awk, c);
2005-11-15 15:32:39 +00:00
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('}'))
{
2005-11-15 15:32:39 +00:00
SET_TOKEN_TYPE (awk, TOKEN_RBRACE);
ADD_TOKEN_CHAR (awk, c);
2006-01-09 16:03:56 +00:00
GET_CHAR_TO (awk, c);
2005-11-15 15:32:39 +00:00
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('['))
{
2006-01-19 16:28:21 +00:00
SET_TOKEN_TYPE (awk, TOKEN_LBRACK);
2005-12-29 12:04:51 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-01-09 16:03:56 +00:00
GET_CHAR_TO (awk, c);
2005-11-15 15:32:39 +00:00
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR(']'))
{
2006-01-19 16:28:21 +00:00
SET_TOKEN_TYPE (awk, TOKEN_RBRACK);
2005-11-15 15:32:39 +00:00
ADD_TOKEN_CHAR (awk, c);
2006-01-09 16:03:56 +00:00
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('$'))
{
2006-01-25 14:50:57 +00:00
SET_TOKEN_TYPE (awk, TOKEN_DOLLAR);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR(','))
{
2006-01-13 14:16:56 +00:00
SET_TOKEN_TYPE (awk, TOKEN_COMMA);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-04-16 04:31:38 +00:00
else if (c == XP_CHAR('.'))
{
SET_TOKEN_TYPE (awk, TOKEN_PERIOD);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR(';'))
{
2006-01-09 16:03:56 +00:00
SET_TOKEN_TYPE (awk, TOKEN_SEMICOLON);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
2005-11-14 15:23:54 +00:00
}
2006-04-10 15:52:07 +00:00
else if (c == XP_CHAR(':'))
{
SET_TOKEN_TYPE (awk, TOKEN_COLON);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
else if (c == XP_CHAR('?'))
{
SET_TOKEN_TYPE (awk, TOKEN_QUEST);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
2006-03-04 10:08:13 +00:00
else
{
2005-11-14 15:23:54 +00:00
awk->errnum = XP_AWK_ELXCHR;
return -1;
}
return 0;
2005-11-06 12:01:29 +00:00
}
2005-11-14 15:23:54 +00:00
2006-04-04 06:26:56 +00:00
static int __get_number (xp_awk_t* awk)
{
xp_cint_t c;
xp_assert (XP_STR_LEN(&awk->token.name) == 0);
SET_TOKEN_TYPE (awk, TOKEN_INT);
c = awk->lex.curc;
if (c == XP_CHAR('0'))
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
if (c == XP_CHAR('x') || c == XP_CHAR('X'))
{
/* hexadecimal number */
do
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
2006-04-07 04:23:11 +00:00
}
while (xp_isxdigit(c));
2006-04-04 06:26:56 +00:00
2006-04-04 16:22:01 +00:00
return 0;
}
else if (c == XP_CHAR('b') || c == XP_CHAR('B'))
{
/* binary number */
do
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
2006-04-07 04:23:11 +00:00
}
while (c == XP_CHAR('0') || c == XP_CHAR('1'));
2006-04-04 16:22:01 +00:00
return 0;
2006-04-04 06:26:56 +00:00
}
else if (c != '.')
{
/* octal number */
2006-04-05 15:56:20 +00:00
while (c >= XP_CHAR('0') && c <= XP_CHAR('7'))
2006-04-04 06:26:56 +00:00
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
2006-04-05 15:56:20 +00:00
}
2006-04-04 06:26:56 +00:00
2006-04-04 16:22:01 +00:00
return 0;
2006-04-04 06:26:56 +00:00
}
}
while (xp_isdigit(c))
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
if (c == XP_CHAR('.'))
{
/* floating-point number */
SET_TOKEN_TYPE (awk, TOKEN_REAL);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
while (xp_isdigit(c))
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
}
if (c == XP_CHAR('E') || c == XP_CHAR('e'))
{
SET_TOKEN_TYPE (awk, TOKEN_REAL);
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
if (c == XP_CHAR('+') || c == XP_CHAR('-'))
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
while (xp_isdigit(c))
{
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
}
return 0;
}
2006-04-07 04:23:11 +00:00
static int __get_string (xp_awk_t* awk)
{
xp_cint_t c;
xp_bool_t escaped = xp_false;
GET_CHAR_TO (awk, c);
while (1)
{
if (c == XP_CHAR_EOF)
{
awk->errnum = XP_AWK_EENDSTR;
return -1;
}
if (escaped == xp_false && c == XP_CHAR('\"'))
{
GET_CHAR_TO (awk, c);
break;
}
if (escaped == xp_false && c == XP_CHAR('\\'))
{
GET_CHAR_TO (awk, c);
escaped = xp_true;
continue;
}
if (escaped == xp_true)
{
if (c == XP_CHAR('n')) c = XP_CHAR('\n');
else if (c == XP_CHAR('r')) c = XP_CHAR('\r');
else if (c == XP_CHAR('t')) c = XP_CHAR('\t');
/* TODO: more escape characters */
escaped = xp_false;
}
ADD_TOKEN_CHAR (awk, c);
GET_CHAR_TO (awk, c);
}
return 0;
}
2005-11-14 15:23:54 +00:00
static int __get_char (xp_awk_t* awk)
{
2006-01-09 16:03:56 +00:00
xp_ssize_t n;
2006-01-20 16:02:03 +00:00
xp_char_t c;
2006-01-09 16:03:56 +00:00
2006-03-04 10:08:13 +00:00
if (awk->lex.ungotc_count > 0)
{
2005-11-14 15:23:54 +00:00
awk->lex.curc = awk->lex.ungotc[--awk->lex.ungotc_count];
return 0;
}
2006-01-20 16:02:03 +00:00
n = awk->src_func(XP_AWK_IO_DATA, awk->src_arg, &c, 1);
2006-03-04 10:08:13 +00:00
if (n == -1)
{
2005-11-14 15:23:54 +00:00
awk->errnum = XP_AWK_ESRCDT;
return -1;
}
2006-01-20 16:02:03 +00:00
awk->lex.curc = (n == 0)? XP_CHAR_EOF: c;
2006-01-09 16:03:56 +00:00
2005-11-14 15:23:54 +00:00
return 0;
}
static int __unget_char (xp_awk_t* awk, xp_cint_t c)
{
2006-03-04 10:08:13 +00:00
if (awk->lex.ungotc_count >= xp_countof(awk->lex.ungotc))
{
2005-11-14 15:23:54 +00:00
awk->errnum = XP_AWK_ELXUNG;
return -1;
}
awk->lex.ungotc[awk->lex.ungotc_count++] = c;
return 0;
}
static int __skip_spaces (xp_awk_t* awk)
{
xp_cint_t c = awk->lex.curc;
while (xp_isspace(c)) GET_CHAR_TO (awk, c);
return 0;
}
static int __skip_comment (xp_awk_t* awk)
{
xp_cint_t c = awk->lex.curc;
2006-04-07 04:23:11 +00:00
if ((awk->opt.parse & XP_AWK_HASHSIGN) && c == XP_CHAR('#'))
{
do
{
GET_CHAR_TO (awk, c);
}
while (c != '\n' && c != XP_CHAR_EOF);
GET_CHAR (awk);
return 1; /* comment by # */
}
if (c != XP_CHAR('/')) return 0; /* not a comment */
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-03-04 10:08:13 +00:00
if (c == XP_CHAR('/'))
{
2006-04-07 04:23:11 +00:00
do
{
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-04-07 04:23:11 +00:00
}
while (c != '\n' && c != XP_CHAR_EOF);
2005-11-14 15:23:54 +00:00
GET_CHAR (awk);
2006-04-07 04:23:11 +00:00
return 1; /* comment by // */
2005-11-14 15:23:54 +00:00
}
2006-03-04 10:08:13 +00:00
else if (c == XP_CHAR('*'))
{
2006-04-07 04:23:11 +00:00
do
{
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-03-04 10:08:13 +00:00
if (c == XP_CHAR('*'))
{
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
2006-03-04 10:08:13 +00:00
if (c == XP_CHAR('/'))
{
2005-11-14 15:23:54 +00:00
GET_CHAR_TO (awk, c);
break;
}
}
2006-04-07 04:23:11 +00:00
}
while (1);
return 1; /* c-style comment */
2005-11-14 15:23:54 +00:00
}
2006-04-07 04:23:11 +00:00
if (__unget_char(awk,c) == -1) return -1; /* error */
2006-01-12 14:20:17 +00:00
awk->lex.curc = XP_CHAR('/');
2005-11-14 15:23:54 +00:00
return 0;
}
2006-02-04 19:31:51 +00:00
static int __classify_ident (xp_awk_t* awk, const xp_char_t* ident)
2005-11-15 15:32:39 +00:00
{
2006-04-10 14:53:48 +00:00
struct __kwent* p;
2005-11-15 15:32:39 +00:00
2006-03-04 10:08:13 +00:00
for (p = __kwtab; p->name != XP_NULL; p++)
{
2006-02-04 19:31:51 +00:00
if (p->valid != 0 && (awk->opt.parse & p->valid) == 0) continue;
2005-11-15 15:32:39 +00:00
if (xp_strcmp(p->name, ident) == 0) return p->type;
}
return TOKEN_IDENT;
}
2006-01-24 16:14:28 +00:00
2006-04-14 16:26:00 +00:00
static int __assign_to_opcode (xp_awk_t* awk)
{
if (MATCH(awk,TOKEN_ASSIGN)) return XP_AWK_ASSOP_NONE;
if (MATCH(awk,TOKEN_PLUS_ASSIGN)) return XP_AWK_ASSOP_PLUS;
if (MATCH(awk,TOKEN_MINUS_ASSIGN)) return XP_AWK_ASSOP_MINUS;
if (MATCH(awk,TOKEN_MUL_ASSIGN)) return XP_AWK_ASSOP_MUL;
if (MATCH(awk,TOKEN_DIV_ASSIGN)) return XP_AWK_ASSOP_DIV;
if (MATCH(awk,TOKEN_MOD_ASSIGN)) return XP_AWK_ASSOP_MOD;
if (MATCH(awk,TOKEN_EXP_ASSIGN)) return XP_AWK_ASSOP_EXP;
return -1;
}