Mercurial > hg-old > index.cgi
changeset 15:1f598d89b9b0
Started creating expression parser
author | lost |
---|---|
date | Thu, 23 Oct 2008 03:37:48 +0000 |
parents | b28d7cb60779 |
children | 4f14eae64d38 |
files | src/Makefile.am src/expr.c src/expr.h src/lwval.c src/lwval.h |
diffstat | 5 files changed, 403 insertions(+), 101 deletions(-) [+] |
line wrap: on
line diff
--- a/src/Makefile.am Thu Oct 23 02:44:07 2008 +0000 +++ b/src/Makefile.am Thu Oct 23 03:37:48 2008 +0000 @@ -1,3 +1,4 @@ bin_PROGRAMS = lwasm -lwasm_SOURCES = main.c expr.c pass1.c pass2.c -EXTRA_DIST = instab.h lwasm.h expr.h +lwasm_SOURCES = main.c expr.c lwval.c pass1.c pass2.c +EXTRA_DIST = instab.h lwasm.h expr.h lwval.h +
--- a/src/expr.c Thu Oct 23 02:44:07 2008 +0000 +++ b/src/expr.c Thu Oct 23 03:37:48 2008 +0000 @@ -19,57 +19,88 @@ */ /* -This file contains implementations associated with the expression evaluator -used by LWASM. - +This file contains the actual expression evaluator which uses the LWVAL +mechanism to store results. */ -#include <malloc.h> - #define __expr_c_seen__ + +#include <ctype.h> +#include <stdlib.h> + #include "expr.h" +#include "lwval.h" + +// parse a single term out of the expression; return NULL if +// end of expression; return LWVAL_TYPE_ERR if error +/* +The following is handled by lwasm_parse_term: -LWVAL *lwval_construct_int(int value) +- constants +- parsing a symbol +- unary - +- unary + +- () + +*/ +LWVAL *lwasm_parse_term(char **ptr) { - LWVAL *v; + int sign = 1; + int s = 0; + LWVAL *rval; - v = malloc(sizeof(LWVAL)); - if (!v) - return NULL; +start_term: + if (!**ptr || isspace(**ptr) || **ptr == ')') + return s ? lwval_construct_err(1) : NULL; + + s = 1; + // unary + - NOOP + if (**ptr == '+') + { + (*ptr)++; + goto start_term; + } + + // unary - - applied once the rest of the term is worked out + if (**ptr == '-') + { + (*ptr)++; + sign = -sign; + goto start_term; + } - v -> lwval_type = LWVAL_TYPE_INT; - v -> dt.lwval_int = value; - - return v; + // parens + if (**ptr == '(') + { + LWVAL *v; + (*ptr)++; + rval = lwasm_parse_expr(ptr); + if (**ptr != ')') + { + lwval_destroy(rval); + return lwval_construct_err(1); + } + (*ptr)++; + goto ret; + } + + // parse an actual term here; no more futzing with expressions + +ret: + // apply negation if appropriate + if (sign < 0) + lwval_neg(rval); + return rval; } -void lwval_destroy(LWVAL *value) -{ - if (value) - free(value); -} - -// v1 + v2 -> v3, return v3 -LWVAL *lwval_add(LWVAL *v1, LWVAL *v2, LWVAL *v3) +// parse an expression +LWVAL *lwasm_parse_expr(char **ptr) { } -// v1 - v2 -> v3, return v3 -LWVAL *lwval_sub(LWVAL *v1, LWVAL *v2, LWVAL *v3) -{ -} - -// v1 * v2 -> v3, return v3 -LWVAL *lwval_mul(LWVAL *v1, LWVAL *v2, LWVAL *v3) +// attempt to evaluate/simplify expression +int lwasm_eval_expr(LWVAL *expr) { } -// v1 / v2 -> v3, return v3 -LWVAL *lwval_div(LWVAL *v1, LWVAL *v2, LWVAL *v3) -{ -} -// v1 % v2 -> v3, return v3 -LWVAL *lwval_mod(LWVAL *v1, LWVAL *v2, LWVAL *v3) -{ -}
--- a/src/expr.h Thu Oct 23 02:44:07 2008 +0000 +++ b/src/expr.h Thu Oct 23 03:37:48 2008 +0000 @@ -19,77 +19,26 @@ */ /* -This file contains definitions associated with the expression evaluator used -by LWASM. - -The core of the entire expression handler is the opaque type LWVAL, pointers -to which are passed around to keep track of values. A value may be a simple -integer or it could be a more complex expression linked by operators or it -could be a polynomial expression. Simple integers are merely a degenerate -case of polynomials. - -The package understands the following operations: - -addition -subtraction -multiplication -division -modulus -parentheses -unary negation -unary "positive" -bitwise and -bitwise or -bitwise not (1's complement) -bitwise exclusive or - -Infix operators can be expressed as LWVAL <op> LWVAL. Thus, the order of -operations is only relevant when initially parsing the expression. The order -of evaluation is determined by what appears on either side of the <op> as -an LWVAL may be an expression. +Definitions for expression evaluator */ #ifndef __expr_h_seen__ #define __expr_h_seen__ -typedef struct lwval LWVAL; - -union lwval_dt -{ - int lwval_int; // integer type data - char *lwval_var; // pointer to variable name -}; - -enum -{ - LWVAL_TYPE_NAN, // not a number - LWVAL_TYPE_INT, // integer - LWVAL_TYPE_VAR, // variable (symbol) - LWVAL_TYPE_EXPR, // expression -}; - -struct lwval -{ - int lwval_type; // data type - union lwval_dt dt; // type specific stuff -}; +#include "lwval.h" #ifndef __expr_c_seen__ -#define EE extern +#define __expr_E__ extern #else -#define EE +#define __expr_E__ #endif -EE LWVAL *lwval_construct_int(int value); -EE void lwval_destroy(LWVAL *value); +// parse an expression +__expr_E__ LWVAL *lwasm_parse_expr(char **ptr); -// operators - operate on v1 and v2 in order, return in v3 -// if v3 is NULL, allocate new LWVAL and return it else just -// return v3 with new value in it -EE LWVAL *lwval_add(LWVAL *v1, LWVAL *v2, LWVAL *v3); -EE LWVAL *lwval_sub(LWVAL *v1, LWVAL *v2, LWVAL *v3); -EE LWVAL *lwval_mul(LWVAL *v1, LWVAL *v2, LWVAL *v3); -EE LWVAL *lwval_div(LWVAL *v1, LWVAL *v2, LWVAL *v3); -EE LWVAL *lwval_mod(LWVAL *v1, LWVAL *v2, LWVAL *v3); +// attempt to evaluate/simplify expression +__expr_E__ int lwasm_eval_expr(LWVAL *expr); -#endif //__expr_h_seen__ +#undef __expr_E__ + +#endif // __expr_h_seen__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lwval.c Thu Oct 23 03:37:48 2008 +0000 @@ -0,0 +1,210 @@ +/* +lwval.c +Copyright © 2008 William Astle + +This file is part of LWASM. + +LWASM is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* +This file contains implementations associated with the expression evaluator +used by LWASM. + +*/ + +#include <malloc.h> + +#define __lwval_c_seen__ +#include "lwval.h" + +LWVAL *lwval_construct_int(int value) +{ + LWVAL *v; + + v = malloc(sizeof(LWVAL)); + if (!v) + return NULL; + + v -> lwval_type = LWVAL_TYPE_INT; + v -> dt.lwval_int = value; + + return v; +} + +LWVAL *lwval_construct_err(int errno) +{ + LWVAL *v; + + v = malloc(sizeof(LWVAL)); + if (!v) + return NULL; + + v -> lwval_type = LWVAL_TYPE_ERR; + v -> dt.lwval_int = errno; + + return v; +} + +LWVAL *lwval_construct_nan(void) +{ + LWVAL *v; + + v = malloc(sizeof(LWVAL)); + if (!v) + return NULL; + + v -> lwval_type = LWVAL_TYPE_NAN; + + return v; +} + +LWVAL *lwval_construct_undef(void) +{ + LWVAL *v; + + v = malloc(sizeof(LWVAL)); + if (!v) + return NULL; + + v -> lwval_type = LWVAL_TYPE_UNDEF; + + return v; +} + +LWVAL *lwval_construct_expr(LWVAL *v1, LWVAL *v2, int op) +{ + LWVAL *v; + v = malloc(sizeof(LWVAL)); + if (!v) + return NULL; + + v -> lwval_type = LWVAL_TYPE_EXPR; + v -> dt.expr.v1 = v1; + v -> dt.expr.v2 = v2; + v -> dt.expr.op = op; + return v; +} + +void lwval_destroy(LWVAL *value) +{ + if (value) + { + lwval_clear(value); + free(value); + } +} + +// performs a deep copy of an LWVAL, including ALL referenced values +void lwval_dup(LWVAL *v1, LWVAL *v2) +{ + lwval_clear(v2); + + switch (v1 -> lwval_type) + { + case LWVAL_TYPE_INT: + case LWVAL_TYPE_ERR: + v2 -> dt.lwval_int = v1 -> dt.lwval_int; + break; + + case LWVAL_TYPE_EXPR: + v2 -> dt.expr.op = v1 -> dt.expr.op; + if (v1 -> dt.expr.v1) + { + v2 -> dt.expr.v1 = lwval_construct_undef(); + lwval_dup(v1 -> dt.expr.v1, v2 -> dt.expr.v1); + } + else + v2 -> dt.expr.v1 = NULL; + if (v1 -> dt.expr.v2) + { + v2 -> dt.expr.v2 = lwval_construct_undef(); + lwval_dup(v1 -> dt.expr.v2, v2 -> dt.expr.v2); + } + else + v2 -> dt.expr.v2 = NULL; + break; + } + + v2 -> lwval_type = v1 -> lwval_type; +} + +void lwval_clear(LWVAL *value) +{ + switch (value -> lwval_type) + { + case LWVAL_TYPE_EXPR: + lwval_destroy(value -> dt.expr.v1); + lwval_destroy(value -> dt.expr.v2); + break; + } + value -> lwval_type = LWVAL_TYPE_UNDEF; +} + +// for integer, simply negate value +// for expr, change to "-1 * (expr)" +// everything else: error +LWVAL *lwval_neg(LWVAL *v1) +{ + switch (v1 -> lwval_type) + { + case LWVAL_TYPE_INT: + v1 -> dt.lwval_int = -(v1 -> dt.lwval_int); + break; + + case LWVAL_TYPE_EXPR: + { + LWVAL *v, *v2; + v = lwval_construct_undef(); + lwval_dup(v1, v); + lwval_clear(v1); + v2 = lwval_construct_expr(lwval_construct_int(-1), v, '*'); + lwval_dup(v2, v1); + lwval_destroy(v2); + } + break; + + default: + lwval_clear(v1); + v1 -> lwval_type = LWVAL_TYPE_ERR; + v1 -> dt.lwval_int = 1; + } + + return v1; +} + +// v1 + v2 -> v1 +LWVAL *lwval_add(LWVAL *v1, LWVAL *v2) +{ +} + +// v1 - v2 -> v1 +LWVAL *lwval_sub(LWVAL *v1, LWVAL *v2) +{ +} + +// v1 * v2 -> v1 +LWVAL *lwval_mul(LWVAL *v1, LWVAL *v2) +{ +} + +// v1 / v2 -> v1 +LWVAL *lwval_div(LWVAL *v1, LWVAL *v2) +{ +} + +// v1 % v2 -> v1 +LWVAL *lwval_mod(LWVAL *v1, LWVAL *v2) +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lwval.h Thu Oct 23 03:37:48 2008 +0000 @@ -0,0 +1,111 @@ +/* +lwval.h +Copyright © 2008 William Astle + +This file is part of LWASM. + +LWASM is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* +This file contains definitions associated with the expression evaluator used +by LWASM. + +The core of the entire expression handler is the opaque type LWVAL, pointers +to which are passed around to keep track of values. A value may be a simple +integer or it could be a more complex expression linked by operators or it +could be a polynomial expression. Simple integers are merely a degenerate +case of polynomials. + +The package understands the following operations: + +addition +subtraction +multiplication +division +modulus +parentheses +unary negation +unary "positive" +bitwise and +bitwise or +bitwise not (1's complement) +bitwise exclusive or + +Infix operators can be expressed as LWVAL <op> LWVAL. Thus, the order of +operations is only relevant when initially parsing the expression. The order +of evaluation is determined by what appears on either side of the <op> as +an LWVAL may be an expression. +*/ + +#ifndef __lwval_h_seen__ +#define __lwval_h_seen__ + +typedef struct lwval LWVAL; + +struct lwval_dt_expr +{ + LWVAL *v1; // first value + LWVAL *v2; // second value + int op; // operator +}; + +union lwval_dt +{ + int lwval_int; // integer type data + char *lwval_var; // pointer to variable name + struct lwval_dt_expr expr; // expression +}; + +enum +{ + LWVAL_TYPE_UNDEF, // undefined + LWVAL_TYPE_NAN, // not a number + LWVAL_TYPE_INT, // integer + LWVAL_TYPE_VAR, // variable (symbol) + LWVAL_TYPE_EXPR, // expression + LWVAL_TYPE_ERR // error +}; + +struct lwval +{ + int lwval_type; // data type + union lwval_dt dt; // type specific stuff +}; + +#ifndef __lwval_c_seen__ +#define EE extern +#else +#define EE +#endif + +EE LWVAL *lwval_construct_int(int value); +EE LWVAL *lwval_construct_err(int errno); +EE LWVAL *lwval_construct_nan(void); +EE LWVAL *lwval_construct_expr(LWVAL *v1, LWVAL *v2, int op); +EE LWVAL *lwval_construct_undef(void); +EE void lwval_clear(LWVAL *value); +EE void lwval_destroy(LWVAL *value); +EE void lwval_dup(LWVAL *v1, LWVAL *v2); + +// operators - operate on v1 and v2 in order, result goes into +// v1; return v1 +EE LWVAL *lwval_add(LWVAL *v1, LWVAL *v2); +EE LWVAL *lwval_sub(LWVAL *v1, LWVAL *v2); +EE LWVAL *lwval_mul(LWVAL *v1, LWVAL *v2); +EE LWVAL *lwval_div(LWVAL *v1, LWVAL *v2); +EE LWVAL *lwval_mod(LWVAL *v1, LWVAL *v2); +EE LWVAL *lwval_neg(LWVAL *v1); + +#endif //__lwval_h_seen__