// This file contains a recursive descent parser for C.
//
// Most functions in this file are named after the symbols they are
// supposed to read from an input token list. For example, stmt() is
// responsible for reading a statement from a token list. The function
// then construct an AST node representing a statement.
//
// Each function conceptually returns two values, an AST node and
// remaining part of the input tokens. Since C doesn't support
// multiple return values, the remaining tokens are returned to the
// caller via a pointer argument.
//
// Input tokens are represented by a linked list. Unlike many recursive
// descent parsers, we don't have the notion of the "input token stream".
// Most parsing functions don't change the global state of the parser.
// So it is very easy to lookahead arbitrary number of tokens in this
// parser.
#include "chibicc.h"
// Scope for local variables, global variables, typedefs
// or enum constants
typedef struct VarScope VarScope;
struct VarScope {
VarScope *next;
char *name;
Obj *var;
Type *type_def;
Type *enum_ty;
int enum_val;
};
// Scope for struct, union or enum tags
typedef struct TagScope TagScope;
struct TagScope {
TagScope *next;
char *name;
Type *ty;
};
// Represents a block scope.
typedef struct Scope Scope;
struct Scope {
Scope *next;
// C has two block scopes; one is for variables/typedefs and
// the other is for struct/union/enum tags.
VarScope *vars;
TagScope *tags;
};
// Variable attributes such as typedef or extern.
typedef struct {
bool is_typedef;
bool is_static;
bool is_extern;
bool is_inline;
bool is_tls;
int align;
} VarAttr;
// This struct represents a variable initializer. Since initializers
// can be nested (e.g. `int x[2][2] = {{1, 2}, {3, 4}}`), this struct
// is a tree data structure.
typedef struct Initializer Initializer;
struct Initializer {
Initializer *next;
Type *ty;
Token *tok;
bool is_flexible;
// If it's not an aggregate type and has an initializer,
// `expr` has an initialization expression.
Node *expr;
// If it's an initializer for an aggregate type (e.g. array or struct),
// `children` has initializers for its children.
Initializer **children;
// Only one member can be initialized for a union.
// `mem` is used to clarify which member is initialized.
Member *mem;
};
// For local variable initializer.
typedef struct InitDesg InitDesg;
struct InitDesg {
InitDesg *next;
int idx;
Member *member;
Obj *var;
};
// All local variable instances created during parsing are
// accumulated to this list.
static Obj *locals;
// Likewise, global variables are accumulated to this list.
static Obj *globals;
static Scope *scope = &(Scope){};
// Points to the function object the parser is currently parsing.
static Obj *current_fn;
// Lists of all goto statements and labels in the curent function.
static Node *gotos;
static Node *labels;
// Current "goto" and "continue" jump targets.
static char *brk_label;
static char *cont_label;
// Points to a node representing a switch if we are parsing
// a switch statement. Otherwise, NULL.
static Node *current_switch;
static Obj *builtin_alloca;
static bool is_typename(Token *tok);
static Type *declspec(Token **rest, Token *tok, VarAttr *attr);
static Type *typename(Token **rest, Token *tok);
static Type *enum_specifier(Token **rest, Token *tok);
static Type *typeof_specifier(Token **rest, Token *tok);
static Type *type_suffix(Token **rest, Token *tok, Type *ty);
static Type *declarator(Token **rest, Token *tok, Type *ty);
static Node *declaration(Token **rest, Token *tok, Type *basety, VarAttr *attr);
static void array_initializer2(Token **rest, Token *tok, Initializer *init, int i);
static void struct_initializer2(Token **rest, Token *tok, Initializer *init, Member *mem);
static void initializer2(Token **rest, Token *tok, Initializer *init);
static Initializer *initializer(Token **rest, Token *tok, Type *ty, Type **new_ty);
static Node *lvar_initializer(Token **rest, Token *tok, Obj *var);
static void gvar_initializer(Token **rest, Token *tok, Obj *var);
static Node *compound_stmt(Token **rest, Token *tok);
static Node *stmt(Token **rest, Token *tok);
static Node *expr_stmt(Token **rest, Token *tok);
static Node *expr(Token **rest, Token *tok);
static int64_t eval(Node *node);
static int64_t eval2(Node *node, char ***label);
static int64_t eval_rval(Node *node, char ***label);
static bool is_const_expr(Node *node);
static Node *assign(Token **rest, Token *tok);
static Node *logor(Token **rest, Token *tok);
static double eval_double(Node *node);
static Node *conditional(Token **rest, Token *tok);
static Node *logand(Token **rest, Token *tok);
static Node *bitor(Token **rest, Token *tok);
static Node *bitxor(Token **rest, Token *tok);
static Node *bitand(Token **rest, Token *tok);
static Node *equality(Token **rest, Token *tok);
static Node *relational(Token **rest, Token *tok);
static Node *shift(Token **rest, Token *tok);
static Node *add(Token **rest, Token *tok);
static Node *new_add(Node *lhs, Node *rhs, Token *tok);
static Node *new_sub(Node *lhs, Node *rhs, Token *tok);
static Node *mul(Token **rest, Token *tok);
static Node *cast(Token **rest, Token *tok);
static Member *get_struct_member(Type *ty, Token *tok);
static Type *struct_decl(Token **rest, Token *tok);
static Type *union_decl(Token **rest, Token *tok);
static Node *postfix(Token **rest, Token *tok);
static Node *funcall(Token **rest, Token *tok, Node *node);
static Node *unary(Token **rest, Token *tok);
static Node *primary(Token **rest, Token *tok);
static Token *parse_typedef(Token *tok, Type *basety);
static bool is_function(Token *tok);
static Token *function(Token *tok, Type *basety, VarAttr *attr);
static Token *global_variable(Token *tok, Type *basety, VarAttr *attr);
static int align_down(int n, int align) {
return align_to(n - align + 1, align);
}
static void enter_scope(void) {
Scope *sc = calloc(1, sizeof(Scope));
sc->next = scope;
scope = sc;
}
static void leave_scope(void) {
scope = scope->next;
}
// Find a variable by name.
static VarScope *find_var(Token *tok) {
for (Scope *sc = scope; sc; sc = sc->next)
for (VarScope *sc2 = sc->vars; sc2; sc2 = sc2->next)
if (equal(tok, sc2->name))
return sc2;
return NULL;
}
static Type *find_tag(Token *tok) {
for (Scope *sc = scope; sc; sc = sc->next)
for (TagScope *sc2 = sc->tags; sc2; sc2 = sc2->next)
if (equal(tok, sc2->name))
return sc2->ty;
return NULL;
}
static Node *new_node(NodeKind kind, Token *tok) {
Node *node = calloc(1, sizeof(Node));
node->kind = kind;
node->tok = tok;
return node;
}
static Node *new_binary(NodeKind kind, Node *lhs, Node *rhs, Token *tok) {
Node *node = new_node(kind, tok);
node->lhs = lhs;
node->rhs = rhs;
return node;
}
static Node *new_unary(NodeKind kind, Node *expr, Token *tok) {
Node *node = new_node(kind, tok);
node->lhs = expr;
return node;
}
static Node *new_num(int64_t val, Token *tok) {
Node *node = new_node(ND_NUM, tok);
node->val = val;
return node;
}
static Node *new_long(int64_t val, Token *tok) {
Node *node = new_node(ND_NUM, tok);
node->val = val;
node->ty = ty_long;
return node;
}
static Node *new_ulong(long val, Token *tok) {
Node *node = new_node(ND_NUM, tok);
node->val = val;
node->ty = ty_ulong;
return node;
}
static Node *new_var_node(Obj *var, Token *tok) {
Node *node = new_node(ND_VAR, tok);
node->var = var;
return node;
}
static Node *new_vla_ptr(Obj *var, Token *tok) {
Node *node = new_node(ND_VLA_PTR, tok);
node->var = var;
return node;
}
Node *new_cast(Node *expr, Type *ty) {
add_type(expr);
Node *node = calloc(1, sizeof(Node));
node->kind = ND_CAST;
node->tok = expr->tok;
node->lhs = expr;
node->ty = copy_type(ty);
return node;
}
static VarScope *push_scope(char *name) {
VarScope *sc = calloc(1, sizeof(VarScope));
sc->name = name;
sc
没有合适的资源?快使用搜索试试~ 我知道了~
c编译器chibicc的所有commits对应的代码
共2000个文件
c:1357个
h:305个
md:278个
需积分: 0 1 下载量 121 浏览量
2024-02-21
01:17:28
上传
评论
收藏 12.98MB ZIP 举报
温馨提示
chibicc_commits_all
资源推荐
资源详情
资源评论
收起资源包目录
c编译器chibicc的所有commits对应的代码 (2000个子文件)
parse.c 85KB
parse.c 85KB
parse.c 85KB
parse.c 85KB
parse.c 85KB
parse.c 84KB
parse.c 83KB
parse.c 79KB
parse.c 77KB
parse.c 75KB
parse.c 72KB
parse.c 70KB
parse.c 69KB
parse.c 69KB
parse.c 69KB
parse.c 68KB
parse.c 68KB
parse.c 67KB
parse.c 65KB
parse.c 65KB
parse.c 64KB
parse.c 64KB
parse.c 64KB
parse.c 64KB
parse.c 64KB
parse.c 64KB
parse.c 62KB
parse.c 62KB
parse.c 62KB
parse.c 58KB
parse.c 57KB
parse.c 53KB
parse.c 52KB
codegen.c 41KB
codegen.c 41KB
codegen.c 41KB
codegen.c 41KB
codegen.c 41KB
parse.c 39KB
codegen.c 37KB
codegen.c 37KB
codegen.c 35KB
codegen.c 35KB
codegen.c 35KB
codegen.c 35KB
codegen.c 35KB
codegen.c 35KB
codegen.c 35KB
codegen.c 35KB
codegen.c 34KB
codegen.c 34KB
codegen.c 34KB
codegen.c 33KB
parse.c 31KB
parse.c 31KB
preprocess.c 30KB
preprocess.c 30KB
preprocess.c 30KB
preprocess.c 30KB
preprocess.c 30KB
preprocess.c 30KB
preprocess.c 30KB
preprocess.c 30KB
preprocess.c 30KB
preprocess.c 27KB
preprocess.c 27KB
parse.c 27KB
preprocess.c 26KB
preprocess.c 26KB
preprocess.c 26KB
parse.c 26KB
codegen.c 26KB
preprocess.c 25KB
preprocess.c 25KB
preprocess.c 25KB
preprocess.c 25KB
preprocess.c 25KB
preprocess.c 25KB
codegen.c 23KB
codegen.c 23KB
codegen.c 23KB
codegen.c 23KB
codegen.c 23KB
codegen.c 23KB
parse.c 21KB
parse.c 21KB
parse.c 21KB
parse.c 21KB
codegen.c 21KB
preprocess.c 20KB
codegen.c 20KB
parse.c 20KB
codegen.c 19KB
tokenize.c 19KB
tokenize.c 19KB
tokenize.c 19KB
tokenize.c 19KB
tokenize.c 19KB
tokenize.c 19KB
tokenize.c 19KB
共 2000 条
- 1
- 2
- 3
- 4
- 5
- 6
- 20
资源评论
御风@户外
- 粉丝: 256
- 资源: 7
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 二叉树7-1-1.cpp
- android 9.0 原生模拟器 签名文件
- 技术面试最后反问面试官的话 校招面试非技术问题有哪些 非技术问题如何回答.png
- NB-IOT-BC26全网通模块Altium+ CADENCE +PADS三种格式(原理图SCH+PCB封装库)文件.zip
- 基于微信小程序开发的校园失物招领系统源码毕业设计(优质项目源码).zip
- 词向量是一种将自然语言中的单词转换为数值向量的技术,它能够捕捉词义和上下文信息
- nmap与masscan的简单使用
- MyBatis动态SQL.pdf
- 基于stm32单片机protues仿真的温湿度控制系统设计(仿真图、源代码)
- 词向量:自然语言处理的基石
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功