Mercurial > hg > index.cgi
changeset 35:cdb0175e1063
More work on expressions
author | Lost Wizard (lost@starbug3) |
---|---|
date | Sat, 05 Feb 2011 14:22:54 -0700 |
parents | bfea77812e64 |
children | 5325b640424d |
files | lwbasic/lexer.c lwbasic/lwbasic.h lwbasic/parser.c |
diffstat | 3 files changed, 190 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/lwbasic/lexer.c Fri Feb 04 21:27:03 2011 -0700 +++ b/lwbasic/lexer.c Sat Feb 05 14:22:54 2011 -0700 @@ -46,6 +46,7 @@ int token; }; +/* keywords that appear as part of normal expressions */ static struct token_list lexer_global_tokens[] = { { "function", token_kw_function }, @@ -59,7 +60,18 @@ { "endsub", token_kw_endsub }, { "endfunction", token_kw_endfunction }, { "dim", token_kw_dim }, - { "=", token_op_assignment }, + { NULL } +}; + +/* contains "built in" function names */ +static struct token_list lexer_expr_tokens[] = +{ + { "and", token_op_and }, + { "or", token_op_or }, + { "band", token_op_band }, + { "bor", token_op_bor }, + { "bxor", token_op_bxor }, + { "xor", token_op_xor }, { NULL } }; @@ -77,6 +89,23 @@ "ENDFUNCTION", "DIM", "<assignment>", + "<equality>", + "<greater>", + "<less>", + "<greaterequal>", + "<lessequal>", + "<notequal>", + "<and>", + "<or>", + "<xor>", + "<bitwiseand>", + "<bitwiseor>", + "<bitwisexor>", + "<plus>", + "<minus>", + "<times>", + "<divide>", + "<modulus>", "<identifier>", "<char>", "<uint>", @@ -171,6 +200,11 @@ tok = lexer_global_tokens; } + if (state -> expression) + { + tok = lexer_expr_tokens; + } + /* check for tokens if appropriate */ /* force uppercase */ if (tok) @@ -194,6 +228,39 @@ state -> lexer_token = token_identifier; } +static void lexer_parse_number(cstate *state, int neg) +{ + unsigned long tint = 0; + int c; + + for (;;) + { + c = lexer_curchar(state); + if (c >= '0' && c <= '9') + { + tint *= 10 + (c - '0'); + } + else + { + /* end of the number here */ + if (neg) + { + if (tint > 0x80000000) + lwb_error("Integer overflow\n"); + state -> lexer_token_number.integer = -tint; + state -> lexer_token = token_int; + } + else + { + state -> lexer_token = token_uint; + state -> lexer_token_number.uinteger = tint; + } + return; + } + lexer_nextchar(state); + } +} + static void lexer_empty_token(cstate *state) { lw_free(state -> lexer_token_string); @@ -239,13 +306,101 @@ lexer_word(state); return; } + + if (state -> expression && c >= '0' && c <= '9') + { + /* we have a number */ + lexer_parse_number(state, 0); + return; + } + + lexer_nextchar(state); + if (state -> expression) + { + if (c == '-' && lexer_curchar(state) >= '0' && lexer_curchar(state) <= '9') + { + /* we have a negative number here */ + lexer_parse_number(state, 1); + return; + } + if (c == '=') + { + state -> lexer_token = token_op_equality; + return; + } + if (c == '<') + { + if (lexer_curchar(state) == '=') + { + lexer_nextchar(state); + state -> lexer_token = token_op_lessequal; + return; + } + if (lexer_curchar(state) == '>') + { + lexer_nextchar(state); + state -> lexer_token = token_op_notequal; + return; + } + state -> lexer_token = token_op_less; + return; + } + if (c == '>') + { + if (lexer_curchar(state) == '>') + { + lexer_nextchar(state); + state -> lexer_token = token_op_greaterequal; + return; + } + if (lexer_curchar(state) == '<') + { + state -> lexer_token = token_op_notequal; + lexer_nextchar(state); + return; + } + state -> lexer_token = token_op_greater; + return; + } + switch(c) + { + case '+': + state -> lexer_token = token_op_plus; + return; + + case '-': + state -> lexer_token = token_op_minus; + return; + + case '/': + state -> lexer_token = token_op_divide; + return; + + case '*': + state -> lexer_token = token_op_times; + return; + + case '%': + state -> lexer_token = token_op_modulus; + return; + + + } + } + else + { + if (c == '=') + { + state -> lexer_token = token_op_assignment; + return; + } + } /* return the character if all else fails */ + state -> lexer_token = token_char; state -> lexer_token_string = lw_realloc(state -> lexer_token_string, 2); state -> lexer_token_string[0] = c; state -> lexer_token_string[1] = 0; - lexer_nextchar(state); - state -> lexer_token = token_char; return; }
--- a/lwbasic/lwbasic.h Fri Feb 04 21:27:03 2011 -0700 +++ b/lwbasic/lwbasic.h Sat Feb 05 14:22:54 2011 -0700 @@ -53,7 +53,7 @@ int lexer_token; int lexer_curchar; int lexer_ignorechar; - + int expression; int parser_state; void *input_state; @@ -87,6 +87,23 @@ token_kw_endfunction, /* ENDFUNCTION keyword */ token_kw_dim, /* DIM keyword */ token_op_assignment, /* assignment operator */ + token_op_equality, /* equality test */ + token_op_greater, /* greater than */ + token_op_less, /* less than */ + token_op_greaterequal, /* greater or equal */ + token_op_lessequal, /* less or equal */ + token_op_notequal, /* not equal */ + token_op_and, /* boolean and */ + token_op_or, /* boolean or */ + token_op_xor, /* boolean exlusive or */ + token_op_band, /* bitwise and */ + token_op_bor, /* bitwise or */ + token_op_bxor, /* bitwise xor */ + token_op_plus, /* plus */ + token_op_minus, /* minus */ + token_op_times, /* times */ + token_op_divide, /* divide */ + token_op_modulus, /* modulus */ token_identifier, /* an identifier (variable, function, etc. */ token_char, /* single character; fallback */ token_uint, /* unsigned integer up to 32 bits */
--- a/lwbasic/parser.c Fri Feb 04 21:27:03 2011 -0700 +++ b/lwbasic/parser.c Sat Feb 05 14:22:54 2011 -0700 @@ -66,6 +66,14 @@ return pt; } +static int parse_expression(cstate *state) +{ + state -> expression = 1; + + state -> expression = 0; + return 1; +} + static void parse_decls(cstate *state) { /* declarations */ @@ -122,6 +130,7 @@ static void parse_statements(cstate *state) { symtab_entry_t *se; + int et; for (;;) { @@ -141,10 +150,14 @@ if (!se) lwb_error("Unknown variable %s\n", state -> lexer_token_string); lexer(state); + /* ensure the first token of the expression will be parsed correctly */ + state -> expression = 1; expect(state, token_op_assignment); /* parse the expression */ - /* parse_expression(state); */ + et = parse_expression(state); + + /* check type compatibility */ /* actually do the assignment */