> compile NEMU

221220000 张三
Linux zzy 5.15.146.1-microsoft-standard-WSL2 #1 SMP Thu Jan 11 04:09:03 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
 20:14:34 up 10:54,  2 users,  load average: 0.37, 0.15, 0.05
This commit is contained in:
tracer-ics2023
2024-08-17 20:14:35 +08:00
committed by zzy
parent b8bb25692f
commit 01d1c63363
5 changed files with 222 additions and 5 deletions

View File

@ -58,4 +58,4 @@ LINKAGE += $(ARCHIVES)
else
# Include rules to build NEMU
include $(NEMU_HOME)/scripts/native.mk
endif
endif

View File

@ -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;
}

View File

@ -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;

5
nemu/tests/Makefile Normal file
View File

@ -0,0 +1,5 @@
CC = gcc
CFLAGS = -Og -std=c99 -Wall -Werror -D__TEST__
test_sdb_expr:
$(CC) $(CFLAGS) -o $@ $@.c

187
nemu/tests/test_sdb_expr.c Normal file
View File

@ -0,0 +1,187 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#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 <regex.h>
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;
}