> 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:
@ -58,4 +58,4 @@ LINKAGE += $(ARCHIVES)
|
||||
else
|
||||
# Include rules to build NEMU
|
||||
include $(NEMU_HOME)/scripts/native.mk
|
||||
endif
|
||||
endif
|
@ -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;
|
||||
}
|
||||
|
@ -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
5
nemu/tests/Makefile
Normal 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
187
nemu/tests/test_sdb_expr.c
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user