refactor: 重构前端代码并添加日志功能
- 重命名和重构了多个文件,包括 lexer、parser 和 AST 相关代码 - 添加了日志功能,使用 LOG_* 宏替代原有的 error 和 warn 函数 - 优化了错误处理和内存分配方式 - 调整了代码结构,提高了模块化和可读性
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
# 编译器设置
|
||||
CC = gcc
|
||||
AR = ar
|
||||
CFLAGS = -g -Wall
|
||||
CFLAGS = -g -Wall -I../..
|
||||
|
||||
# 源文件路径
|
||||
LEXER_DIR = ./lexer
|
||||
@ -15,7 +15,7 @@ SRCS = \
|
||||
$(LEXER_DIR)/lexer.c \
|
||||
$(LEXER_DIR)/token.c \
|
||||
$(PARSER_DIR)/parser.c \
|
||||
$(AST_DIR)/ast.c \
|
||||
$(PARSER_DIR)/ast.c \
|
||||
$(AST_DIR)/block.c \
|
||||
$(AST_DIR)/decl.c \
|
||||
$(AST_DIR)/expr.c \
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include "lexer/lexer.h"
|
||||
#include "parser/symtab/symtab.h"
|
||||
#include <lib/core.h>
|
||||
#include "frontend.h"
|
||||
#include "parser/symtab/symtab.h"
|
||||
|
||||
ast_node_t* frontend(const char* file, void* stream, sread_fn sread) {
|
||||
init_lib_core();
|
||||
|
||||
struct ASTNode* frontend(const char* file, void* stream, sread_fn sread) {
|
||||
lexer_t lexer;
|
||||
init_lexer(&lexer, file, stream, sread);
|
||||
|
||||
|
@ -1,27 +1,9 @@
|
||||
#ifndef __FRONTEND_H__
|
||||
#define __FRONTEND_H__
|
||||
#ifndef __SMCC_FRONTEND_H__
|
||||
#define __SMCC_FRONTEND_H__
|
||||
|
||||
#ifndef error
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#define STD_LIBRARY
|
||||
#define error(...) do { fprintf(stderr, __VA_ARGS__); assert(0); } while (0)
|
||||
#endif
|
||||
#ifndef warn
|
||||
#include <stdio.h>
|
||||
#define STD_LIBRARY
|
||||
#define warn(...) do { fprintf(stdout, __VA_ARGS__); } while (0)
|
||||
#endif
|
||||
|
||||
#define xmalloc(size) malloc(size)
|
||||
|
||||
#ifndef FRONTEND_IMPLEMENTATION
|
||||
#include "lexer/lexer.h"
|
||||
#include "parser/parser.h"
|
||||
#include "parser/ast/ast.h"
|
||||
|
||||
typedef int (*sread_fn)(void *dst_buf, int dst_size, int elem_size, int count, void *stream);
|
||||
struct ASTNode* frontend(const char* file, void* stream, sread_fn sread);
|
||||
#endif
|
||||
ast_node_t* frontend(const char* file, void* stream, sread_fn sread);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -26,8 +26,8 @@ the distribution and installation instructions.
|
||||
Chris Fraser / cwf@aya.yale.edu
|
||||
David Hanson / drh@drhanson.net
|
||||
*/
|
||||
#define FRONTEND_IMPLEMENTATION
|
||||
#include "../frontend.h"
|
||||
#include <lib/core.h>
|
||||
#include "lexer_log.h"
|
||||
#include "token.h"
|
||||
#include "lexer.h"
|
||||
|
||||
@ -74,8 +74,9 @@ static inline int keyword_cmp(const char* name, int len) {
|
||||
return -1; // Not a keyword.
|
||||
}
|
||||
|
||||
void init_lexer(lexer_t* lexer, const char* file_name, void* stream, lexer_sread_fn sread)
|
||||
{
|
||||
void init_lexer(lexer_t* lexer, const char* file_name, void* stream, lexer_sread_fn sread) {
|
||||
init_lib_core();
|
||||
|
||||
lexer->cur_ptr = lexer->end_ptr = (unsigned char*)&(lexer->buffer);
|
||||
lexer->index = 1;
|
||||
lexer->line = 1;
|
||||
@ -96,10 +97,10 @@ static void flush_buffer(lexer_t* lexer) {
|
||||
lexer->cur_ptr = (unsigned char*)lexer->buffer;
|
||||
|
||||
int read_size = LEXER_BUFFER_SIZE - num;
|
||||
// TODO size_t to int maybe lose precision
|
||||
// TODO rt_size_t to int maybe lose precision
|
||||
int got_size = lexer->sread(lexer->buffer + num, read_size, 1, read_size, lexer->stream);
|
||||
if (got_size < 0) {
|
||||
error("lexer read error");
|
||||
LEX_ERROR("lexer read error");
|
||||
} else if (got_size < read_size) {
|
||||
lexer->end_ptr += got_size;
|
||||
lexer->end_ptr[0] = '\0'; // EOF
|
||||
@ -107,7 +108,7 @@ static void flush_buffer(lexer_t* lexer) {
|
||||
} else if (got_size == read_size) {
|
||||
lexer->end_ptr += got_size;
|
||||
} else {
|
||||
error("lexer read error imposible got_size > read_size maybe overflow?");
|
||||
LEX_ERROR("lexer read error imposible got_size > read_size maybe overflow?");
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,8 +154,10 @@ static char got_slash(unsigned char* peek) {
|
||||
case 'r': return '\r';
|
||||
case 't': return '\t';
|
||||
case 'v': return '\v';
|
||||
default: error("Unknown escape character");
|
||||
default: break;
|
||||
}
|
||||
LEX_ERROR("Unknown escape character");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void parse_char_literal(lexer_t* lexer, tok_t* token) {
|
||||
@ -168,7 +171,7 @@ static void parse_char_literal(lexer_t* lexer, tok_t* token) {
|
||||
val = *peek++;
|
||||
}
|
||||
|
||||
if (*peek++ != '\'') error("Unclosed character literal");
|
||||
if (*peek++ != '\'') LEX_ERROR("Unclosed character literal");
|
||||
token->val.ch = val;
|
||||
lexer->cur_ptr = peek;
|
||||
token->val.have = 1;
|
||||
@ -178,7 +181,7 @@ static void parse_char_literal(lexer_t* lexer, tok_t* token) {
|
||||
static void parse_string_literal(lexer_t* lexer, tok_t* token) {
|
||||
unsigned char* peek = lexer->cur_ptr + 1;
|
||||
// TODO string literal size check
|
||||
char* dest = token->val.str = xmalloc(LEXER_MAX_TOKEN_SIZE + 1);
|
||||
char* dest = token->val.str = rt._malloc(LEXER_MAX_TOKEN_SIZE + 1);
|
||||
int len = 0;
|
||||
|
||||
while (*peek != '"') {
|
||||
@ -189,7 +192,7 @@ static void parse_string_literal(lexer_t* lexer, tok_t* token) {
|
||||
*peek = got_slash(peek);
|
||||
}
|
||||
|
||||
if (len >= LEXER_MAX_TOKEN_SIZE) error("String too long");
|
||||
if (len >= LEXER_MAX_TOKEN_SIZE) LEX_ERROR("String too long");
|
||||
dest[len++] = *peek++;
|
||||
}
|
||||
dest[len] = '\0';
|
||||
@ -431,7 +434,7 @@ void get_token(lexer_t* lexer, tok_t* token) {
|
||||
lexer->line++;
|
||||
tok = TOKEN_FLUSH; break;
|
||||
case '#':
|
||||
warn("TODO: #define\n");
|
||||
LEX_WARN("Marroc does not support in lexer rather in preprocessor, it will be ignored");
|
||||
goto_newline(lexer);
|
||||
tok = TOKEN_FLUSH;
|
||||
goto END;
|
||||
@ -458,14 +461,14 @@ void get_token(lexer_t* lexer, tok_t* token) {
|
||||
case '_':
|
||||
// TOKEN_IDENT
|
||||
if ((*peek == 'L' && *peek == '\'') || (*peek == 'L' && *peek == '"')) {
|
||||
error("unsupport wide-character char literal by `L` format");
|
||||
LEX_ERROR("unsupport wide-character char literal by `L` format");
|
||||
}
|
||||
while (1) {
|
||||
if (peek == lexer->end_ptr) {
|
||||
error("unsupport outof 64 length identifier");
|
||||
LEX_ERROR("unsupport outof 64 length identifier");
|
||||
}
|
||||
if ((*peek >= 'a' && *peek <= 'z') || (*peek >= 'A' && *peek <= 'Z') ||
|
||||
(*peek == '_') || (*peek >= '0' && *peek <= '9')) {
|
||||
(*peek == '_') || (*peek >= '0' && *peek <= '9')) {
|
||||
peek++;
|
||||
continue;
|
||||
}
|
||||
@ -475,7 +478,7 @@ void get_token(lexer_t* lexer, tok_t* token) {
|
||||
int res = keyword_cmp((const char*)lexer->cur_ptr, peek - (lexer->cur_ptr));
|
||||
if (res == -1) {
|
||||
int strlen = peek - lexer->cur_ptr;
|
||||
unsigned char* str = xmalloc(strlen + 1);
|
||||
unsigned char* str = rt._malloc(strlen + 1);
|
||||
constant.have = 1;
|
||||
constant.str = (char*)str;
|
||||
for (int i = 0; i < strlen; i++) {
|
||||
@ -489,7 +492,7 @@ void get_token(lexer_t* lexer, tok_t* token) {
|
||||
tok = keywords[res].tok; break;
|
||||
}
|
||||
default:
|
||||
error("unsupport char in sourse code `%c`", *(lexer->cur_ptr));
|
||||
LEX_ERROR("unsupport char in sourse code `%c`", *(lexer->cur_ptr));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -497,6 +500,7 @@ void get_token(lexer_t* lexer, tok_t* token) {
|
||||
END:
|
||||
token->val = constant;
|
||||
token->type = tok;
|
||||
LEX_DEBUG("get token `%s` (ch: %c, int: %d)", get_tok_name(token->type), token->val.ch, token->val.i);
|
||||
}
|
||||
|
||||
// get_token maybe got invalid (with parser)
|
||||
@ -507,4 +511,3 @@ void get_valid_token(lexer_t* lexer, tok_t* token) {
|
||||
type = token->type;
|
||||
} while (type == TOKEN_FLUSH || type == TOKEN_LINE_COMMENT || type == TOKEN_BLOCK_COMMENT);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef __LEXER_H__
|
||||
#define __LEXER_H__
|
||||
#ifndef __SMCC_LEXER_H__
|
||||
#define __SMCC_LEXER_H__
|
||||
|
||||
#include <lib/core.h>
|
||||
#include "token.h"
|
||||
#ifndef LEXER_MAX_TOKEN_SIZE
|
||||
#define LEXER_MAX_TOKEN_SIZE 63
|
||||
|
13
ccompiler/frontend/lexer/lexer_log.h
Normal file
13
ccompiler/frontend/lexer/lexer_log.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef __SMCC_LEXER_LOG_H__
|
||||
#define __SMCC_LEXER_LOG_H__
|
||||
|
||||
#include <lib/rt/rt.h>
|
||||
|
||||
#define LEX_NOTSET( fmt, ...) LOG_NOTSET("LEXER: " fmt, ##__VA_ARGS__)
|
||||
#define LEX_DEBUG( fmt, ...) LOG_DEBUG("LEXER: " fmt, ##__VA_ARGS__)
|
||||
#define LEX_INFO( fmt, ...) LOG_INFO("LEXER: " fmt, ##__VA_ARGS__)
|
||||
#define LEX_WARN( fmt, ...) LOG_WARN("LEXER: " fmt, ##__VA_ARGS__)
|
||||
#define LEX_ERROR( fmt, ...) LOG_ERROR("LEXER: " fmt, ##__VA_ARGS__)
|
||||
#define LEX_FATAL( fmt, ...) LOG_FATAL("LEXER: " fmt, ##__VA_ARGS__)
|
||||
|
||||
#endif // __SMCC_LEXER_LOG_H__
|
@ -1,6 +1,7 @@
|
||||
CC = gcc
|
||||
CFLAGS = -g -Wall
|
||||
CFLAGS = -g -Wall -I../../../..
|
||||
SRC = ../lexer.c ../token.c
|
||||
LIB = -L../../../../lib -lcore
|
||||
|
||||
all = test_all
|
||||
|
||||
@ -8,10 +9,10 @@ test_all: test
|
||||
./test
|
||||
|
||||
run:
|
||||
$(CC) $(CFLAGS) $(SRC) run.c -o run
|
||||
$(CC) $(CFLAGS) $(SRC) run.c $(LIB) -o run
|
||||
|
||||
test:
|
||||
$(CC) $(CFLAGS) $(SRC) -o test test.c
|
||||
$(CC) $(CFLAGS) $(SRC) $(LIB) -o test test.c
|
||||
|
||||
clean:
|
||||
rm -f test run
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "../lexer.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
// gcc -g ../lexer.c ../token.c test_lexer.c -o test_lexer
|
||||
/*
|
||||
tok_tConstant {
|
||||
@ -18,9 +19,14 @@ tok_tConstant {
|
||||
int g_num;
|
||||
int g_num_arr[3];
|
||||
int main(int argc, char* argv[]) {
|
||||
int num = 0;
|
||||
// int num = 0;
|
||||
// You Must Be Call
|
||||
init_lib_core();
|
||||
if (argc == 3 && strcmp(argv[2], "-nodebug") == 0) {
|
||||
log_set_level(NULL, LOG_LEVEL_ALL & ~LOG_LEVEL_DEBUG);
|
||||
}
|
||||
|
||||
const char* file_name = "test_lexer.c";
|
||||
const char* file_name = "run.c";
|
||||
if (argc == 2) {
|
||||
file_name = argv[1];
|
||||
}
|
||||
@ -32,7 +38,7 @@ int main(int argc, char* argv[]) {
|
||||
printf("open file success\n");
|
||||
|
||||
lexer_t lexer;
|
||||
init_lexer(&lexer, "test_lexter.c", fp, (lexer_sread_fn)fread_s);
|
||||
init_lexer(&lexer, file_name, fp, (lexer_sread_fn)fread_s);
|
||||
tok_t tok;
|
||||
|
||||
while (1) {
|
||||
@ -40,7 +46,7 @@ int main(int argc, char* argv[]) {
|
||||
if (tok.type == TOKEN_EOF) {
|
||||
break;
|
||||
}
|
||||
printf("line: %d, column: %d, type: %3d, typename: %s\n",
|
||||
lexer.line, lexer.index, tok.type, get_tok_name(tok.type));
|
||||
// printf("line: %d, column: %d, type: %3d, typename: %s\n",
|
||||
// lexer.line, lexer.index, tok.type, get_tok_name(tok.type));
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
#define FRONTEND_IMPLEMENTATION
|
||||
#include "../frontend.h"
|
||||
#include <lib/core.h>
|
||||
#include "lexer_log.h"
|
||||
#include "token.h"
|
||||
|
||||
#define ROUND_IDX(idx) ((idx) % tokbuf->cap)
|
||||
|
||||
tok_t* pop_tok(tok_buf_t* tokbuf) {
|
||||
tok_t* pop_tok(tok_stream_t* tokbuf) {
|
||||
if (tokbuf->size == 0) {
|
||||
error("no token to pop");
|
||||
LEX_ERROR("no token to pop");
|
||||
return NULL;
|
||||
}
|
||||
int idx = tokbuf->cur;
|
||||
@ -15,11 +15,11 @@ tok_t* pop_tok(tok_buf_t* tokbuf) {
|
||||
return tokbuf->buf + idx;
|
||||
}
|
||||
|
||||
void flush_peek_tok(tok_buf_t* tokbuf) {
|
||||
void flush_peek_tok(tok_stream_t* tokbuf) {
|
||||
tokbuf->peek = tokbuf->cur;
|
||||
}
|
||||
|
||||
void init_tokbuf(tok_buf_t *tokbuf, void *stream, get_tokbuf_func gettok) {
|
||||
void init_tokbuf(tok_stream_t *tokbuf, void *stream, tok_stream_get_func gettok) {
|
||||
tokbuf->cur = 0;
|
||||
tokbuf->end = 0;
|
||||
tokbuf->peek = 0;
|
||||
@ -30,18 +30,19 @@ void init_tokbuf(tok_buf_t *tokbuf, void *stream, get_tokbuf_func gettok) {
|
||||
tokbuf->cap = 0;
|
||||
}
|
||||
|
||||
tok_t *peek_tok(tok_buf_t *tokbuf) {
|
||||
tok_t *peek_tok(tok_stream_t *tokbuf) {
|
||||
Assert(tokbuf->size <= tokbuf->cap);
|
||||
int idx = tokbuf->peek;
|
||||
tokbuf->peek = ROUND_IDX(idx + 1);
|
||||
if (tokbuf->size >= tokbuf->cap) {
|
||||
error("peek too deep, outof array size");
|
||||
}
|
||||
|
||||
if (idx == tokbuf->end) {
|
||||
if (tokbuf->size == tokbuf->cap) {
|
||||
error("peek_tok buffer overflow");
|
||||
LEX_ERROR("peek_tok buffer overflow");
|
||||
return NULL;
|
||||
}
|
||||
if (tokbuf->gettok == NULL) {
|
||||
error("peek_tok can not got tok");
|
||||
LEX_ERROR("peek_tok can not got tok");
|
||||
return NULL;
|
||||
}
|
||||
tokbuf->gettok(tokbuf->stream, &(tokbuf->buf[idx]));
|
||||
tokbuf->size++;
|
||||
@ -51,15 +52,16 @@ tok_t *peek_tok(tok_buf_t *tokbuf) {
|
||||
return &(tokbuf->buf[idx]);
|
||||
}
|
||||
|
||||
tok_type_t peek_tok_type(tok_buf_t* tokbuf) {
|
||||
tok_type_t peek_tok_type(tok_stream_t* tokbuf) {
|
||||
return peek_tok(tokbuf)->type;
|
||||
}
|
||||
|
||||
int expect_pop_tok(tok_buf_t* tokbuf, tok_type_t type) {
|
||||
int expect_pop_tok(tok_stream_t* tokbuf, tok_type_t type) {
|
||||
flush_peek_tok(tokbuf);
|
||||
tok_t* tok = peek_tok(tokbuf);
|
||||
if (tok->type != type) {
|
||||
error("expected tok: %s, got %s", get_tok_name(type), get_tok_name(tok->type));
|
||||
LEX_ERROR("expected tok `%s` but got `%s`", get_tok_name(type), get_tok_name(tok->type));
|
||||
return 0;
|
||||
} else {
|
||||
pop_tok(tokbuf);
|
||||
}
|
||||
|
@ -51,10 +51,10 @@ enum CSTD_KEYWORD {
|
||||
X(flush , TOKEN_FLUSH) \
|
||||
X("==" , TOKEN_EQ) \
|
||||
X("=" , TOKEN_ASSIGN) \
|
||||
X("++" , TOKEN_ADD_ADD) \
|
||||
X("++" , TOKEN_ADD_ADD) \
|
||||
X("+=" , TOKEN_ASSIGN_ADD) \
|
||||
X("+" , TOKEN_ADD) \
|
||||
X("--" , TOKEN_SUB_SUB) \
|
||||
X("--" , TOKEN_SUB_SUB) \
|
||||
X("-=" , TOKEN_ASSIGN_SUB) \
|
||||
X("->" , TOKEN_DEREF) \
|
||||
X("-" , TOKEN_SUB) \
|
||||
@ -134,7 +134,7 @@ typedef struct tok {
|
||||
tok_val_t val;
|
||||
} tok_t;
|
||||
|
||||
typedef struct tok_buf {
|
||||
typedef struct tok_stream {
|
||||
int cur;
|
||||
int end;
|
||||
int peek;
|
||||
@ -143,15 +143,15 @@ typedef struct tok_buf {
|
||||
tok_t* buf;
|
||||
void* stream;
|
||||
void (*gettok)(void* stream, tok_t* token);
|
||||
} tok_buf_t;
|
||||
} tok_stream_t;
|
||||
|
||||
typedef void(*get_tokbuf_func)(void* stream, tok_t* token);
|
||||
void init_tokbuf(tok_buf_t* tokbuf, void* stream, get_tokbuf_func gettok);
|
||||
tok_t* peek_tok(tok_buf_t* tokbuf);
|
||||
tok_t* pop_tok(tok_buf_t* tokbuf);
|
||||
void flush_peek_tok(tok_buf_t* tokbuf);
|
||||
tok_type_t peek_tok_type(tok_buf_t* tokbuf);
|
||||
int expect_pop_tok(tok_buf_t* tokbuf, tok_type_t type);
|
||||
typedef void(*tok_stream_get_func)(void* stream, tok_t* token);
|
||||
void init_tokbuf(tok_stream_t* tokbuf, void* stream, tok_stream_get_func gettok);
|
||||
tok_t* peek_tok(tok_stream_t* tokbuf);
|
||||
tok_t* pop_tok(tok_stream_t* tokbuf);
|
||||
void flush_peek_tok(tok_stream_t* tokbuf);
|
||||
tok_type_t peek_tok_type(tok_stream_t* tokbuf);
|
||||
int expect_pop_tok(tok_stream_t* tokbuf, tok_type_t type);
|
||||
const char* get_tok_name(tok_type_t type);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
0
ccompiler/frontend/parser/ast-gdb.py
Normal file
0
ccompiler/frontend/parser/ast-gdb.py
Normal file
@ -1,12 +1,11 @@
|
||||
#include "ast.h"
|
||||
#include "../parser.h"
|
||||
struct ASTNode* new_ast_node(void) {
|
||||
struct ASTNode* node = xmalloc(sizeof(struct ASTNode));
|
||||
ast_node_t* new_ast_node(void) {
|
||||
ast_node_t* node = rt._malloc(sizeof(ast_node_t));
|
||||
init_ast_node(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
void init_ast_node(struct ASTNode* node) {
|
||||
void init_ast_node(ast_node_t* node) {
|
||||
node->type = NT_INIT;
|
||||
|
||||
for (int i = 0; i < sizeof(node->children) / sizeof(node->children[0]); i++) {
|
||||
@ -14,7 +13,7 @@ void init_ast_node(struct ASTNode* node) {
|
||||
}
|
||||
}
|
||||
|
||||
// struct ASTNode* find_ast_node(struct ASTNode* node, ast_type_t type) {
|
||||
// ast_node_t* find_ast_node(ast_node_t* node, ast_type_t type) {
|
||||
|
||||
// }
|
||||
|
||||
@ -25,7 +24,7 @@ static void pnt_depth(int depth) {
|
||||
}
|
||||
}
|
||||
|
||||
// void pnt_ast(struct ASTNode* node, int depth) {
|
||||
// void pnt_ast(ast_node_t* node, int depth) {
|
||||
// if (!node) return;
|
||||
// pnt_depth(depth);
|
||||
// switch (node->type) {
|
@ -1,10 +1,9 @@
|
||||
#ifndef __AST_H__
|
||||
#define __AST_H__
|
||||
|
||||
#include "../../frontend.h"
|
||||
#include "../../lexer/lexer.h"
|
||||
#include "../../../../libcore/vector.h"
|
||||
#include "../type.h"
|
||||
#include <lib/utils/ds/vector.h>
|
||||
#include "../lexer/lexer.h"
|
||||
#include "type.h"
|
||||
|
||||
typedef enum {
|
||||
NT_INIT,
|
||||
@ -78,98 +77,98 @@ typedef enum {
|
||||
NT_TERM_TYPE,
|
||||
} ast_type_t;
|
||||
|
||||
typedef struct ASTNode {
|
||||
typedef struct ast_node {
|
||||
ast_type_t type;
|
||||
|
||||
union {
|
||||
void *children[6];
|
||||
struct {
|
||||
vector_header(children, struct ASTNode*);
|
||||
vector_header(children, struct ast_node *);
|
||||
} root;
|
||||
struct {
|
||||
vector_header(children, struct ASTNode*);
|
||||
vector_header(children, struct ast_node *);
|
||||
} block;
|
||||
struct {
|
||||
struct ASTNode* decl_node;
|
||||
struct ast_node * decl_node;
|
||||
tok_t tok;
|
||||
} syms;
|
||||
struct {
|
||||
vector_header(params, struct ASTNode*);
|
||||
vector_header(params, struct ast_node *);
|
||||
} params;
|
||||
struct {
|
||||
struct ASTNode* name;
|
||||
struct ASTNode* params;
|
||||
struct ASTNode* func_decl;
|
||||
struct ast_node * name;
|
||||
struct ast_node * params;
|
||||
struct ast_node * func_decl;
|
||||
} call;
|
||||
struct {
|
||||
struct ASTNode *type;
|
||||
struct ASTNode *name;
|
||||
struct ASTNode *expr_stmt; // optional
|
||||
struct ast_node *type;
|
||||
struct ast_node *name;
|
||||
struct ast_node *expr_stmt; // optional
|
||||
void* data;
|
||||
} decl_val;
|
||||
struct {
|
||||
struct ASTNode *ret;
|
||||
struct ASTNode *name;
|
||||
struct ASTNode *params; // array of params
|
||||
struct ASTNode *def;
|
||||
struct ast_node *ret;
|
||||
struct ast_node *name;
|
||||
struct ast_node *params; // array of params
|
||||
struct ast_node *def;
|
||||
} decl_func;
|
||||
struct {
|
||||
struct ASTNode *decl;
|
||||
struct ASTNode *body; // optional
|
||||
struct ast_node *decl;
|
||||
struct ast_node *body; // optional
|
||||
void* data;
|
||||
} func;
|
||||
struct {
|
||||
struct ASTNode *left;
|
||||
struct ASTNode *right;
|
||||
struct ASTNode *optional; // optional
|
||||
struct ast_node *left;
|
||||
struct ast_node *right;
|
||||
struct ast_node *optional; // optional
|
||||
} expr;
|
||||
struct {
|
||||
struct ASTNode *cond;
|
||||
struct ASTNode *if_stmt;
|
||||
struct ASTNode *else_stmt; // optional
|
||||
struct ast_node *cond;
|
||||
struct ast_node *if_stmt;
|
||||
struct ast_node *else_stmt; // optional
|
||||
} if_stmt;
|
||||
struct {
|
||||
struct ASTNode *cond;
|
||||
struct ASTNode *body;
|
||||
struct ast_node *cond;
|
||||
struct ast_node *body;
|
||||
} switch_stmt;
|
||||
struct {
|
||||
struct ASTNode *cond;
|
||||
struct ASTNode *body;
|
||||
struct ast_node *cond;
|
||||
struct ast_node *body;
|
||||
} while_stmt;
|
||||
struct {
|
||||
struct ASTNode *body;
|
||||
struct ASTNode *cond;
|
||||
struct ast_node *body;
|
||||
struct ast_node *cond;
|
||||
} do_while_stmt;
|
||||
struct {
|
||||
struct ASTNode *init;
|
||||
struct ASTNode *cond; // optional
|
||||
struct ASTNode *iter; // optional
|
||||
struct ASTNode *body;
|
||||
struct ast_node *init;
|
||||
struct ast_node *cond; // optional
|
||||
struct ast_node *iter; // optional
|
||||
struct ast_node *body;
|
||||
} for_stmt;
|
||||
struct {
|
||||
struct ASTNode *expr_stmt; // optional
|
||||
struct ast_node *expr_stmt; // optional
|
||||
} return_stmt;
|
||||
struct {
|
||||
struct ASTNode *label;
|
||||
struct ast_node *label;
|
||||
} goto_stmt;
|
||||
struct {
|
||||
struct ASTNode *label;
|
||||
struct ast_node *label;
|
||||
} label_stmt;
|
||||
struct {
|
||||
struct ASTNode *block;
|
||||
struct ast_node *block;
|
||||
} block_stmt;
|
||||
struct {
|
||||
struct ASTNode *expr_stmt;
|
||||
struct ast_node *expr_stmt;
|
||||
} expr_stmt;
|
||||
};
|
||||
} ast_node_t;
|
||||
|
||||
struct ASTNode* new_ast_node(void);
|
||||
void init_ast_node(struct ASTNode* node);
|
||||
void pnt_ast(struct ASTNode* node, int depth);
|
||||
ast_node_t* new_ast_node(void);
|
||||
void init_ast_node(ast_node_t* node);
|
||||
void pnt_ast(ast_node_t* node, int depth);
|
||||
|
||||
typedef struct parser parser_t;
|
||||
typedef struct ASTNode* (*parse_func_t) (parser_t*);
|
||||
typedef ast_node_t* (*parse_func_t) (parser_t*);
|
||||
|
||||
void parse_prog(parser_t* parser);
|
||||
ast_node_t* parse_decl(parser_t* parser);
|
||||
@ -182,8 +181,8 @@ ast_node_t* parse_expr(parser_t* parser);
|
||||
ast_node_t* parse_type(parser_t* parser);
|
||||
|
||||
ast_node_t* new_ast_ident_node(tok_t* tok);
|
||||
ast_node_t* expect_pop_ident(tok_buf_t* tokbuf);
|
||||
ast_node_t* expect_pop_ident(tok_stream_t* tokbuf);
|
||||
|
||||
int peek_decl(tok_buf_t* tokbuf);
|
||||
int peek_decl(tok_stream_t* tokbuf);
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
|
||||
#include "ast.h"
|
||||
#include "../ast.h"
|
||||
#include "../parser.h"
|
||||
#include "../symtab/symtab.h"
|
||||
|
||||
@ -17,7 +17,7 @@ ast_node_t* new_ast_node_block() {
|
||||
|
||||
ast_node_t* parse_block(parser_t* parser) {
|
||||
symtab_enter_scope(parser->symtab);
|
||||
tok_buf_t *tokbuf = &parser->tokbuf;
|
||||
tok_stream_t *tokbuf = &parser->tokbuf;
|
||||
flush_peek_tok(tokbuf);
|
||||
tok_type_t ttype;
|
||||
ast_node_t* node = new_ast_node_block();
|
||||
|
@ -1,19 +1,19 @@
|
||||
#include "../ast.h"
|
||||
#include "../parser.h"
|
||||
#include "ast.h"
|
||||
#include "../symtab/symtab.h"
|
||||
|
||||
/**
|
||||
* 0 false
|
||||
* 1 true
|
||||
*/
|
||||
int peek_decl(tok_buf_t* tokbuf) {
|
||||
int peek_decl(tok_stream_t* tokbuf) {
|
||||
flush_peek_tok(tokbuf);
|
||||
switch (peek_tok_type(tokbuf)) {
|
||||
case TOKEN_STATIC:
|
||||
case TOKEN_EXTERN:
|
||||
case TOKEN_REGISTER:
|
||||
case TOKEN_TYPEDEF:
|
||||
error("not impliment");
|
||||
LOG_ERROR("not impliment");
|
||||
break;
|
||||
default:
|
||||
flush_peek_tok(tokbuf);
|
||||
@ -36,7 +36,7 @@ int peek_decl(tok_buf_t* tokbuf) {
|
||||
}
|
||||
|
||||
ast_node_t* parse_decl_val(parser_t* parser) {
|
||||
tok_buf_t* tokbuf = &parser->tokbuf;
|
||||
tok_stream_t* tokbuf = &parser->tokbuf;
|
||||
tok_type_t ttype;
|
||||
flush_peek_tok(tokbuf);
|
||||
|
||||
@ -55,28 +55,28 @@ ast_node_t* parse_decl_val(parser_t* parser) {
|
||||
if (ttype == TOKEN_ASSIGN) {
|
||||
node->decl_val.expr_stmt = parse_stmt(parser);
|
||||
if (node->decl_val.expr_stmt->type != NT_STMT_EXPR) {
|
||||
error("parser_decl_val want stmt_expr");
|
||||
LOG_ERROR("parser_decl_val want stmt_expr");
|
||||
}
|
||||
} else if (ttype == TOKEN_SEMICOLON) {
|
||||
pop_tok(tokbuf);
|
||||
expect_pop_tok(tokbuf, TOKEN_SEMICOLON);
|
||||
} else {
|
||||
error("parser_decl_val syntax error");
|
||||
LOG_ERROR("parser_decl_val syntax error");
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
ast_node_t* parse_decl(parser_t* parser) {
|
||||
tok_buf_t* tokbuf = &parser->tokbuf;
|
||||
tok_stream_t* tokbuf = &parser->tokbuf;
|
||||
flush_peek_tok(tokbuf);
|
||||
tok_type_t ttype;
|
||||
ast_node_t* node;
|
||||
|
||||
if (peek_decl(tokbuf) == 0) {
|
||||
error("syntax error expect decl_val TYPE");
|
||||
LOG_ERROR("syntax error expect decl_val TYPE");
|
||||
}
|
||||
if (peek_tok_type(tokbuf) != TOKEN_IDENT) {
|
||||
error("syntax error expect decl_val IDENT");
|
||||
LOG_ERROR("syntax error expect decl_val IDENT");
|
||||
}
|
||||
|
||||
ttype = peek_tok_type(tokbuf);
|
||||
@ -89,7 +89,7 @@ ast_node_t* parse_decl(parser_t* parser) {
|
||||
node = parse_decl_val(parser);
|
||||
break;
|
||||
default:
|
||||
error("syntax error expect decl_val ASSIGN or SEMICOLON");
|
||||
LOG_ERROR("syntax error expect decl_val ASSIGN or SEMICOLON");
|
||||
return NULL;
|
||||
}
|
||||
return node;
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "../ast.h"
|
||||
#include "../parser.h"
|
||||
#include "ast.h"
|
||||
#include "../symtab/symtab.h"
|
||||
|
||||
// Copy from `CParse`
|
||||
@ -33,7 +33,7 @@ enum ParseType {
|
||||
PREFIX_PARSER,
|
||||
};
|
||||
|
||||
static ast_node_t *parse_subexpression(tok_buf_t* tokbuf, symtab_t *symtab, enum Precedence prec);
|
||||
static ast_node_t *parse_subexpression(tok_stream_t* tokbuf, symtab_t *symtab, enum Precedence prec);
|
||||
#define NEXT(prec) parse_subexpression(tokbuf, symtab, prec)
|
||||
|
||||
static ast_node_t* gen_node2(ast_node_t* left, ast_node_t* right,
|
||||
@ -72,7 +72,7 @@ static ast_node_t* gen_node2(ast_node_t* left, ast_node_t* right,
|
||||
// }
|
||||
}
|
||||
|
||||
static ast_node_t* parse_comma(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* left) {
|
||||
static ast_node_t* parse_comma(tok_stream_t* tokbuf, symtab_t *symtab, ast_node_t* left) {
|
||||
ast_node_t* node = new_ast_node();
|
||||
node->type = NT_COMMA;
|
||||
node->expr.left = left;
|
||||
@ -80,7 +80,7 @@ static ast_node_t* parse_comma(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t*
|
||||
return node;
|
||||
}
|
||||
|
||||
static ast_node_t* parse_assign(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* left) {
|
||||
static ast_node_t* parse_assign(tok_stream_t* tokbuf, symtab_t *symtab, ast_node_t* left) {
|
||||
flush_peek_tok(tokbuf);
|
||||
tok_type_t ttype = peek_tok_type(tokbuf);
|
||||
pop_tok(tokbuf);
|
||||
@ -124,14 +124,14 @@ static ast_node_t* parse_assign(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t*
|
||||
left = gen_node2(left, NEXT(next), NT_XOR);
|
||||
break;
|
||||
default:
|
||||
error("unsupported operator");
|
||||
LOG_ERROR("unsupported operator");
|
||||
break;
|
||||
}
|
||||
node->expr.right = left;
|
||||
return node;
|
||||
}
|
||||
|
||||
static ast_node_t* parse_cmp(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* left) {
|
||||
static ast_node_t* parse_cmp(tok_stream_t* tokbuf, symtab_t *symtab, ast_node_t* left) {
|
||||
flush_peek_tok(tokbuf);
|
||||
tok_type_t ttype = peek_tok_type(tokbuf);
|
||||
pop_tok(tokbuf);
|
||||
@ -164,12 +164,12 @@ static ast_node_t* parse_cmp(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* le
|
||||
node->expr.right = NEXT(PREC_RELATIONAL);
|
||||
break;
|
||||
default:
|
||||
error("invalid operator");
|
||||
LOG_ERROR("invalid operator");
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static ast_node_t* parse_cal(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* left) {
|
||||
static ast_node_t* parse_cal(tok_stream_t* tokbuf, symtab_t *symtab, ast_node_t* left) {
|
||||
flush_peek_tok(tokbuf);
|
||||
tok_type_t ttype = peek_tok_type(tokbuf);
|
||||
pop_tok(tokbuf);
|
||||
@ -230,7 +230,7 @@ static ast_node_t* parse_cal(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* le
|
||||
return node;
|
||||
}
|
||||
|
||||
static ast_node_t* parse_call(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* ident) {
|
||||
static ast_node_t* parse_call(tok_stream_t* tokbuf, symtab_t *symtab, ast_node_t* ident) {
|
||||
ast_node_t* node = new_ast_node();
|
||||
node->type = NT_TERM_CALL;
|
||||
node->call.name = ident;
|
||||
@ -257,14 +257,14 @@ static ast_node_t* parse_call(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* i
|
||||
ast_node_t* sym = symtab_lookup_symbol(symtab, name);
|
||||
// TODO check func is match
|
||||
if (sym == NULL || sym->type != NT_DECL_FUNC) {
|
||||
error("function not decl %s", name);
|
||||
LOG_ERROR("function not decl %s", name);
|
||||
}
|
||||
node->call.name = ident;
|
||||
node->call.func_decl = sym;
|
||||
return node;
|
||||
}
|
||||
|
||||
static ast_node_t* parse_paren(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* left) {
|
||||
static ast_node_t* parse_paren(tok_stream_t* tokbuf, symtab_t *symtab, ast_node_t* left) {
|
||||
flush_peek_tok(tokbuf);
|
||||
expect_pop_tok(tokbuf, TOKEN_L_PAREN);
|
||||
left = NEXT(PREC_EXPRESSION);
|
||||
@ -273,7 +273,7 @@ static ast_node_t* parse_paren(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t*
|
||||
return left;
|
||||
}
|
||||
|
||||
typedef ast_node_t* (*parse_expr_fun_t)(tok_buf_t*, symtab_t* , ast_node_t*);
|
||||
typedef ast_node_t* (*parse_expr_fun_t)(tok_stream_t*, symtab_t* , ast_node_t*);
|
||||
static struct expr_prec_table_t {
|
||||
parse_expr_fun_t parser;
|
||||
enum Precedence prec;
|
||||
@ -322,7 +322,7 @@ static struct expr_prec_table_t {
|
||||
[TOKEN_L_PAREN] = {parse_paren, PREC_POSTFIX, INFIX_PARSER},
|
||||
};
|
||||
|
||||
static ast_node_t *parse_primary_expression(tok_buf_t* tokbuf, symtab_t *symtab) {
|
||||
static ast_node_t *parse_primary_expression(tok_stream_t* tokbuf, symtab_t *symtab) {
|
||||
flush_peek_tok(tokbuf);
|
||||
|
||||
tok_t* tok = peek_tok(tokbuf);
|
||||
@ -335,7 +335,7 @@ static ast_node_t *parse_primary_expression(tok_buf_t* tokbuf, symtab_t *symtab)
|
||||
// node->data.data_type = TYPE_INT;
|
||||
break;
|
||||
case TOKEN_FLOAT_LITERAL:
|
||||
warn("float not supported");
|
||||
LOG_WARN("float not supported");
|
||||
break;
|
||||
case TOKEN_CHAR_LITERAL:
|
||||
// node->data.data_type = TYPE_CHAR;
|
||||
@ -350,7 +350,7 @@ static ast_node_t *parse_primary_expression(tok_buf_t* tokbuf, symtab_t *symtab)
|
||||
} else {
|
||||
void *sym = symtab_lookup_symbol(symtab, tok->val.str);
|
||||
if (sym == NULL) {
|
||||
error("undefined symbol but use %s", tok->val.str);
|
||||
LOG_ERROR("undefined symbol but use %s", tok->val.str);
|
||||
}
|
||||
node->type = NT_TERM_IDENT;
|
||||
node->syms.decl_node = sym;
|
||||
@ -364,7 +364,7 @@ END:
|
||||
return node;
|
||||
}
|
||||
|
||||
static ast_node_t *parse_subexpression(tok_buf_t* tokbuf, symtab_t *symtab, enum Precedence prec) {
|
||||
static ast_node_t *parse_subexpression(tok_stream_t* tokbuf, symtab_t *symtab, enum Precedence prec) {
|
||||
tok_type_t ttype;
|
||||
struct expr_prec_table_t* work;
|
||||
ast_node_t* left;
|
||||
@ -397,7 +397,7 @@ static ast_node_t *parse_subexpression(tok_buf_t* tokbuf, symtab_t *symtab, enum
|
||||
}
|
||||
|
||||
ast_node_t* parse_expr(parser_t* parser) {
|
||||
tok_buf_t* tokbuf = &(parser->tokbuf);
|
||||
tok_stream_t* tokbuf = &(parser->tokbuf);
|
||||
symtab_t *symtab = parser->symtab;
|
||||
flush_peek_tok(tokbuf);
|
||||
tok_type_t ttype = peek_tok_type(tokbuf);
|
||||
@ -419,7 +419,7 @@ ast_node_t* parse_expr(parser_t* parser) {
|
||||
case TOKEN_IDENT:
|
||||
return NEXT(PREC_EXPRESSION);
|
||||
default:
|
||||
error("Want expr but not got %s", get_tok_name(ttype));
|
||||
LOG_ERROR("Want expr but not got %s", get_tok_name(ttype));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
#include "../ast.h"
|
||||
#include "../parser.h"
|
||||
#include "../symtab/symtab.h"
|
||||
#include "ast.h"
|
||||
|
||||
#ifndef FUNC_PARAM_CACHE_SIZE
|
||||
#define FUNC_PARAM_CACHE_SIZE 32 // 合理初始值,可覆盖99%常见情况
|
||||
#endif
|
||||
|
||||
// TODO 语义分析压入符号表
|
||||
static void parse_params(parser_t* parser, tok_buf_t* cache, ast_node_t* node) {
|
||||
static void parse_params(parser_t* parser, tok_stream_t* cache, ast_node_t* node) {
|
||||
flush_peek_tok(cache);
|
||||
tok_type_t ttype;
|
||||
ast_node_t *params = new_ast_node();
|
||||
@ -23,10 +23,10 @@ static void parse_params(parser_t* parser, tok_buf_t* cache, ast_node_t* node) {
|
||||
case TOKEN_ELLIPSIS:
|
||||
ttype = peek_tok_type(cache);
|
||||
if (ttype != TOKEN_R_PAREN) {
|
||||
error("... must be a last parameter list (expect ')')");
|
||||
LOG_ERROR("... must be a last parameter list (expect ')')");
|
||||
}
|
||||
// TODO
|
||||
error("not implement");
|
||||
LOG_ERROR("not implement");
|
||||
break;
|
||||
case TOKEN_IDENT:
|
||||
// TODO 静态数组
|
||||
@ -62,13 +62,13 @@ static void parse_params(parser_t* parser, tok_buf_t* cache, ast_node_t* node) {
|
||||
// flush_peek_tok(tokbuf);
|
||||
// continue;
|
||||
// }
|
||||
// error("function expected ')' or ','\n");
|
||||
// LOG_ERROR("function expected ')' or ','\n");
|
||||
}
|
||||
pop_tok(cache);
|
||||
}
|
||||
}
|
||||
|
||||
ast_type_t check_is_func_decl(tok_buf_t* tokbuf, tok_buf_t* cache) {
|
||||
ast_type_t check_is_func_decl(tok_stream_t* tokbuf, tok_stream_t* cache) {
|
||||
expect_pop_tok(tokbuf, TOKEN_L_PAREN);
|
||||
int depth = 1;
|
||||
|
||||
@ -76,7 +76,7 @@ ast_type_t check_is_func_decl(tok_buf_t* tokbuf, tok_buf_t* cache) {
|
||||
tok_t* tok = peek_tok(tokbuf);
|
||||
pop_tok(tokbuf);
|
||||
if (cache->size >= cache->cap - 1) {
|
||||
error("function parameter list too long");
|
||||
LOG_ERROR("function parameter list too long");
|
||||
}
|
||||
cache->buf[cache->size++] = *tok;
|
||||
switch (tok->type) {
|
||||
@ -100,7 +100,7 @@ ast_type_t check_is_func_decl(tok_buf_t* tokbuf, tok_buf_t* cache) {
|
||||
return NT_FUNC;
|
||||
break;
|
||||
default:
|
||||
error("function define or decl need '{' or ';' but you don't got");
|
||||
LOG_ERROR("function define or decl need '{' or ';' but you don't got");
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,14 +114,14 @@ static ast_node_t* new_ast_node_funcdecl(ast_node_t* ret, ast_node_t* name) {
|
||||
}
|
||||
|
||||
void parse_func(parser_t* parser) {
|
||||
tok_buf_t* tokbuf = &(parser->tokbuf);
|
||||
tok_stream_t* tokbuf = &(parser->tokbuf);
|
||||
flush_peek_tok(tokbuf);
|
||||
ast_node_t* ret_node = parse_type(parser);
|
||||
ast_node_t* name_node = expect_pop_ident(tokbuf);
|
||||
const char* func_name = name_node->syms.tok.val.str;
|
||||
ast_node_t* decl = new_ast_node_funcdecl(ret_node, name_node);
|
||||
|
||||
tok_buf_t cache;
|
||||
tok_stream_t cache;
|
||||
init_tokbuf(&cache, NULL, NULL);
|
||||
cache.cap = FUNC_PARAM_CACHE_SIZE;
|
||||
tok_t buf[FUNC_PARAM_CACHE_SIZE];
|
||||
@ -132,12 +132,12 @@ void parse_func(parser_t* parser) {
|
||||
ast_node_t* prev = symtab_add_symbol(parser->symtab, func_name, decl, 1);
|
||||
if (prev != NULL) {
|
||||
if (prev->type != NT_DECL_FUNC) {
|
||||
error("the symbol duplicate old is %d, new is func", prev->type);
|
||||
LOG_ERROR("the symbol duplicate old is %d, new is func", prev->type);
|
||||
}
|
||||
// TODO check redeclare func is match
|
||||
if (type == NT_FUNC) {
|
||||
// TODO Free decl;
|
||||
free(decl);
|
||||
rt._free(decl);
|
||||
decl = prev;
|
||||
goto FUNC;
|
||||
}
|
||||
@ -151,7 +151,7 @@ void parse_func(parser_t* parser) {
|
||||
FUNC:
|
||||
// 该data临时用于判断是否重复定义
|
||||
if (decl->decl_func.def != NULL) {
|
||||
error("redefinition of function %s", func_name);
|
||||
LOG_ERROR("redefinition of function %s", func_name);
|
||||
}
|
||||
|
||||
ast_node_t* node = new_ast_node();
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "../ast.h"
|
||||
#include "../parser.h"
|
||||
#include "ast.h"
|
||||
|
||||
#ifndef PROG_MAX_NODE_SIZE
|
||||
#define PROG_MAX_NODE_SIZE (1024 * 4)
|
||||
@ -13,7 +13,7 @@ void parse_prog(parser_t* parser) {
|
||||
* same as
|
||||
* Program := Declaration* Definition*
|
||||
*/
|
||||
tok_buf_t *tokbuf = &(parser->tokbuf);
|
||||
tok_stream_t *tokbuf = &(parser->tokbuf);
|
||||
parser->root = new_ast_node();
|
||||
ast_node_t* node;
|
||||
parser->root->type = NT_ROOT;
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "../ast.h"
|
||||
#include "../parser.h"
|
||||
#include "ast.h"
|
||||
|
||||
ast_node_t* parse_stmt(parser_t* parser) {
|
||||
tok_buf_t* tokbuf = &parser->tokbuf;
|
||||
tok_stream_t* tokbuf = &parser->tokbuf;
|
||||
flush_peek_tok(tokbuf);
|
||||
tok_type_t ttype = peek_tok_type(tokbuf);
|
||||
ast_node_t* node = new_ast_node();
|
||||
@ -66,7 +66,7 @@ ast_node_t* parse_stmt(parser_t* parser) {
|
||||
node->do_while_stmt.body = parse_stmt(parser);
|
||||
ttype = peek_tok_type(tokbuf);
|
||||
if (ttype != TOKEN_WHILE) {
|
||||
error("expected while after do");
|
||||
LOG_ERROR("expected while after do");
|
||||
}
|
||||
pop_tok(tokbuf);
|
||||
expect_pop_tok(tokbuf, TOKEN_L_PAREN);
|
||||
@ -83,7 +83,7 @@ ast_node_t* parse_stmt(parser_t* parser) {
|
||||
pop_tok(tokbuf);
|
||||
ttype = peek_tok_type(tokbuf);
|
||||
if (ttype != TOKEN_L_PAREN) {
|
||||
error("expected ( after for");
|
||||
LOG_ERROR("expected ( after for");
|
||||
}
|
||||
pop_tok(tokbuf);
|
||||
|
||||
@ -170,7 +170,7 @@ ast_node_t* parse_stmt(parser_t* parser) {
|
||||
// find symbol table
|
||||
ttype = peek_tok_type(tokbuf);
|
||||
if (ttype != TOKEN_IDENT) {
|
||||
error("expect identifier after goto");
|
||||
LOG_ERROR("expect identifier after goto");
|
||||
}
|
||||
expect_pop_tok(tokbuf, TOKEN_SEMICOLON);
|
||||
// TODO filling label
|
||||
@ -211,7 +211,7 @@ ast_node_t* parse_stmt(parser_t* parser) {
|
||||
case TOKEN_CASE: {
|
||||
// TODO label switch
|
||||
pop_tok(tokbuf);
|
||||
error("unimplemented switch label");
|
||||
LOG_ERROR("unimplemented switch label");
|
||||
node->label_stmt.label = parse_expr(parser);
|
||||
// TODO 该表达式为const int
|
||||
expect_pop_tok(tokbuf, TOKEN_COLON);
|
||||
@ -234,7 +234,7 @@ ast_node_t* parse_stmt(parser_t* parser) {
|
||||
flush_peek_tok(tokbuf);
|
||||
ttype = peek_tok_type(tokbuf);
|
||||
if (ttype != TOKEN_SEMICOLON) {
|
||||
error("exp must end with \";\"");
|
||||
LOG_ERROR("exp must end with \";\"");
|
||||
}
|
||||
pop_tok(tokbuf);
|
||||
node->type = NT_STMT_EXPR;
|
||||
|
@ -1,10 +1,10 @@
|
||||
#include "../ast.h"
|
||||
#include "../parser.h"
|
||||
#include "../type.h"
|
||||
#include "ast.h"
|
||||
|
||||
ast_node_t* new_ast_ident_node(tok_t* tok) {
|
||||
if (tok->type != TOKEN_IDENT) {
|
||||
error("syntax error: want identifier but got %d", tok->type);
|
||||
LOG_ERROR("syntax error: want identifier but got %d", tok->type);
|
||||
}
|
||||
ast_node_t* node = new_ast_node();
|
||||
node->type = NT_TERM_IDENT;
|
||||
@ -13,7 +13,7 @@ ast_node_t* new_ast_ident_node(tok_t* tok) {
|
||||
return node;
|
||||
}
|
||||
|
||||
ast_node_t* expect_pop_ident(tok_buf_t* tokbuf) {
|
||||
ast_node_t* expect_pop_ident(tok_stream_t* tokbuf) {
|
||||
flush_peek_tok(tokbuf);
|
||||
tok_t* tok = peek_tok(tokbuf);
|
||||
ast_node_t* node = new_ast_ident_node(tok);
|
||||
@ -22,7 +22,7 @@ ast_node_t* expect_pop_ident(tok_buf_t* tokbuf) {
|
||||
}
|
||||
|
||||
ast_node_t* parse_type(parser_t* parser) {
|
||||
tok_buf_t* tokbuf = &parser->tokbuf;
|
||||
tok_stream_t* tokbuf = &parser->tokbuf;
|
||||
flush_peek_tok(tokbuf);
|
||||
tok_type_t ttype = peek_tok_type(tokbuf);
|
||||
data_type_t dtype;
|
||||
@ -35,7 +35,7 @@ ast_node_t* parse_type(parser_t* parser) {
|
||||
case TOKEN_FLOAT: dtype = TYPE_FLOAT; break;
|
||||
case TOKEN_DOUBLE: dtype = TYPE_DOUBLE; break;
|
||||
default:
|
||||
error("无效的类型说明符");
|
||||
LOG_ERROR("无效的类型说明符");
|
||||
}
|
||||
|
||||
ast_node_t* node = new_ast_node();
|
||||
|
@ -1,13 +1,16 @@
|
||||
#include <lib/core.h>
|
||||
#include "parser.h"
|
||||
#include "type.h"
|
||||
|
||||
void init_parser(parser_t* parser, lexer_t* lexer, symtab_t* symtab) {
|
||||
init_lib_core();
|
||||
|
||||
parser->cur_node = NULL;
|
||||
parser->root = NULL;
|
||||
|
||||
parser->lexer = lexer;
|
||||
parser->symtab = symtab;
|
||||
init_tokbuf(&parser->tokbuf, lexer, (get_tokbuf_func)get_valid_token);
|
||||
init_tokbuf(&parser->tokbuf, lexer, (tok_stream_get_func)get_valid_token);
|
||||
parser->tokbuf.cap = sizeof(parser->TokenBuffer) / sizeof(parser->TokenBuffer[0]);
|
||||
parser->tokbuf.buf = parser->TokenBuffer;
|
||||
}
|
||||
|
@ -1,20 +1,19 @@
|
||||
#ifndef __PARSER_H__
|
||||
#define __PARSER_H__
|
||||
|
||||
#include "../frontend.h"
|
||||
|
||||
#include "../lexer/lexer.h"
|
||||
#include "ast.h"
|
||||
typedef struct lexer lexer_t;
|
||||
typedef struct symtab symtab_t;
|
||||
#define PARSER_MAX_TOKEN_QUEUE 16
|
||||
|
||||
typedef struct parser {
|
||||
struct ASTNode* root;
|
||||
struct ASTNode* cur_node;
|
||||
ast_node_t* root;
|
||||
ast_node_t* cur_node;
|
||||
|
||||
lexer_t* lexer;
|
||||
symtab_t* symtab;
|
||||
tok_buf_t tokbuf;
|
||||
tok_stream_t tokbuf;
|
||||
tok_t TokenBuffer[PARSER_MAX_TOKEN_QUEUE];
|
||||
int err_level;
|
||||
} parser_t;
|
||||
|
@ -1,5 +1,6 @@
|
||||
// symtab.c
|
||||
#include "../../frontend.h"
|
||||
#include <lib/core.h>
|
||||
#include "scope.h"
|
||||
#include "symtab.h"
|
||||
|
||||
@ -24,7 +25,7 @@ void symtab_enter_scope(symtab_t* symtab) {
|
||||
void symtab_leave_scope(symtab_t* symtab) {
|
||||
Scope * scope = symtab->cur_scope;
|
||||
if (scope == NULL) {
|
||||
error("cannot leave NULL scope or global scope");
|
||||
LOG_ERROR("cannot leave NULL scope or global scope");
|
||||
}
|
||||
symtab->cur_scope = symtab->cur_scope->parent;
|
||||
scope_destroy(scope);
|
||||
@ -35,7 +36,7 @@ void* symtab_add_symbol(symtab_t* symtab, const char* name, void* ast_node, int
|
||||
void* node = scope_lookup_current(scope, name);
|
||||
if (node != NULL) {
|
||||
if (!can_duplicate) {
|
||||
error("duplicate symbol %s", name);
|
||||
LOG_ERROR("duplicate symbol %s", name);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
Reference in New Issue
Block a user