aboutsummaryrefslogtreecommitdiffstats
path: root/tools/npl
diff options
context:
space:
mode:
authorJakub Zawadzki <darkjames-ws@darkjames.pl>2013-03-24 16:38:57 +0000
committerJakub Zawadzki <darkjames-ws@darkjames.pl>2013-03-24 16:38:57 +0000
commitace8a9cb6ae4b869b3de77b95032afb024338424 (patch)
tree3aa9284fdfbe8af0c5ca8aa9bc260dab7f55329a /tools/npl
parent8677c1f42fc62dfca3a84dfd080eef13de56a3af (diff)
[NPL] another weekend work.
svn path=/trunk/; revision=48527
Diffstat (limited to 'tools/npl')
-rw-r--r--tools/npl/ast.h1
-rw-r--r--tools/npl/npl.c446
-rw-r--r--tools/npl/parser.l18
3 files changed, 359 insertions, 106 deletions
diff --git a/tools/npl/ast.h b/tools/npl/ast.h
index 75c1355049..476a3ee79d 100644
--- a/tools/npl/ast.h
+++ b/tools/npl/ast.h
@@ -9,6 +9,7 @@ typedef enum {
OP2_INVALID = 0,
OP2_ASSIGN,
+ OP2_ASSIGN_PLUS,
OP2_PLUS,
OP2_MINUS,
diff --git a/tools/npl/npl.c b/tools/npl/npl.c
index 5ade4f04ac..06515bf460 100644
--- a/tools/npl/npl.c
+++ b/tools/npl/npl.c
@@ -27,7 +27,7 @@
int npl_parse_file(npl_code_t *code, FILE *f, const char *filename); /* parser.l */
-static void gen_expr(FILE *f, npl_expression_t *e);
+static struct symbol *gen_expr(FILE *f, npl_expression_t *e);
static void gen_statements(FILE *f, struct _npl_statements *sts);
static void gen_struct(FILE *f, npl_struct_t *s);
@@ -50,7 +50,9 @@ enum symbol_type {
SYMBOL_STRUCT = (1 << 1),
SYMBOL_TABLE = (1 << 2),
SYMBOL_TYPE = (1 << 3),
- SYMBOL_FIELD = (1 << 4)
+ SYMBOL_FIELD = (1 << 4),
+
+ SYMBOL_SIMPLE = (1 << 5)
};
struct symbol {
@@ -66,6 +68,8 @@ struct symbol *symbols;
struct hfinfo *hfs;
struct ettinfo *etts;
+static npl_expression_t property_e;
+
static void _fail(const char *file, int line, const char *msg) {
fprintf(stderr, "!!! %s:%d fail(%s)\n", file, line, msg);
abort();
@@ -238,36 +242,43 @@ count_expression_list(const npl_expression_list_t *exprs)
}
return c;
}
-static const npl_expression_t *
-id_to_expr(const char *id)
+
+static struct symbol *
+expr_to_symbol(const npl_expression_t *e)
{
- struct symbol *sym = symbol_find(id, SYMBOL_EXPR | SYMBOL_FIELD);
+ struct symbol *sym = NULL;
- if (!sym) {
- fprintf(stderr, "can't find id: %s\n", id);
- abort();
- }
+ if (e->type == EXPRESSION_ID) {
+ const char *id = e->id.id;
- if (sym->type == SYMBOL_EXPR)
- return sym->data;
- else if (sym->type == SYMBOL_FIELD) {
- fprintf(stderr, "XXX ID %s SYMBOL_FIELD\n", sym->id);
- return NULL;
- } else {
- fprintf(stderr, "ID %s invalid type [%d]\n", sym->id, sym->type);
- abort();
+ sym = symbol_find(id, SYMBOL_ANY);
+
+ if (!sym) {
+ fprintf(stderr, "can't find id: %s\n", id);
+ abort();
+ }
+
+ if (sym->type == SYMBOL_EXPR) {
+ struct symbol *new_sym = expr_to_symbol(sym->data);
+
+ if (new_sym)
+ sym = new_sym;
+ }
}
+ return sym;
}
static int
-expr_to_int(const npl_expression_t *e, int *val)
+expr_to_const_int(const npl_expression_t *e, int *val)
{
+ struct symbol *sym;
+
if (e->type == EXPRESSION_INT) {
*val = e->num.digit;
return 1;
}
if (e->type == EXPRESSION_UNARY) {
- if (!expr_to_int(e->u.operand, val))
+ if (!expr_to_const_int(e->u.operand, val))
return 0;
switch (e->u.operator) {
@@ -282,30 +293,123 @@ expr_to_int(const npl_expression_t *e, int *val)
return 1;
}
}
- if (e->type == EXPRESSION_ID) {
- e = id_to_expr(e->id.id);
- if (e)
- return expr_to_int(e, val);
- }
+
+ sym = expr_to_symbol(e);
+ if (sym && sym->type == SYMBOL_EXPR)
+ return expr_to_const_int(sym->data, val);
+
return 0;
}
static int
-expr_to_str(const npl_expression_t *e, const char **val)
+expr_to_const_str(const npl_expression_t *e, const char **val)
{
+ struct symbol *sym;
+
if (e->type == EXPRESSION_STR) {
*val = e->str.str;
return 1;
}
- if (e->type == EXPRESSION_ID) {
- e = id_to_expr(e->id.id);
- if (e)
- return expr_to_str(e, val);
- }
+
+ sym = expr_to_symbol(e);
+ if (sym && sym->type == SYMBOL_EXPR)
+ return expr_to_const_str(sym->data, val);
+
return 0;
}
static const char *
+type_to_ctype(const npl_type_t *t, int size)
+{
+ switch (t->type) {
+ case FIELD_DECIMAL:
+ if (size == 4)
+ return "float";
+ if (size == 8)
+ return "double";
+
+ fprintf(stderr, "!!! decimal, size: %d\n", size);
+ return NULL;
+
+ case FIELD_NUMBER:
+ if (size == 1)
+ return "gint8";
+ if (size == 2)
+ return "gint16";
+ if (size == 3 || size == 4)
+ return "gint32";
+ if (size > 4 && size <= 8)
+ return "gint64";
+
+ fprintf(stderr, "!!! number, size: %d\n", size);
+ return NULL;
+
+ case FIELD_UNSIGNED_NUMBER:
+ if (size == 1)
+ return "guint8";
+ if (size == 2)
+ return "guint16";
+ if (size == 3 || size == 4)
+ return "guint32";
+ if (size > 4 && size <= 8)
+ return "guint64";
+
+ fprintf(stderr, "!!! number, size: %d\n", size);
+ return NULL;
+
+ case FIELD_TIME:
+ return "nstime_t";
+ }
+ fprintf(stderr, "!!! not handled, type: %d, size: %d\n", t->type, size);
+ return NULL;
+}
+
+static const char *
+type_to_tvb(const npl_type_t *t, int size, int endian)
+{
+ switch (t->type) {
+ case FIELD_DECIMAL:
+ if (size == 4 && endian == 0)
+ return "tvb_get_letohieee_float";
+ if (size == 4 && endian == 1)
+ return "tvb_get_ntohieee_float";
+
+ if (size == 8 && endian == 0)
+ return "tvb_get_letohieee_double";
+ if (size == 8 && endian == 1)
+ return "tvb_get_ntohieee_double";
+
+ fprintf(stderr, "!!! decimal, size: %d, endian: %d\n", size, endian);
+ return NULL;
+
+ case FIELD_UNSIGNED_NUMBER:
+ case FIELD_NUMBER:
+ if (size == 1)
+ return "tvb_get_guint8";
+
+ if (size == 2 && endian == 0)
+ return "tvb_get_letohs";
+ if (size == 2 && endian == 1)
+ return "tvb_get_ntohs";
+
+ if (t->type == FIELD_UNSIGNED_NUMBER && size == 3 && endian == 0)
+ return "tvb_get_letoh24";
+ if (t->type == FIELD_UNSIGNED_NUMBER && size == 3 && endian == 1)
+ return "tvb_get_ntoh24";
+
+ if (size == 4 && endian == 0)
+ return "tvb_get_letohl";
+ if (size == 4 && endian == 1)
+ return "tvb_get_ntohl";
+
+ fprintf(stderr, "!!! number, size: %d, endian: %d\n", size, endian);
+ return NULL;
+ }
+ fprintf(stderr, "!!! not handled, type: %d, size: %d, endian: %d\n", t->type, size, endian);
+ return NULL;
+}
+
+static const char *
type_to_ft(const npl_type_t *t, int size)
{
switch (t->type) {
@@ -417,64 +521,81 @@ op2_to_str(npl_op2_t op)
}
static void
-gen_expr_type(FILE *f, npl_type_t *t)
+gen_expr_field(FILE *f, struct _npl_statement_field *field)
{
- fprintf(stderr, "XXX gen expr type: %s\n", t->id);
+ xassert(field->generate_var || f == NULL);
- gen_fprintf(f, "<<TYPE %s>>", t->id);
+ field->generate_var = 1;
+ gen_fprintf(f, "_field_%s", field->id);
}
static void
+gen_expr_type(FILE *f, npl_type_t *t)
+{
+ int size = -1;
+ int byte_order = -1;
+ const char *fetch_func;
+
+ if (t->size && !expr_to_const_int(t->size, &size))
+ fprintf(stderr, "!!! expr_to_const_int(size) failed for type: %s\n", t->id);
+
+ if (t->byte_order && !expr_to_const_int(t->byte_order, &byte_order))
+ fprintf(stderr, "!!! expr_to_const_int(byte_order) failed for type: %s\n", t->id);
+
+ fetch_func = type_to_tvb(t, size, byte_order);
+ if (fetch_func)
+ gen_fprintf(f, "%s", fetch_func);
+ else
+ gen_fprintf(f, "<<TYPE %s>>", t->id);
+}
+
+static struct symbol *
gen_expr(FILE *f, npl_expression_t *e)
{
switch (e->type) {
case EXPRESSION_ID:
- {
- struct symbol *sym = symbol_find(e->id.id, SYMBOL_EXPR | SYMBOL_FIELD | SYMBOL_TYPE);
-
- if (!sym) {
- fprintf(stderr, "can't find id: %s\n", e->id.id);
- gen_fprintf(f, " <<UNK %s>> ", e->id.id);
- return;
- abort();
- }
+ {
+ struct symbol *sym = symbol_find(e->id.id, SYMBOL_EXPR | SYMBOL_FIELD | SYMBOL_TYPE | SYMBOL_SIMPLE);
- if (sym->type == SYMBOL_EXPR) {
- gen_expr(f, sym->data);
- } else if (sym->type == SYMBOL_FIELD) {
- struct _npl_statement_field *field = sym->data;
+ if (!sym) {
+ fprintf(stderr, "can't find id: %s\n", e->id.id);
+ abort();
+ }
- xassert(field->generate_var || f == NULL);
+ if (sym->type == SYMBOL_EXPR)
+ gen_expr(f, sym->data);
- field->generate_var = 1;
- gen_fprintf(f, "_field_%s", sym->id);
+ else if (sym->type == SYMBOL_FIELD)
+ gen_expr_field(f, sym->data);
- } else if (sym->type == SYMBOL_TYPE) {
- npl_type_t *t = sym->data;
+ else if (sym->type == SYMBOL_TYPE)
+ gen_expr_type(f, sym->data);
- gen_expr_type(f, t);
- } else {
- fprintf(stderr, "ID %s wrong type [%d]\n", sym->id, sym->type);
- abort();
- }
+ else if (sym->type == SYMBOL_SIMPLE)
+ gen_fprintf(f, "%s", (const char *) sym->data);
+
+ else {
+ fprintf(stderr, "ID %s wrong type [%d]\n", sym->id, sym->type);
+ abort();
}
- return;
+ return sym;
+ }
case EXPRESSION_INT:
gen_fprintf(f, " %d ", e->num.digit);
- return;
+ return NULL;
case EXPRESSION_STR:
// XXX e->str.str is escaped, almost like C-string so just print it.
gen_fprintf(f, " \"%s\" ", e->str.str);
- return;
+ return NULL;
case EXPRESSION_UNARY:
gen_fprintf(f, "(");
gen_fprintf(f, "%s", op1_to_str(e->u.operator));
gen_expr(f, e->u.operand);
gen_fprintf(f, ")");
- return;
+ return NULL;
case EXPRESSION_BINARY:
gen_fprintf(f, "(");
@@ -482,14 +603,18 @@ gen_expr(FILE *f, npl_expression_t *e)
gen_fprintf(f, " %s ", op2_to_str(e->b.operator));
gen_expr(f, e->b.operand2);
gen_fprintf(f, ")");
- return;
+ return NULL;
case EXPRESSION_CALL:
{
npl_expression_list_t *arg;
- char *ind = "";
+ struct symbol *sym;
+ const char *ind = "";
+
+ sym = gen_expr(f, e->call.fn);
+ if (!sym)
+ abort();
- gen_expr(f, e->call.fn);
gen_fprintf(f, "(");
for (arg = e->call.args; arg; arg = arg->next) {
gen_fprintf(f, "%s", ind);
@@ -497,15 +622,40 @@ gen_expr(FILE *f, npl_expression_t *e)
ind = ", ";
}
gen_fprintf(f, ")");
- return;
+ return NULL;
}
+ case EXPRESSION_COND:
+ gen_fprintf(f, "((");
+ gen_expr(f, e->c.test_expr);
+ gen_fprintf(f, ") ? ");
+ gen_expr(f, e->c.true_expr);
+ gen_fprintf(f, " : ");
+ gen_expr(f, e->c.false_expr);
+ gen_fprintf(f, ")");
+ return NULL;
+
case EXPRESSION_FIELD:
- gen_expr(f, e->fld.base);
- gen_fprintf(f, ".%s ", e->fld.field);
- return;
+ {
+ struct symbol *sym;
+
+ sym = gen_expr(NULL, e->fld.base);
+ if (!sym)
+ abort();
+
+ if (sym->data == &property_e) {
+ gen_fprintf(f, "<< PROPERTY %s>>", e->fld.field);
+ } else {
+ gen_expr(f, e->fld.base);
+ gen_fprintf(f, ".%s ", e->fld.field);
+ }
+ return NULL;
+ }
}
+
fprintf(stderr, "XXX expr->type: %d\n", e->type);
+
+ return NULL;
}
static int
@@ -524,12 +674,12 @@ gen_table_struct(FILE *f, npl_table_t *t)
const char *str;
int val;
- if (!c->return_expr || !expr_to_str(c->return_expr, &str))
+ if (!c->return_expr || !expr_to_const_str(c->return_expr, &str))
return 0;
- if (all_int && !expr_to_int(&c->e, &val))
+ if (all_int && !expr_to_const_int(&c->e, &val))
all_int = 0;
- if (all_str && !expr_to_str(&c->e, &str))
+ if (all_str && !expr_to_const_str(&c->e, &str))
all_str = 0;
if (!all_int && !all_str)
@@ -554,10 +704,10 @@ gen_table_struct(FILE *f, npl_table_t *t)
int val;
/* checked above, should not fail now */
- if (!expr_to_str(c->return_expr, &str))
- fail("expr_to_str(str)");
- if (!expr_to_int(&c->e, &val))
- fail("expr_to_int(val)");
+ if (!expr_to_const_str(c->return_expr, &str))
+ fail("expr_to_const_str(str)");
+ if (!expr_to_const_int(&c->e, &val))
+ fail("expr_to_const_int(val)");
gen_fprintf(f, "\t{ 0x%x, \"%s\" },\n", val, str);
}
@@ -577,10 +727,10 @@ gen_table_struct(FILE *f, npl_table_t *t)
const char *val;
/* checked above, should not fail now */
- if (!expr_to_str(c->return_expr, &str))
- fail("expr_to_str(str)");
- if (!expr_to_str(&c->e, &val))
- fail("expr_to_str(val)");
+ if (!expr_to_const_str(c->return_expr, &str))
+ fail("expr_to_const_str(str)");
+ if (!expr_to_const_str(&c->e, &val))
+ fail("expr_to_const_str(val)");
gen_fprintf(f, "\t{ \"%s\", \"%s\" },\n", val, str);
}
@@ -595,12 +745,15 @@ gen_table_struct(FILE *f, npl_table_t *t)
static void
gen_table_func(FILE *f, npl_table_t *t)
{
+ struct symbol *symroot;
struct npl_table_case *c;
gen_fprintf(f,
"static const char *\n"
"format_table_%s", t->id);
+ symroot = symbols_push();
+
gen_fprintf(f, "(");
if (t->params.count) {
int i;
@@ -609,11 +762,13 @@ gen_table_func(FILE *f, npl_table_t *t)
if (i)
gen_fprintf(f, ", ");
gen_fprintf(f, "TYPE %s", t->params.args[i]);
+ symbol_add(t->params.args[i], SYMBOL_SIMPLE, t->params.args[i]);
}
} else {
/* default */
gen_fprintf(f, "TYPE value");
+ symbol_add("value", SYMBOL_SIMPLE, "value");
}
gen_fprintf(f, ")\n{\n");
@@ -678,6 +833,8 @@ again2:
gen_fprintf(f, "\treturn \"\";\n");
gen_fprintf(f, "}\n");
+
+ symbols_pop(symroot);
}
static void
@@ -700,6 +857,7 @@ static void
gen_field_struct(FILE *f, npl_statement_t *st, npl_struct_t *s)
{
// XXX st->f.bits, st->f.arr, st->f.format, st->f.sts
+ // XXX, st->f.generate_var
gen_fprintf(f, "\toffset = dissect_struct_%s(tvb, pinfo, tree, %s, offset);\n", s->tmpid, hfi_var(st->f.hfi));
@@ -715,6 +873,8 @@ gen_field_type(FILE *f, npl_statement_t *st, npl_type_t *t)
// XXX st->f.bits, st->f.arr, st->f.sts
int size = -1;
+ struct symbol *sym_size = NULL;
+
int byte_order = -1;
npl_expression_t *display_format = t->display_format;
const char *hf_type;
@@ -734,19 +894,57 @@ gen_field_type(FILE *f, npl_statement_t *st, npl_type_t *t)
argv = argv->next;
}
- if (t->size && !expr_to_int(t->size, &size))
- fprintf(stderr, "!!! expr_to_int(size) failed for type: %s\n", t->id);
+ xassert(t->size != NULL);
+ if (!expr_to_const_int(t->size, &size)) {
+ sym_size = expr_to_symbol(t->size);
- if (t->byte_order && !expr_to_int(t->byte_order, &byte_order))
- fprintf(stderr, "!!! expr_to_int(byte_order) failed for type: %s\n", t->id);
+ if (!sym_size) {
+ fprintf(stderr, "!!! expr_to_const_int, _symbol(size) failed for type: %s\n", t->id);
+ abort();
+ }
+ }
+
+ if (t->byte_order && !expr_to_const_int(t->byte_order, &byte_order))
+ fprintf(stderr, "!!! expr_to_const_int(byte_order) failed for type: %s\n", t->id);
+
+ if (st->f.generate_var) {
+ /* XXX, sym_size */
+
+ const char *ctype = type_to_ctype(t, size);
+ const char *fetch_func = type_to_tvb(t, size, byte_order);
+
+/*
+ if (!ctype || !fetch_func)
+ abort();
+*/
+
+ /* XXX, we should declare variable on begin of block (< C99) */
+ gen_fprintf(f, "\t%s _field_%s = %s(tvb, offset);\n", ctype, st->f.id, fetch_func);
+ }
+
+ if (sym_size) {
+ if (sym_size->type == SYMBOL_FIELD) {
+ struct _npl_statement_field *field = sym_size->data;
- hf_type = type_to_ft(t, size);
+ xassert(field->generate_var || f == NULL);
+
+ field->generate_var = 1;
+ } else
+ fprintf(stderr, "::: %s (%d)\n", sym_size->id, sym_size->type);
+
+ hf_type = NULL;
+
+ } else
+ hf_type = type_to_ft(t, size);
st->f.hfi->hf_type = hf_type;
/* prefer statement format over type one (?) */
if (st->f.format)
display_format = st->f.format;
+
+ /* XXX, when generate_var we can use fetched value, not proto_tree_add_item() */
+
#if 0
if (display_format)
fprintf(stderr, "XXX, format\n");
@@ -758,7 +956,30 @@ gen_field_type(FILE *f, npl_statement_t *st, npl_type_t *t)
(byte_order == 0) ? "ENC_LITTLE_ENDIAN" :
(byte_order == 1) ? "ENC_BIG_ENDIAN" :
"ENC_NA");
- gen_fprintf(f, "offset += %d;\n", size);
+
+ if (sym_size) {
+ /* runtime */
+ if (sym_size->type == SYMBOL_FIELD) {
+ gen_fprintf(f, "offset += _field_%s;\n", sym_size->id);
+
+ } else if (sym_size->type == SYMBOL_EXPR) {
+ gen_fprintf(f, "\n\t");
+ gen_fprintf(f, "offset += (");
+ gen_expr(f, sym_size->data);
+ gen_fprintf(f, ");\n");
+
+ } else if (sym_size->type == SYMBOL_SIMPLE) {
+ gen_fprintf(f, "offset += %s;\n", (const char *) sym_size->data);
+
+ } else {
+ fprintf(stderr, "::: %s (%d)\n", sym_size->id, sym_size->type);
+ gen_fprintf(f, "offset += XXX;\n");
+ }
+
+ } else {
+ /* const */
+ gen_fprintf(f, "offset += %d;\n", size);
+ }
symbols_pop(symroot);
}
@@ -800,11 +1021,6 @@ gen_statement(FILE *f, npl_statement_t *st)
abort();
}
- if (st->f.generate_var) {
- // XXX
- gen_fprintf(f, "\t_field_%s = tvb_...\n", st->f.id);
- }
-
symbol_add(st->f.id, SYMBOL_FIELD, &st->f);
if (sym->type == SYMBOL_STRUCT)
@@ -1012,7 +1228,7 @@ gen_struct(FILE *f, npl_struct_t *s)
gen_fprintf(f,
"\tif (parent_tree) {\n"
- "\t\tti = proto_tree_add_bytes_format(tree, hf_index, tvb, offset, 0, NULL, \"%s\");\n"
+ "\t\tti = proto_tree_add_bytes_format(parent_tree, hf_index, tvb, offset, 0, NULL, \"%s\");\n"
"\t\ttree = proto_item_add_subtree(ti, %s);\n"
"\t}\n", "description", ett_var(s->ett));
@@ -1233,26 +1449,57 @@ get_protocol(npl_code_t *code)
return NULL;
}
+static void
+merge_code(npl_code_t *code, npl_code_t *subcode)
+{
+ struct _npl_decl_list **p = &code->decls;
+
+ while (*p)
+ p = &(*p)->next;
+
+ *p = subcode->decls;
+}
+
int main(int argc, char **argv) {
FILE *f;
npl_code_t code;
- int parse_ok;
- if (argc != 2) {
+ int i;
+
+ if (argc < 2) {
fprintf(stderr, "usage: %s filename\n", argv[0]);
return 1;
}
- if (!(f = fopen(argv[1], "rb"))) {
- fprintf(stderr, "can't open: %s\n", argv[1]);
- return 1;
- }
+ /* build-in symbols */
+ symbol_add("FrameOffset", SYMBOL_SIMPLE, "offset");
+ symbol_add("FrameData", SYMBOL_SIMPLE, "tvb");
+ symbol_add("Property", SYMBOL_EXPR, &property_e); /* XXX, SYMBOL_STRUCT */
memset(&code, 0, sizeof(code));
- parse_ok = npl_parse_file(&code, f, argv[1]);
-// parse_ok = 0;
- if (parse_ok) {
+ for (i = 1; i < argc; i++) {
+ npl_code_t mcode;
+ int parse_ok;
+
+ if (!(f = fopen(argv[i], "rb"))) {
+ fprintf(stderr, "can't open: %s\n", argv[i]);
+ return 1;
+ }
+
+ memset(&mcode, 0, sizeof(mcode));
+ parse_ok = npl_parse_file(&mcode, f, argv[i]);
+ fclose(f);
+
+ if (!parse_ok) {
+ fprintf(stderr, "can't parse: %s\n", argv[i]);
+ return 1;
+ }
+
+ merge_code(&code, &mcode);
+ }
+
+ {
const npl_protocol_t *proto = get_protocol(&code);
const char *proto_name = (proto) ? proto->id : "noname";
FILE *out;
@@ -1280,7 +1527,6 @@ int main(int argc, char **argv) {
fclose(out);
}
- fclose(f);
return 0;
}
diff --git a/tools/npl/parser.l b/tools/npl/parser.l
index e97bce5188..57e0d5763d 100644
--- a/tools/npl/parser.l
+++ b/tools/npl/parser.l
@@ -79,6 +79,7 @@ typedef enum {
TOKEN_GEQUAL,
TOKEN_ASSIGN,
+ TOKEN_ASSIGN_PLUS,
TOKEN_PLUS,
TOKEN_MINUS,
TOKEN_MULTIPLY,
@@ -170,6 +171,7 @@ or return TOKEN_OROR;
">=" return TOKEN_GEQUAL;
"<=" return TOKEN_LEQUAL;
+"+=" return TOKEN_ASSIGN_PLUS;
"=" return TOKEN_ASSIGN;
"+" return TOKEN_PLUS;
"-" return TOKEN_MINUS;
@@ -881,14 +883,12 @@ parse_expression13(npl_expression_t *expr)
expr->c.test_expr = operand;
e = xnew(npl_expression_t);
-// parse_expression13(e);
parse_expression(e);
expr->c.true_expr = e;
accept(TOKEN_COLON);
e = xnew(npl_expression_t);
-// parse_expression13(e);
- parse_expression(e);
+ parse_expression13(e);
expr->c.false_expr = e;
expr->type = EXPRESSION_COND;
@@ -907,14 +907,21 @@ xparse_expression(void)
static void
parse_expression(npl_expression_t *expr)
{
+ npl_op2_t op;
+
parse_expression13(expr);
- if (is_token_accept(TOKEN_ASSIGN)) {
+ op =
+ (is_token_accept(TOKEN_ASSIGN)) ? OP2_ASSIGN :
+ (is_token_accept(TOKEN_ASSIGN_PLUS)) ? OP2_ASSIGN_PLUS :
+ OP2_INVALID;
+
+ if (op != OP2_INVALID) {
npl_expression_t *operand = xdup(npl_expression_t, expr);
expr->b.operand2 = xparse_expression();
- expr->b.operator = OP2_ASSIGN;
+ expr->b.operator = op;
expr->b.operand1 = operand;
expr->type = EXPRESSION_BINARY;
}
@@ -1136,7 +1143,6 @@ parse_statement(npl_statement_t *st)
st->f.t_id = accept_id();
if (is_token_accept(TOKEN_LPAREN)) {
- /* XXX, WTF: StringTerm(Property.XMLEncoding, "<", true, false, false) Reason; */
parse_expression_list(&st->f.params);
accept(TOKEN_RPAREN);