pa1.2: use flex and bason to implement expr parser
This commit is contained in:
parent
69264e69c6
commit
9cca9de2a8
11 changed files with 297 additions and 29 deletions
1
nemu/src/isa/riscv64
Symbolic link
1
nemu/src/isa/riscv64
Symbolic link
|
@ -0,0 +1 @@
|
|||
riscv32
|
2
nemu/src/monitor/sdb/.gitignore
vendored
Normal file
2
nemu/src/monitor/sdb/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
addrexp_lex.h
|
||||
addrexp.h
|
13
nemu/src/monitor/sdb/addrexp.l
Normal file
13
nemu/src/monitor/sdb/addrexp.l
Normal file
|
@ -0,0 +1,13 @@
|
|||
%{
|
||||
#include <addrexp.h>
|
||||
%}
|
||||
%option noyywrap
|
||||
|
||||
%%
|
||||
|
||||
0[xX][0-9a-fA-F]+ { yylval = strtol(yytext, NULL, 16); return HEX_NUMBER; }
|
||||
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
|
||||
[+\-*/()] { return *yytext; }
|
||||
[ \t] { }
|
||||
. { printf("Unexpected character: %s\n", yytext); }
|
||||
%%
|
36
nemu/src/monitor/sdb/addrexp.y
Normal file
36
nemu/src/monitor/sdb/addrexp.y
Normal file
|
@ -0,0 +1,36 @@
|
|||
%{
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
extern int yylex(void);
|
||||
void yyerror(uint32_t *result, const char *s) {
|
||||
fprintf(stderr, "Error: %s\n", s);
|
||||
}
|
||||
%}
|
||||
|
||||
%token NUMBER HEX_NUMBER
|
||||
%start input
|
||||
%define api.value.type { uint32_t }
|
||||
%parse-param { uint32_t *result }
|
||||
%left '+' '-'
|
||||
%left '*' '/'
|
||||
|
||||
%%
|
||||
input
|
||||
: expression { *result = $1; }
|
||||
;
|
||||
|
||||
expression
|
||||
: expression '+' expression { $$ = $1 + $3; }
|
||||
| expression '-' expression { $$ = $1 - $3; }
|
||||
| expression '*' expression { $$ = $1 * $3; }
|
||||
| expression '/' expression { $$ = $1 / $3; }
|
||||
| '-' number { $$ = -$2; }
|
||||
| '(' expression ')' { $$ = $2; }
|
||||
| number { $$ = $1; }
|
||||
|
||||
number
|
||||
: NUMBER
|
||||
| HEX_NUMBER
|
||||
|
||||
%%
|
|
@ -21,24 +21,18 @@
|
|||
#include <regex.h>
|
||||
|
||||
enum {
|
||||
TK_NOTYPE = 256, TK_EQ,
|
||||
|
||||
/* TODO: Add more token types */
|
||||
|
||||
TK_NOTYPE = 256, TK_EQ, TK_NUMBER,
|
||||
LEX_GROUP_OPERATOR, LEX_GROUP_DIGIT
|
||||
};
|
||||
|
||||
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
|
||||
{"[ \t]+", TK_NOTYPE},
|
||||
{"==", TK_EQ},
|
||||
{"[0-9]+", LEX_GROUP_DIGIT},
|
||||
{"[\\+-*/()", LEX_GROUP_OPERATOR},
|
||||
};
|
||||
|
||||
#define NR_REGEX ARRLEN(rules)
|
||||
|
@ -95,6 +89,16 @@ static bool make_token(char *e) {
|
|||
*/
|
||||
|
||||
switch (rules[i].token_type) {
|
||||
case LEX_GROUP_OPERATOR:
|
||||
tokens[nr_token].type = *substr_start;
|
||||
tokens[nr_token].str[0] = '\0';
|
||||
nr_token++;
|
||||
break;
|
||||
case LEX_GROUP_DIGIT:
|
||||
tokens[nr_token].type = TK_NUMBER;
|
||||
nr_token++;
|
||||
break;
|
||||
case TK_NOTYPE: break;
|
||||
default: TODO();
|
||||
}
|
||||
|
||||
|
|
3
nemu/src/monitor/sdb/filelist.mk
Normal file
3
nemu/src/monitor/sdb/filelist.mk
Normal file
|
@ -0,0 +1,3 @@
|
|||
SRCS-y += src/monitor/sdb/addrexp.tag.c src/monitor/sdb/addrexp.yy.c
|
||||
INC_PATH += src/monitor/sdb
|
||||
LFLAGS += -DYY_NO_UNPUT -DYY_NO_INPUT
|
|
@ -23,6 +23,8 @@
|
|||
#include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
#include <stdint.h>
|
||||
#include <addrexp.h>
|
||||
#include <addrexp_lex.h>
|
||||
|
||||
static int is_batch_mode = false;
|
||||
|
||||
|
@ -107,7 +109,7 @@ static word_t parse_uint(const char *arg, bool *success) {
|
|||
char *endptr;
|
||||
uintmax_t n = strtoumax(arg, &endptr, base);
|
||||
if (errno == ERANGE || n > WORD_T_MAX) {
|
||||
printf("%s is exceed the limit of uint\n", arg);
|
||||
printf("%s exceed the limit of uint\n", arg);
|
||||
*success = false;
|
||||
return 0;
|
||||
} else if (arg == endptr) {
|
||||
|
@ -129,10 +131,14 @@ static paddr_t parse_expr(const char *arg, bool *success) {
|
|||
*success = false;
|
||||
return 0;
|
||||
} else {
|
||||
bool res = false;
|
||||
// bool res = false;
|
||||
// FIXME: We cannot use `parse_uint` here, it accept `-1234` as input
|
||||
paddr_t addr = parse_uint(arg, &res);
|
||||
*success = res;
|
||||
// paddr_t addr = parse_uint(arg, &res);
|
||||
// *success = res;
|
||||
paddr_t addr;
|
||||
yy_scan_string(arg);
|
||||
*success = !yyparse(&addr);
|
||||
yylex_destroy();
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
@ -199,7 +205,7 @@ static int cmd_x(char *args) {
|
|||
return 0;
|
||||
|
||||
wrong_usage:
|
||||
printf("Invalid argument for command si: %s\n", args);
|
||||
printf("Invalid argument for command x: %s\n", args);
|
||||
printf("Usage: x [N: uint] [EXPR: <expr>]\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -324,8 +330,8 @@ void sdb_mainloop() {
|
|||
}
|
||||
|
||||
void init_sdb() {
|
||||
/* Compile the regular expressions. */
|
||||
init_regex();
|
||||
// /* Compile the regular expressions. */
|
||||
// init_regex();
|
||||
|
||||
/* Initialize the watchpoint pool. */
|
||||
init_wp_pool();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue