Mercurial > hg > index.cgi
changeset 36:5325b640424d
First pass expression parsing
author | Lost Wizard (lost@starbug3) |
---|---|
date | Tue, 08 Feb 2011 22:42:12 -0700 |
parents | cdb0175e1063 |
children | a5d4693483af |
files | lwbasic/lexer.c lwbasic/lwbasic.h lwbasic/parser.c |
diffstat | 3 files changed, 129 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/lwbasic/lexer.c Sat Feb 05 14:22:54 2011 -0700 +++ b/lwbasic/lexer.c Tue Feb 08 22:42:12 2011 -0700 @@ -72,6 +72,8 @@ { "bor", token_op_bor }, { "bxor", token_op_bxor }, { "xor", token_op_xor }, + { "not", token_op_not }, + { "bnot", token_op_bnot }, { NULL } }; @@ -106,6 +108,10 @@ "<times>", "<divide>", "<modulus>", + "<openparen>", + "<closeparen>", + "<not>", + "<bitwisenot>", "<identifier>", "<char>", "<uint>", @@ -384,6 +390,13 @@ state -> lexer_token = token_op_modulus; return; + case '(': + state -> lexer_token = token_op_oparen; + return; + + case ')': + state -> lexer_token = token_op_cparen; + return; } }
--- a/lwbasic/lwbasic.h Sat Feb 05 14:22:54 2011 -0700 +++ b/lwbasic/lwbasic.h Tue Feb 08 22:42:12 2011 -0700 @@ -104,6 +104,10 @@ token_op_times, /* times */ token_op_divide, /* divide */ token_op_modulus, /* modulus */ + token_op_oparen, /* open paren */ + token_op_cparen, /* close paren */ + token_op_not, /* boolean not */ + token_op_bnot, /* bitwise not */ token_identifier, /* an identifier (variable, function, etc. */ token_char, /* single character; fallback */ token_uint, /* unsigned integer up to 32 bits */
--- a/lwbasic/parser.c Sat Feb 05 14:22:54 2011 -0700 +++ b/lwbasic/parser.c Tue Feb 08 22:42:12 2011 -0700 @@ -66,10 +66,14 @@ return pt; } +static void parse_expr(cstate *state, int prec); +static void parse_term(cstate *state); static int parse_expression(cstate *state) { state -> expression = 1; + parse_expr(state, 0); + state -> expression = 0; return 1; } @@ -355,3 +359,111 @@ } } } + +static void parse_expr(cstate *state, int prec) +{ + static const struct operinfo { + int opernum; + int operprec; + } operators[] = + { + { token_op_plus, 100 }, + { token_op_minus, 100 }, + { token_op_times, 150 }, + { token_op_divide, 150 }, + { token_op_modulus, 150 }, + { token_op_and, 25 }, + { token_op_or, 20 }, + { token_op_xor, 20 }, + { token_op_band, 50 }, + { token_op_bor, 45 }, + { token_op_bxor, 45 }, + { -1, -1 } + }; + int opern; + + parse_term(state); + +eval_next: + for (opern = 0; operators[opern].opernum != -1; opern++) + { + if (operators[opern].opernum == state -> lexer_token) + break; + } + if (operators[opern].opernum == -1) + return; + + if (operators[opern].operprec <= prec) + return; + + lexer(state); + + parse_expr(state, operators[opern].operprec); + + /* push operator */ + + goto eval_next; +} + +static void parse_term(cstate *state) +{ +eval_next: + /* parens */ + if (state -> lexer_token == token_op_oparen) + { + lexer(state); + parse_expr(state, 0); + expect(state, token_op_cparen); + return; + } + + /* unary plus; ignore it */ + if (state -> lexer_token == token_op_plus) + { + lexer(state); + goto eval_next; + } + + /* unary minus, precision 200 */ + if (state -> lexer_token == token_op_minus) + { + lexer(state); + parse_expr(state, 200); + + /* push unary negation */ + } + + /* BNOT, NOT */ + if (state -> lexer_token == token_op_not || state -> lexer_token == token_op_bnot) + { + lexer(state); + parse_expr(state, 200); + + /* push unary operator */ + } + + /* integer */ + if (state -> lexer_token == token_int) + { + } + + /* unsigned integer */ + if (state -> lexer_token == token_uint) + { + } + + /* variable or function call */ + if (state -> lexer_token == token_identifier) + { + lexer(state); + if (state -> lexer_token == token_op_oparen) + { + /* function call */ + return; + } + /* variable */ + return; + } + + lwb_error("Invalid input in expression; got %s\n", lexer_return_token(state)); +}