From 01d1c63363d30aee9b107d030d9962f7bdb1214b Mon Sep 17 00:00:00 2001 From: tracer-ics2023 Date: Sat, 17 Aug 2024 20:14:35 +0800 Subject: [PATCH] =?UTF-8?q?>=20=20compile=20NEMU=20221220000=20=E5=BC=A0?= =?UTF-8?q?=E4=B8=89=20Linux=20zzy=205.15.146.1-microsoft-standard-WSL2=20?= =?UTF-8?q?#1=20SMP=20Thu=20Jan=2011=2004:09:03=20UTC=202024=20x86=5F64=20?= =?UTF-8?q?x86=5F64=20x86=5F64=20GNU/Linux=20=2020:14:34=20up=2010:54,=20?= =?UTF-8?q?=202=20users,=20=20load=20average:=200.37,=200.15,=200.05?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nemu/Makefile | 2 +- nemu/src/monitor/sdb/expr.c | 32 +++++- nemu/src/monitor/sdb/sdb.c | 1 - nemu/tests/Makefile | 5 + nemu/tests/test_sdb_expr.c | 187 ++++++++++++++++++++++++++++++++++++ 5 files changed, 222 insertions(+), 5 deletions(-) create mode 100644 nemu/tests/Makefile create mode 100644 nemu/tests/test_sdb_expr.c diff --git a/nemu/Makefile b/nemu/Makefile index c94e04f..44eee8b 100644 --- a/nemu/Makefile +++ b/nemu/Makefile @@ -58,4 +58,4 @@ LINKAGE += $(ARCHIVES) else # Include rules to build NEMU include $(NEMU_HOME)/scripts/native.mk -endif +endif \ No newline at end of file diff --git a/nemu/src/monitor/sdb/expr.c b/nemu/src/monitor/sdb/expr.c index 9f38355..f60707c 100644 --- a/nemu/src/monitor/sdb/expr.c +++ b/nemu/src/monitor/sdb/expr.c @@ -139,6 +139,34 @@ static bool make_token(char *e) { return true; } +bool check_parentheses(Token* tokens, size_t len, size_t p, size_t q) { + + return false; +} + +word_t eval(size_t p, size_t q) { + if (p > q) { + /* Bad expression */ + panic("bad expression"); + } + else if (p == q) { + /* Single token. + * For now this token should be a number. + * Return the value of the number. + */ + return atoi(tokens[p].str); + } + else if (check_parentheses(tokens, ARRLEN(tokens), p, q) == true) { + /* The expression is surrounded by a matched pair of parentheses. + * If that is the case, just throw away the parentheses. + */ + return eval(p + 1, q - 1); + } + else { + /* We should do more things here. */ + return 0; + } +} word_t expr(char *e, bool *success) { if (!make_token(e)) { @@ -148,9 +176,7 @@ word_t expr(char *e, bool *success) { /* TODO: Insert codes to evaluate the expression. */ // TODO(); - for (int i = 0; i < nr_token; i++) { - Log("token[%d].type = %d, token[%d].str = %s", i, tokens[i].type, i, tokens[i].str); - } + return 0; } diff --git a/nemu/src/monitor/sdb/sdb.c b/nemu/src/monitor/sdb/sdb.c index aee4b32..e993405 100644 --- a/nemu/src/monitor/sdb/sdb.c +++ b/nemu/src/monitor/sdb/sdb.c @@ -51,7 +51,6 @@ static int cmd_c(char *args) { return 0; } - static int cmd_q(char *args) { set_nemu_state(NEMU_END, 0, 0); return -1; diff --git a/nemu/tests/Makefile b/nemu/tests/Makefile new file mode 100644 index 0000000..145615b --- /dev/null +++ b/nemu/tests/Makefile @@ -0,0 +1,5 @@ +CC = gcc +CFLAGS = -Og -std=c99 -Wall -Werror -D__TEST__ + +test_sdb_expr: + $(CC) $(CFLAGS) -o $@ $@.c \ No newline at end of file diff --git a/nemu/tests/test_sdb_expr.c b/nemu/tests/test_sdb_expr.c new file mode 100644 index 0000000..9c9dd67 --- /dev/null +++ b/nemu/tests/test_sdb_expr.c @@ -0,0 +1,187 @@ +#include +#include +#include +#include +#include +#include + +#define panic(fmt, ...) printf(fmt, ## __VA_ARGS__) +#define Log(fmt, ...) printf(fmt, ## __VA_ARGS__) + +#define ARRLEN(arr) (sizeof(arr) / sizeof(arr[0])) +typedef uint32_t word_t; + +/* We use the POSIX regex functions to process regular expressions. + * Type 'man regex' for more information about POSIX regex functions. + */ +#include + +enum { + TK_NOTYPE = 256, TK_EQ, + TK_DEC, + + /* TODO: Add more token types */ + +}; + +static struct rule { + const char *regex; + int token_type; +} rules[] = { + + /* TODO: Add more rules. + * Pay attention to the precedence level of different rules. + */ + + {" +", TK_NOTYPE}, // spaces + {"\\+", '+'}, // plus + {"==", TK_EQ}, // equal + + {"-", '-'}, // sub + {"\\*", '*'}, // mul + {"/", '/'}, // div + {"\\(", '('}, // ( + {"\\)", ')'}, // ) + {"[0-9]+", TK_DEC}, // dec number +}; + +#define NR_REGEX ARRLEN(rules) + +static regex_t re[NR_REGEX] = {}; + +/* Rules are used for many times. + * Therefore we compile them only once before any usage. + */ +void init_regex() { + int i; + char error_msg[128]; + int ret; + + for (i = 0; i < NR_REGEX; i ++) { + ret = regcomp(&re[i], rules[i].regex, REG_EXTENDED); + if (ret != 0) { + regerror(ret, &re[i], error_msg, 128); + panic("regex compilation failed: %s\n%s", error_msg, rules[i].regex); + } + } +} + +typedef struct token { + int type; + char str[32]; +} Token; + +static Token tokens[32] __attribute__((used)) = {}; +static int nr_token __attribute__((used)) = 0; + +static bool make_token(char *e) { + int position = 0; + int i; + regmatch_t pmatch; + + nr_token = 0; + + while (e[position] != '\0') { + /* Try all rules one by one. */ + for (i = 0; i < NR_REGEX; i ++) { + if (regexec(&re[i], e + position, 1, &pmatch, 0) == 0 && pmatch.rm_so == 0) { + char *substr_start = e + position; + int substr_len = pmatch.rm_eo; + + Log("match rules[%d] = \"%s\" at position %d with len %d: %.*s", + i, rules[i].regex, position, substr_len, substr_len, substr_start); + + position += substr_len; + + /* TODO: Now a new token is recognized with rules[i]. Add codes + * to record the token in the array `tokens'. For certain types + * of tokens, some extra actions should be performed. + */ + + tokens[nr_token].type = rules[i].token_type; + switch (rules[i].token_type) { + case '+': + case '-': + case '*': + case '/': + case '(': + case ')': + break; + case TK_DEC: + if (substr_len + 1 > sizeof(((Token*)0)->str)) { + printf("token string is too long"); + return false; + } + strncpy(tokens[nr_token].str, substr_start, substr_len); + tokens[nr_token].str[substr_len] = '\0'; + break; + case TK_EQ: + case TK_NOTYPE: + break; + default: ; + } + nr_token ++; + + break; + } + } + + if (i == NR_REGEX) { + printf("no match at position %d\n%s\n%*.s^\n", position, e, position, ""); + return false; + } + } + + return true; +} + +bool check_parentheses(size_t p, size_t q) { + + return false; +} + +word_t eval(size_t p, size_t q) { + if (p > q) { + /* Bad expression */ + panic("bad expression"); + } + else if (p == q) { + /* Single token. + * For now this token should be a number. + * Return the value of the number. + */ + return atoi(tokens[p].str); + } + else if (check_parentheses(p, q) == true) { + /* The expression is surrounded by a matched pair of parentheses. + * If that is the case, just throw away the parentheses. + */ + return eval(p + 1, q - 1); + } + else { + /* We should do more things here. */ + return eval(p, p) + eval(p + 1, q); + } + return 0; +} + +word_t expr(char *e, bool *success) { + if (!make_token(e)) { + *success = false; + return 0; + } + + /* TODO: Insert codes to evaluate the expression. */ + // TODO(); + + + return 0; +} + +int main(void) { + init_regex(); + + make_token("1+2"); + + return 0; +}