Skip to content
Snippets Groups Projects
Verified Commit 9de1dd73 authored by Recolic Keghart's avatar Recolic Keghart
Browse files

> Manual commit: Finished expression parser. Slightly changed Makefile and gitignore file.

U201614531
recolic
Linux RECOLICPC 5.4.2-arch1-1 #1 SMP PREEMPT Thu, 05 Dec 2019 12:29:40 +0000 x86_64 GNU/Linux
 23:53:05 up 3 days,  7:11,  1 user,  load average: 0.74, 1.27, 1.12
31989000402905faaa2cb728bf473984cea394e
parent 5d2ab63a
No related branches found
No related tags found
No related merge requests found
*.yy.cc
*.tab.cc
*.tab.h
*.d
*.o
*.out
*.output
build
.idea
.vscode
......@@ -36,10 +36,14 @@ $(OBJ_DIR)/%.o: src/%.cc
# Depencies
-include $(OBJS:.o=.d)
# Some convinient rules
# Source code generation before any targets.
SUBDIRS = src/monitor/debug/expr_impl
$(SUBDIRS):
$(MAKE) -C $@
.PHONY: app run clean
app: $(BINARY)
# Some convinient rules
.PHONY: app run clean $(SUBDIRS)
app: $(SUBDIRS) $(BINARY)
override ARGS ?= -l $(BUILD_DIR)/nemu-log.txt
override ARGS += -d $(NEMU_HOME)/tools/qemu-diff/build/qemu-so
......
#ifndef __MACRO_H__
#define __MACRO_H__
// From rlib/macro.hpp
#ifndef _RLIB_MACRO_ENSTRING
#define _RLIB_MACRO_ENSTRING(_s) #_s
#endif
#ifndef RLIB_MACRO_TO_CSTR
#define RLIB_MACRO_TO_CSTR(m) _RLIB_MACRO_ENSTRING(m)
#endif
// Implements origin `str()` macro. Extremely bad naming.
#include <rlib/macro.hpp>
#define concat_temp(x, y) x ## y
#define concat(x, y) concat_temp(x, y)
......
#ifndef RCPP_HUST_PARSER_INTERFACE_H_
#define RCPP_HUST_PARSER_INTERFACE_H_ 1
#include <string>
#include <cstdint>
// Implemented in src/monitor/debug/expr_impl/parser.y
int64_t parse_one(std::string expr);
#endif
\ No newline at end of file
......@@ -6,6 +6,9 @@
#include <sys/types.h>
#include <regex.h>
#include "monitor/expr_impl/parser_interface.h"
#include <rlib/stdio.hpp>
enum {
TK_NOTYPE = 256, TK_EQ
......@@ -14,7 +17,7 @@ enum {
};
static struct rule {
char *regex;
const char *regex;
int token_type;
} rules[] = {
......@@ -103,7 +106,14 @@ uint32_t expr(char *e, bool *success) {
}
/* TODO: Insert codes to evaluate the expression. */
TODO();
return 0;
try {
auto res = parse_one(std::string(e));
*success = true;
return res;
}
catch(std::exception &e) {
rlib::println("Exception caught:", e.what());
*success = false;
return 0;
}
}
generate: parser.tab.cc lexer.yy.cc parser.tab.h
all: parser
parser.tab.cc parser.tab.h: parser.y
@echo Generating $@...
bison --defines=parser.tab.h -o parser.tab.cc parser.y
lexer.yy.cc: lexer.l parser.tab.h
@echo Generating $@...
flex -o lexer.yy.cc lexer.l
parser: generate
g++ -o parser parser.tab.cc lexer.yy.cc
clean:
rm -f parser parser.tab.cc lexer.yy.cc parser.tab.h
%option noyywrap
%{
#define YY_DECL int yylex()
#include "parser.tab.h"
#include <stdint.h>
%}
%%
[ \t\n] {}
0x[0-9]+ {yylval.ival = (int)strtol(yytext, NULL, 16); return T_INT;}
[0-9]+ {yylval.ival = atoi(yytext); return T_INT;}
"==" {return T_EQUAL;}
"!=" {return T_NEQUAL;}
"&&" {return T_LOGICAL_AND;}
[-+*/()] {return yytext[0];}
"%"[a-z]{3} {yylval.ival = ((uint32_t)yytext[1] << 8) + yytext[2]; return T_REG;}
%%
// Registers: eax='a'+'x', ebx='b'+'x', ...
%{
#include <string>
#include <rlib/stdio.hpp>
#include <cassert>
#include <cstdlib>
extern int yylex();
extern int yyparse();
typedef struct yy_buffer_state * YY_BUFFER_STATE;
extern YY_BUFFER_STATE yy_scan_string(const char * str);
void yyerror(int64_t *result, std::string s);
uint32_t ryy_read_cpu_reg_value(int64_t which_reg);
uint32_t ryy_read_memory_value(uint32_t addr);
%}
%union {
int64_t ival;
}
%token<ival> T_INT T_REG // I represent REG by: (int)(REG_NAME[1] << 8 + REG_NAME[2])
%left T_LOGICAL_AND
%left T_EQUAL T_NEQUAL
%left '+' '-'
%left '*' '/'
%type<ival> expr
%start entry
%parse-param {int64_t *result}
%%
entry: {*result = 0;}
| expr {*result = $1;}
;
expr: T_INT { $$ = $1; }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
| expr T_EQUAL expr { $$ = ($1 == $3); }
| expr T_NEQUAL expr { $$ = ($1 != $3); }
| expr T_LOGICAL_AND expr { $$ = ($1 && $3); }
| '(' expr ')' { $$ = $2; }
| '-' expr { $$ = 0 - $2; }
| '*' expr { $$ = ryy_read_memory_value((uint32_t)$2); }
| T_REG { $$ = ryy_read_cpu_reg_value($1); }
;
%%
#include "monitor/expr_impl/parser_interface.h"
int64_t parse_one(std::string expr) {
yy_scan_string(expr.c_str());
int64_t result;
assert(0 == yyparse(&result));
return result;
}
int ryy_test_main() {
while(!std::cin.eof()) {
rlib::println(parse_one(rlib::scanln()));
}
return 0;
}
void yyerror(int64_t *result, std::string msg) {
rlib::println("Parse error:", msg);
exit(1);
}
// v-cpu related code:
#include "cpu/reg.h"
#include "memory/memory.h"
#include <rlib/macro.hpp>
uint32_t ryy_read_cpu_reg_value(int64_t which_reg) {
#define CODE_OF(reg) (((uint32_t)RLIB_MACRO_TO_CSTR(reg)[1] << 8) + RLIB_MACRO_TO_CSTR(reg)[2])
switch(which_reg) {
case CODE_OF(eax):
return cpu.eax;
case CODE_OF(ebx):
return cpu.ebx;
case CODE_OF(ecx):
return cpu.ecx;
case CODE_OF(edx):
return cpu.edx;
case CODE_OF(esp):
return cpu.esp;
case CODE_OF(ebp):
return cpu.ebp;
case CODE_OF(esi):
return cpu.esi;
case CODE_OF(edi):
return cpu.edi;
case CODE_OF(eip):
return cpu.eip;
default:
throw std::invalid_argument("Invalid register name.");
}
#undef CODE_OF
}
uint32_t ryy_read_memory_value(uint32_t addr) {
return vaddr_read(addr, 4);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment