framework init
This commit is contained in:
commit
7b1e1ef1eb
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
.*
|
||||
!.gitignore
|
||||
|
||||
*.o
|
||||
*.out
|
||||
|
||||
*.obj
|
||||
*.exe
|
5
Makefile
Normal file
5
Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
CXX = g++
|
||||
CXX_FLAG = -g -std=c++11 -Wall -Werror
|
||||
|
||||
all:
|
||||
$(CXX) $(CXX_FLAG) -o main.out main.c expr.cpp
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
||||
注意 由于使用c++的regex库,所以需要编译时需要注意大于等于c++11语法
|
||||
注意 这是一个多文件编译的项目,需要你结合main.c和expr.cpp使用
|
||||
注意 gen-expr里面需要命令行里编译c语言,所以Windows需要自行配置以保证可以使用system命令编译,以及popen的路径
|
17
common.h
Normal file
17
common.h
Normal file
@ -0,0 +1,17 @@
|
||||
// Modified by: Zhiyi Zhang in 2024.08
|
||||
|
||||
#ifndef __COMMON_H__
|
||||
#define __COMMON_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#include "debug.h"
|
||||
|
||||
#define ARRLEN(arr) ((int)(sizeof(arr) / sizeof(arr[0])))
|
||||
|
||||
#endif
|
67
debug.h
Normal file
67
debug.h
Normal file
@ -0,0 +1,67 @@
|
||||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
// Modified by: Zhiyi Zhang in 2024.08
|
||||
|
||||
#ifndef __DEBUG_H__
|
||||
#define __DEBUG_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
// ----------- log -----------
|
||||
|
||||
#define ANSI_FG_BLACK "\33[1;30m"
|
||||
#define ANSI_FG_RED "\33[1;31m"
|
||||
#define ANSI_FG_GREEN "\33[1;32m"
|
||||
#define ANSI_FG_YELLOW "\33[1;33m"
|
||||
#define ANSI_FG_BLUE "\33[1;34m"
|
||||
#define ANSI_FG_MAGENTA "\33[1;35m"
|
||||
#define ANSI_FG_CYAN "\33[1;36m"
|
||||
#define ANSI_FG_WHITE "\33[1;37m"
|
||||
#define ANSI_BG_BLACK "\33[1;40m"
|
||||
#define ANSI_BG_RED "\33[1;41m"
|
||||
#define ANSI_BG_GREEN "\33[1;42m"
|
||||
#define ANSI_BG_YELLOW "\33[1;43m"
|
||||
#define ANSI_BG_BLUE "\33[1;44m"
|
||||
#define ANSI_BG_MAGENTA "\33[1;35m"
|
||||
#define ANSI_BG_CYAN "\33[1;46m"
|
||||
#define ANSI_BG_WHITE "\33[1;47m"
|
||||
#define ANSI_NONE "\33[0m"
|
||||
|
||||
#define ANSI_FMT(str, fmt) fmt str ANSI_NONE
|
||||
|
||||
#define _Log(...) \
|
||||
do { \
|
||||
printf(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define Log(format, ...) \
|
||||
_Log(ANSI_FMT("[%s:%d %s] " format, ANSI_FG_BLUE) "\n", \
|
||||
__FILE__, __LINE__, __func__, ## __VA_ARGS__)
|
||||
|
||||
#define Assert(cond, format, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
fflush(stdout); \
|
||||
fprintf(stderr, ANSI_FMT(format, ANSI_FG_RED) "\n", ## __VA_ARGS__); \
|
||||
assert(cond); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define panic(format, ...) Assert(0, format, ## __VA_ARGS__)
|
||||
|
||||
#define TODO() panic("please implement me")
|
||||
|
||||
#endif
|
122
expr.cpp
Normal file
122
expr.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
// Modified by: Zhiyi Zhang in 2024.08
|
||||
|
||||
#include "common.h"
|
||||
/* We use the POSIX regex functions to process regular expressions.
|
||||
* Type 'man regex' for more information about POSIX regex functions.
|
||||
*/
|
||||
#include <regex>
|
||||
|
||||
enum {
|
||||
TK_NOTYPE = 256, TK_EQ,
|
||||
|
||||
/* 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
|
||||
};
|
||||
|
||||
#define NR_REGEX ARRLEN(rules)
|
||||
|
||||
static std::regex re[NR_REGEX] = {};
|
||||
|
||||
/* Rules are used for many times.
|
||||
* Therefore we compile them only once before any usage.
|
||||
*/
|
||||
void init_regex() {
|
||||
for (int i = 0; i < NR_REGEX; i ++) {
|
||||
try {
|
||||
re[i] = std::regex(rules[i].regex, std::regex_constants::ECMAScript);
|
||||
}
|
||||
catch(const std::regex_error & e) {
|
||||
panic("regex compilation failed: %s\n%s", e.what(), 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;
|
||||
std::cmatch 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) {
|
||||
if (std::regex_search(e + position, pmatch, re[i], std::regex_constants::match_continuous)) {
|
||||
char *substr_start = e + position;
|
||||
int substr_len = pmatch.length();
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
switch (rules[i].token_type) {
|
||||
default: TODO();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == NR_REGEX) {
|
||||
printf("no match at position %d\n%s\n%*.s^\n", position, e, position, "");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t expr(char *e, bool *success) {
|
||||
if (!make_token(e)) {
|
||||
*success = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: Insert codes to evaluate the expression. */
|
||||
TODO();
|
||||
|
||||
return 0;
|
||||
}
|
75
gen-expr/gen-expr.c
Normal file
75
gen-expr/gen-expr.c
Normal file
@ -0,0 +1,75 @@
|
||||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
// Modified by: Zhiyi Zhang in 2024.08
|
||||
|
||||
#define TMP_FILE_PATH "/tmp"
|
||||
#define TMP_C_SRC_FILE_PATH TMP_FILE_PATH "/.code.c"
|
||||
#define TMP_C_EXE_FILE_PATH TMP_FILE_PATH "/.expr"
|
||||
#define TMP_COMPILE_CMD "gcc -o " TMP_C_EXE_FILE_PATH " " TMP_C_SRC_FILE_PATH
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
// this should be enough
|
||||
static char buf[65536] = {};
|
||||
static char code_buf[65536 + 128] = {}; // a little larger than `buf`
|
||||
static char *code_format =
|
||||
"#include <stdio.h>\n"
|
||||
"int main() { "
|
||||
" unsigned result = %s; "
|
||||
" printf(\"%%u\", result); "
|
||||
" return 0; "
|
||||
"}";
|
||||
|
||||
static void gen_rand_expr() {
|
||||
buf[0] = '\0';
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int seed = time(0);
|
||||
srand(seed);
|
||||
int loop = 1;
|
||||
if (argc > 1) {
|
||||
sscanf(argv[1], "%d", &loop);
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < loop; i ++) {
|
||||
gen_rand_expr();
|
||||
|
||||
sprintf(code_buf, code_format, buf);
|
||||
|
||||
FILE *fp = fopen(TMP_C_SRC_FILE_PATH, "w");
|
||||
assert(fp != NULL);
|
||||
fputs(code_buf, fp);
|
||||
fclose(fp);
|
||||
|
||||
int ret = system(TMP_COMPILE_CMD);
|
||||
if (ret != 0) continue;
|
||||
|
||||
fp = popen("." TMP_C_EXE_FILE_PATH, "r");
|
||||
assert(fp != NULL);
|
||||
|
||||
int result;
|
||||
ret = fscanf(fp, "%d", &result);
|
||||
pclose(fp);
|
||||
|
||||
printf("%u %s\n", result, buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
117
main.c
Normal file
117
main.c
Normal file
@ -0,0 +1,117 @@
|
||||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
// Modified by: Zhiyi Zhang in 2024.08
|
||||
|
||||
#include "common.h"
|
||||
|
||||
void init_regex(void);
|
||||
uint32_t expr(char *e, bool *success);
|
||||
|
||||
static int cmd_q(char *args) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int cmd_help(char *args);
|
||||
|
||||
static int cmd_p(char *args) {
|
||||
bool success = true;
|
||||
uint32_t res = expr(args, &success);
|
||||
if (success) {
|
||||
printf("$res = % " PRIdLEAST32 "\n", res);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
const char *description;
|
||||
int (*handler) (char *);
|
||||
} cmd_table [] = {
|
||||
{ "help", "Display information about all supported commands", cmd_help },
|
||||
{ "p", "p EXPR: To evaluate an expression EXPR and output the result", cmd_p },
|
||||
{ "q", "Exit NEMU", cmd_q },
|
||||
|
||||
/* TODO: Add more commands */
|
||||
|
||||
};
|
||||
|
||||
#define NR_CMD ARRLEN(cmd_table)
|
||||
|
||||
static void print_help() {
|
||||
for (int i = 0; i < NR_CMD; i ++) {
|
||||
printf("%s - %s\n", cmd_table[i].name, cmd_table[i].description);
|
||||
}
|
||||
}
|
||||
|
||||
static int cmd_help(char *args) {
|
||||
/* extract the first argument */
|
||||
char *arg = strtok(NULL, " ");
|
||||
int i;
|
||||
|
||||
if (arg == NULL) {
|
||||
/* no argument given */
|
||||
print_help();
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < NR_CMD; i ++) {
|
||||
if (strcmp(arg, cmd_table[i].name) == 0) {
|
||||
printf("%s - %s\n", cmd_table[i].name, cmd_table[i].description);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
printf("Unknown command '%s'\n", arg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
static char str[1024] = { 0 };
|
||||
init_regex();
|
||||
print_help();
|
||||
bool running = true;
|
||||
|
||||
while (running) {
|
||||
if (!fgets(str, 1024, stdin)) {
|
||||
continue;
|
||||
}
|
||||
str[strlen(str) - 1] = '\0';
|
||||
char *str_end = str + strlen(str);
|
||||
|
||||
/* extract the first token as the command */
|
||||
char *cmd = strtok(str, " ");
|
||||
if (cmd == NULL) { continue; }
|
||||
|
||||
/* treat the remaining string as the arguments,
|
||||
* which may need further parsing
|
||||
*/
|
||||
char *args = cmd + strlen(cmd) + 1;
|
||||
if (args >= str_end) {
|
||||
args = NULL;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < NR_CMD; i ++) {
|
||||
if (strcmp(cmd, cmd_table[i].name) == 0) {
|
||||
if (cmd_table[i].handler(args) < 0) { return -1; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == NR_CMD) { printf("Unknown command '%s'\n", cmd); }
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user