├── .gitignore ├── 100days.txt ├── CMakeLists.txt ├── README.md ├── doc ├── bnf.txt ├── local_variable_layout.txt └── struct_layout.txt ├── src ├── AST │ ├── AstNode.cpp │ ├── AstNode.h │ └── AstVisitor.h ├── Basic │ ├── Diag.cpp │ └── Diag.h ├── Gen │ ├── CodeGen.cpp │ └── CodeGen.h ├── Lex │ ├── Lexer.cpp │ ├── Lexer.h │ └── ReserveWord.cpp ├── Parse │ ├── Decl.cpp │ ├── Decl.h │ ├── Expr.cpp │ ├── Expr.h │ ├── Parser.cpp │ ├── Parser.h │ ├── Stmt.cpp │ └── Stmt.h ├── Sema │ ├── DeclSema.cpp │ ├── ExprSema.cpp │ ├── Sema.cpp │ ├── Sema.h │ ├── StmtSema.cpp │ ├── Symbol.cpp │ ├── Symbol.h │ ├── SymbolTable.cpp │ ├── SymbolTable.h │ ├── Type.cpp │ └── Type.h └── main.cpp └── test ├── arith.c ├── array.c ├── build.py ├── common.c ├── control.c ├── declaration.c ├── function.c ├── pointer.c ├── scope.c ├── struct.c └── union.c /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | cmake-build-debug/ 3 | -------------------------------------------------------------------------------- /100days.txt: -------------------------------------------------------------------------------- 1 | 100天开发c编译器 2 | 3 | build step: 4 | 1. cd c100/ 5 | 2. cd testcode/ 6 | 3. python build.py 7 | 8 | day1: 支持编译5+1-3*4/2 9 | day2: 支持编译5+(1-3)*4/2 10 | day3: 支持编译a=3;5+a*4/2-a; 11 | day4: 支持错误提示, eg 输入"4+3"会提示 ';' expected 12 | day5: 编译 a=3;a==3;a!=3;a>3;a>=3;a<3;a<=3; 13 | day6: 能编译如下if语句 14 | a=3; if (a!=4) a = 5; 15 | a=3; if (a!=4) a = 5; else a = 6; 16 | a=3; if (a!=4) {a = 5;a = a + a;} else {a = a*a; a = a + 10;} 17 | day7: 编译 a=0; b=1; while (a < 10) {a = a+1; b=a+b;} b; 18 | day8: 支持文件读入,编译do-while和for语句 19 | day9: 支持函数定义, 现在能编译如下语句 20 | day10: 支持函数调用,支持递归,能编译 21 | day11: 支持类型,函数类型,变量声明语句,能编译正式的c代码了 22 | day12: 调整诊断代码,支持如下的错误诊断. 拆分测试。 23 | day13: 添加一元操作符的支持,支持注释操作. 能编译 24 | day14: 添加指针运算和sizeof操作 25 | day15: 支持数组声明和指针访问 26 | day16: 支持数组索引,添加编译脚本 27 | day17: 支持char/short/long类型 28 | day18: 支持struct/union声明和成员访问 29 | day19: 支持作用域和struct tag 以及 -> 访问 30 | day20: split parser&&sema 31 | day21: for支持声明&&添加break和continue语句 32 | day22: 支持goto和switch语句 33 | 34 | int main() { 35 | 36 | struct A { 37 | char c, d; 38 | } s; 39 | 40 | struct A *p = &s; 41 | p->c = 5; 42 | p->d = 6; 43 | 44 | return s.c * s.d; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(ccc) 3 | set(CMAKE_CXX_STANDARD 17) 4 | set(CMAKE_BUILD_TYPE Debug) 5 | include_directories(src/ src/AST src/Lex src/Parse src/Sema src/Gen src/Basic) 6 | file(GLOB_RECURSE SRCS Diag.cpp main.cpp 7 | "src/AST/*.cpp" 8 | "src/Lex/*.cpp" 9 | "src/Parse/*.cpp" 10 | "src/Sema/*.cpp" 11 | "src/Gen/*.cpp" 12 | "src/Basic/*.cpp") 13 | add_executable(${PROJECT_NAME} ${SRCS}) 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C编译器功能TODO 2 | 3 | Note: ccc is no longer an active project. The successor is 4 | [subc-llvm](https://github.com/iiicp/subc-llvm). 5 | 6 | # 声明 7 | 8 | - [ ] 存储类声明说明符(`extern`、`static`、`auto`、`register`、`typedef`) 9 | - [ ] 类型限定符(`const`、`volatile`、`restrict`) 10 | - [x] 声明说明符(`char`、`short`、`int`、`long`) 11 | - [x] 指针说明符(`*`) 12 | - [x] 直接说明符(`[]`、`()`) 13 | - [x] 结构体说明符(`struct or union {struct-declaration*}、struct or union tag{struct-declaration*}`) 14 | - [ ] 枚举说明符 15 | - [ ] 函数声明符(`inline`) 16 | 17 | # 语句 18 | 19 | - [x] if-else 20 | - [x] switch-case-default 21 | - [x] while 22 | - [x] do-while 23 | - [x] for 24 | - [x] goto-label 25 | - [x] break 26 | - [x] continue 27 | - [x] blockStmt 28 | 29 | # 表达式 30 | 31 | - [ ] 逗号表达式(`,`) 32 | - [x] 赋值表达式(`=`) 33 | - [ ] 赋值表达式(`+=`、`-=`、`*=`、`/=` 、`%=`、`<<=`、`>>=`、`&=`、`|=`、`^=`) 34 | - [ ] 条件表达式(`?:`) 35 | - [ ] 逻辑或表达式(`||`) 36 | - [ ] 逻辑与表达式(`&&`) 37 | - [ ] 按位或表达式(`|`) 38 | - [ ] 按位异或表达式(`^`) 39 | - [ ] 按位与表达式(`&`) 40 | - [x] 相等表达式(`==`、`!=`) 41 | - [x] 关系表达式(`>`、`>=`、`<`、`<=`) 42 | - [ ] 移位表达式(`<<`、`>>`) 43 | - [x] 加法表达式(`+`、`-`) 44 | - [x] 乘法表达式(`*`、`/`) 45 | - [ ] 乘法表达式(`%`) 46 | - [ ] case表达式 (`(type-name) unary-expression`) 47 | - [x] 一元表达式(`+`、`-`、`&`、`*`) 48 | - [ ] 一元表达式(`++`、`- -`) 49 | - [ ] 一元表达式(`~`、`!`) 50 | - [x] 一元表达式(`sizeof unary-expression`) 51 | - [ ] 一元表达式(`sizeof (type-name)`) 52 | - [x] 后缀表达式(`[ ]`、`( )`、`.`、`→`) 53 | - [ ] 后缀表达式(`++`、 `- -`) 54 | - [x] 基本表达式(`id`、`num`、(`Expr`)、`StmtExpr`) 55 | 56 | # 词素 57 | 58 | - [ ] 整数解析(八进制、十进制、十六进制、后缀) 59 | - [ ] 浮点数解析 (后缀) 60 | - [ ] 字符解析(包含转义字符) 61 | - [ ] 字符串解析(包含转义字符) 62 | - [ ] 标识符(包含关键字) 63 | - [ ] 运算符、标点符号、分界符 64 | 65 | # 操作系统平台 66 | 67 | - [x] Linux 68 | - [x] MacOSX 69 | 70 | # 指令集 71 | 72 | - [x] X86-64 73 | -------------------------------------------------------------------------------- /doc/bnf.txt: -------------------------------------------------------------------------------- 1 | ----------------------------------------- 2 | Prog := Expr 3 | Expr := AddExpr 4 | AddExpr := MultiExpr 5 | := AddExpr + MultiExpr 6 | := AddExpr - MultiExpr 7 | MultiExpr := PrimaryExpr 8 | := MultiExpr * PrimaryExpr 9 | := MultiExpr / PrimaryExpr 10 | PrimaryExpr := Num 11 | ----------------------------------------- 12 | Prog := Expr 13 | Expr := AddExpr 14 | AddExpr := MultiExpr 15 | := AddExpr + MultiExpr 16 | := AddExpr - MultiExpr 17 | MultiExpr := PrimaryExpr 18 | := MultiExpr * PrimaryExpr 19 | := MultiExpr / PrimaryExpr 20 | PrimaryExpr := Num 21 | := (Expr) 22 | 23 | ----------------------------------------- 24 | Prog := Stmt* 25 | Stmt := Expr; 26 | Expr := Expr 27 | Expr := AddExpr 28 | := AddExpr = Expr 29 | AddExpr := MultiExpr 30 | := AddExpr + MultiExpr 31 | := AddExpr - MultiExpr 32 | MultiExpr := PrimaryExpr 33 | := MultiExpr * PrimaryExpr 34 | := MultiExpr / PrimaryExpr 35 | PrimaryExpr := Num 36 | := (Expr) 37 | := Id 38 | 39 | ----------------------------------------- 40 | Prog := Function* 41 | Function := DeclarationSpec Declarator "{"Stmt*"}" 42 | DeclarationSpec := char | short | int | long | StructOrUnionDecl 43 | StructOrUnionDecl := struct_or_union identifier? "{" StructMember* "}" 44 | := struct_or_union identifier 45 | StructMember := DeclarationSpec Declarator (, Declarator)* ";" 46 | Declarator := (*)* identifier TypeSuffix 47 | TypeSuffix := "("FuncArg?")" 48 | := "["Number"]"+ 49 | := ε 50 | FuncArg := DeclarationSpec Declarator (, DeclarationSpec Declarator)* 51 | Stmt := Expr?; 52 | := IfStmt 53 | := WhileStmt 54 | := DoWhileStmt 55 | := ForStmt 56 | := BlockStmt 57 | := ReturnStmt 58 | := DeclarationStmt 59 | IfStmt := if "(" Expr ")" Stmt 60 | := if "(" Expr ")" Stmt Else Stmt 61 | WhileStmt := while "(" Expr ")" Stmt 62 | DoWhileStmt := do Stmt while "(" Expr ")" ";" 63 | ForStmt := for "("Expr?;Expr?;Expr?")" Stmt 64 | BlockStmt := "{" Stmt* "}" 65 | ReturnStmt := return Expr ";" 66 | DeclarationStmt := DeclarationSpec Declarator(= Expr)? (, Declarator(= Expr)?)* ";" 67 | := DeclarationSpec ";" 68 | Expr := Expr 69 | Expr := EqualityExpr 70 | := EqualityExpr = Expr 71 | EqualityExpr := RelationalExpr 72 | := EqualityExpr == RelationalExpr 73 | := EqualityExpr != relationalExpr 74 | RelationalExpr := AddExpr 75 | := RelationalExpr < AddExpr 76 | := RelationalExpr > AddExpr 77 | := RelationalExpr <= AddExpr 78 | := RelationalExpr >= AddExpr 79 | AddExpr := MultiExpr 80 | := AddExpr + MultiExpr 81 | := AddExpr - MultiExpr 82 | MultiExpr := UnaryExpr 83 | := MultiExpr * UnaryExpr 84 | := MultiExpr / UnaryExpr 85 | UnaryExpr := UnaryOperator UnaryExpr 86 | := PostfixExpr 87 | PostfixExpr := PrimaryExpr 88 | := PrimaryExpr ("["Expr"]") 89 | := PrimaryExpr "("ArgExprList?")" 90 | := PrimaryExpr "." identifier 91 | := PrimaryExpr "->" identifier 92 | PrimaryExpr := Num 93 | := (Expr) 94 | := Id 95 | := "({"Stmt+"})" 96 | := sizeof UnaryExpr 97 | ArgExprList := Expr(,Expr)* -------------------------------------------------------------------------------- /doc/local_variable_layout.txt: -------------------------------------------------------------------------------- 1 | ┌─────────────────┐ 2 | high │ │ old rsp │ 3 | │ │─────────────────| 4 | │ 028 | y ┤ 5 | │ ├─────────────────┤ 6 | │ │ x │ 7 | │ 020 ├─────────────────┤ int y, x; 8 | │ │ │ int *z = &x; 9 | │ 01c ├ z ┤ *(z+1) = 5; 10 | │ │ │ 11 | │ 018 ├─────────────────┤ z = 020 12 | │ │ │ z+1 => mem[020]+4 => mem[024] 13 | │ │ │ *(z+1) => load mem[024] 14 | │ │ │ 15 | │ 010 ├─────────────────┤ 16 | │ │ │ 17 | │ │ │ 18 | │ │ │ 19 | │ 008 ├─────────────────┤ 20 | │ │ │ 21 | low │ │ │ 22 | ▼ │ │ 23 | 000 └─────────────────┘ -------------------------------------------------------------------------------- /doc/struct_layout.txt: -------------------------------------------------------------------------------- 1 | struct { 2 | char c1; 3 | short s; 4 | char c2; 5 | long l; 6 | ┌──────────────┐ } s1; 7 | │ │ 8 | │ old rsp │ 9 | ├──────────────┤ 10 | │ │ 11 | │ │ ┌─────────────┐ 12 | 040 ├──────────────┤ │ │ 13 | │ │ │ long │ 14 | │ │ │ │ 15 | │ │ ├─────────────┤ 16 | │ │ ────────────► char 17 | │ │ ├─────────────┤ 18 | │ │ │ │ 19 | │ │ │ short │ 20 | 020 ├──────────────┤ ├─────────────┤ 21 | │ │ ├─────────────┤ 22 | │ │ │ char │ 23 | │ │ 0 └─────────────┘ 24 | │ │ 25 | │ │ 26 | │ │ 27 | │ │ 28 | └──────────────┘ -------------------------------------------------------------------------------- /src/AST/AstNode.cpp: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: AstNode.cpp.cc 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/3 9 | ***********************************/ 10 | 11 | #include "AstNode.h" 12 | 13 | namespace CCC 14 | { 15 | } 16 | -------------------------------------------------------------------------------- /src/AST/AstNode.h: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: AstNode.h 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/3 9 | ***********************************/ 10 | 11 | #ifndef CCC_ASTNODE_H 12 | #define CCC_ASTNODE_H 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "Lexer.h" 19 | 20 | namespace CCC 21 | { 22 | class AstVisitor; 23 | 24 | class AstNode 25 | { 26 | public: 27 | std::shared_ptr Tok; 28 | virtual ~AstNode() {} 29 | AstNode(std::shared_ptr tok) : Tok(tok) {} 30 | virtual void Accept(AstVisitor *visitor) = 0; 31 | }; 32 | 33 | enum class TagKind { 34 | Struct, 35 | Union 36 | }; 37 | 38 | // storage-class-specifier 39 | enum class StorageClass { 40 | UnSpecified, Typedef, Extern, Static, 41 | Auto, Register 42 | }; 43 | 44 | // type-specifier 45 | enum class TypeSpecifier { 46 | UnSpecified, Void, Char, Short, Int, 47 | Long, Float, Double, Signed, UnSigned, 48 | Bool, Struct, Union, Enum 49 | }; 50 | 51 | // type-qualifier 52 | enum class TypeQualifier { 53 | UnSpecified, Const, Restrict, Volatile 54 | }; 55 | } 56 | 57 | #endif // CCC_ASTNODE_H 58 | -------------------------------------------------------------------------------- /src/AST/AstVisitor.h: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: AstVisitor.h 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/30 9 | ***********************************/ 10 | 11 | #ifndef CCC_SRC_ASTVISITOR_H 12 | #define CCC_SRC_ASTVISITOR_H 13 | 14 | #include "AstNode.h" 15 | 16 | namespace CCC 17 | { 18 | /// declaration 19 | class TranslationUnit; 20 | class Function; 21 | class Declaration; 22 | class DeclSpecifier; 23 | class Declarator; 24 | class NameDeclarator; 25 | class FunctionDeclarator; 26 | class ArrayDeclarator; 27 | class PointerDeclarator; 28 | class ParamTypeList; 29 | class ParamDeclaration; 30 | class InitDeclarator; 31 | class Initializer; 32 | class StructSpecifier; 33 | class StructDeclaration; 34 | class StructDeclarator; 35 | class EnumSpecifier; 36 | class EnumDeclarator; 37 | class DeclSpecToken; 38 | 39 | /// stmt 40 | class StmtNode; 41 | class ExprStmtNode; 42 | class IfStmtNode; 43 | class WhileStmtNode; 44 | class DoWhileStmtNode; 45 | class ForStmtNode; 46 | class BlockStmtNode; 47 | class ReturnStmtNode; 48 | class BreakStmtNode; 49 | class ContinueStmtNode; 50 | class GotoStmtNode; 51 | class LabelStmtNode; 52 | class CaseStmtNode; 53 | class DefaultStmtNode; 54 | class SwitchStmtNode; 55 | 56 | /// expr 57 | class ExprNode; 58 | class AssignExpr; 59 | class SizeOfExpr; 60 | class BinaryExpr; 61 | class UnaryExpr; 62 | class NumExpr; 63 | class VarExpr; 64 | class FuncCallExpr; 65 | class StmtExpr; 66 | class MemberExpr; 67 | 68 | class AstVisitor { 69 | public: 70 | virtual ~AstVisitor() {} 71 | virtual void VisitorTranslationUnitNode(TranslationUnit *node) {}; 72 | virtual void VisitorFunctionNode(Function *node) {}; 73 | virtual void VisitorDeclarationNode(Declaration *node) {}; 74 | virtual void VisitorDeclSpecifierNode(DeclSpecifier *node) {}; 75 | virtual void VisitorPointerDeclaratorNode(PointerDeclarator *node) {}; 76 | virtual void VisitorNameDeclaratorNode(NameDeclarator *node) {}; 77 | virtual void VisitorFuncDeclaratorNode(FunctionDeclarator *node) {}; 78 | virtual void VisitorArrayDeclaratorNode(ArrayDeclarator *node) {}; 79 | virtual void VisitorInitDeclaratorNode(InitDeclarator *node) {}; 80 | virtual void VisitorInitializerNode(Initializer *node) {}; 81 | virtual void VisitorParamTypeListNode(ParamTypeList *node) {}; 82 | virtual void VisitorParamDeclarationNode(ParamDeclaration *node) {}; 83 | virtual void VisitorStructSpecifierNode(StructSpecifier *node) {}; 84 | virtual void VisitorStructDeclarationNode(StructDeclaration *node) {}; 85 | virtual void VisitorStructDeclaratorNode(StructDeclarator *node) {}; 86 | virtual void VisitorEnumSpecifierNode(EnumSpecifier *node) {}; 87 | virtual void VisitorEnumDeclaratorNode(EnumDeclarator *node) {}; 88 | virtual void VisitorDeclSpecTokenNode(DeclSpecToken *node) {}; 89 | 90 | virtual void VisitorExprStmtNode(ExprStmtNode *node) = 0; 91 | virtual void VisitorIfStmtNode(IfStmtNode *node) = 0; 92 | virtual void VisitorWhileStmtNode(WhileStmtNode *node) = 0; 93 | virtual void VisitorDoWhileStmtNode(DoWhileStmtNode *node) = 0; 94 | virtual void VisitorForStmtNode(ForStmtNode *node) = 0; 95 | virtual void VisitorBlockStmtNode(BlockStmtNode *node) = 0; 96 | virtual void VisitorReturnStmtNode(ReturnStmtNode *node) = 0; 97 | virtual void VisitorBreakStmtNode(BreakStmtNode *node) = 0; 98 | virtual void VisitorContinueStmtNode(ContinueStmtNode *node) = 0; 99 | virtual void VisitorGotoStmtNode(GotoStmtNode *node) = 0; 100 | virtual void VisitorLabelStmtNode(LabelStmtNode *node) = 0; 101 | virtual void VisitorCaseStmtNode(CaseStmtNode *node) = 0; 102 | virtual void VisitorDefaultStmtNode(DefaultStmtNode *node) = 0; 103 | virtual void VisitorSwitchStmtNode(SwitchStmtNode *node) = 0; 104 | 105 | virtual void VisitorAssignExprNode(AssignExpr *node) = 0; 106 | virtual void VisitorSizeOfExprNode(SizeOfExpr *node) = 0; 107 | virtual void VisitorBinaryExprNode(BinaryExpr *node) = 0; 108 | virtual void VisitorUnaryExprNode(UnaryExpr *node) = 0; 109 | virtual void VisitorNumExprNode(NumExpr *node) = 0; 110 | virtual void VisitorVarExprNode(VarExpr *node) = 0; 111 | virtual void VisitorFuncCallExprNode(FuncCallExpr *node) = 0; 112 | virtual void VisitorStmtExprNode(StmtExpr *node) = 0; 113 | virtual void VisitorMemberExprNode(MemberExpr *node) = 0; 114 | }; 115 | } 116 | 117 | 118 | #endif // CCC_SRC_ASTVISITOR_H 119 | -------------------------------------------------------------------------------- /src/Basic/Diag.cpp: -------------------------------------------------------------------------------- 1 | /*********************************** 2 | * File: Diag.cpp.cc 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/6 9 | ***********************************/ 10 | 11 | #include "Diag.h" 12 | #include 13 | #include 14 | #include 15 | 16 | namespace CCC { 17 | 18 | std::string PhaseToString(DiagPhase diagPhase) { 19 | switch (diagPhase) { 20 | case DiagPhase::LexPhase: 21 | return "LexPhase"; 22 | case DiagPhase::ParsePhase: 23 | return "ParsePhase"; 24 | case DiagPhase::SemaPhase: 25 | return "SemanticsPhase"; 26 | case DiagPhase::CodeGenPhase: 27 | return "CodeGenPhase"; 28 | } 29 | } 30 | 31 | void DiagLoc(DiagPhase diagPhase, SourceLocation loc, const char *fmt, ...) { 32 | va_list ap; 33 | va_start(ap, fmt); 34 | int len = fprintf(stderr, "%s:%s:%d:%d ", loc.FilePath, PhaseToString(diagPhase).data(), loc.Line+1, loc.Col); 35 | int i = loc.LineHead; 36 | while (loc.Code[i]!='\n'){ 37 | fprintf(stderr, "%c", loc.Code[i]); 38 | i++; 39 | } 40 | fprintf(stderr, "\n"); 41 | fprintf(stderr, "%*s", len + loc.Col,""); 42 | fprintf(stderr, "^"); 43 | vfprintf(stderr, fmt, ap); 44 | fprintf(stderr, "\n"); 45 | va_end(ap); 46 | exit(0); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Basic/Diag.h: -------------------------------------------------------------------------------- 1 | /*********************************** 2 | * File: Diag.h 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/6 9 | ***********************************/ 10 | 11 | #ifndef CCC_SRC_DIAG_H 12 | #define CCC_SRC_DIAG_H 13 | 14 | #include "Lexer.h" 15 | #include 16 | 17 | namespace CCC { 18 | 19 | #define LexDiag(loc, fmt, ...) DiagLoc(DiagPhase::LexPhase, loc, fmt, ##__VA_ARGS__); 20 | #define ParseDiag(loc, fmt, ...) DiagLoc(DiagPhase::ParsePhase, loc, fmt, ##__VA_ARGS__); 21 | #define SemaDiag(loc, fmt, ...) DiagLoc(DiagPhase::SemaPhase, loc, fmt, ##__VA_ARGS__); 22 | #define GenDiag(loc, fmt, ...) DiagLoc(DiagPhase::CodeGenPhase, loc, fmt, ##__VA_ARGS__); 23 | 24 | enum class DiagPhase { 25 | LexPhase, 26 | ParsePhase, 27 | SemaPhase, 28 | CodeGenPhase 29 | }; 30 | 31 | void DiagLoc(DiagPhase diagPhase, SourceLocation loc, const char*fmt, ...); 32 | 33 | 34 | } 35 | 36 | #endif //CCC_SRC_DIAG_H 37 | -------------------------------------------------------------------------------- /src/Gen/CodeGen.cpp: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: Gen.cpp.cc 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/3 9 | ***********************************/ 10 | 11 | #include "CodeGen.h" 12 | #include "Expr.h" 13 | #include "Decl.h" 14 | #include "Stmt.h" 15 | #include "Basic/Diag.h" 16 | #include 17 | #include "SymbolTable.h" 18 | 19 | using namespace CCC; 20 | 21 | void CodeGen::VisitorTranslationUnitNode(TranslationUnit *node) 22 | { 23 | for (auto &f : node->ExtDecl) 24 | f->Accept(this); 25 | } 26 | 27 | void CodeGen::VisitorDeclarationNode(Declaration *node) 28 | { 29 | if (node->IsLocalDecl) { 30 | for (auto &initDec : node->DecList) { 31 | if (initDec->Sym->Init != nullptr) { 32 | printf("\tlea %d(%%rbp), %%rax\n", initDec->Sym->Offset); 33 | Push(); 34 | initDec->Sym->Init->Expr->Accept(this); 35 | Store(initDec->Sym->Ty); 36 | } 37 | } 38 | } 39 | } 40 | 41 | void CodeGen::VisitorFunctionNode(Function *node) 42 | { 43 | printf("\t.text\n"); 44 | CurrentFuncName = node->FuncName; 45 | #ifdef __linux__ 46 | printf("\t.globl %s\n", CurrentFuncName.data()); 47 | printf("%s:\n",CurrentFuncName.data()); 48 | #else 49 | /// macos 50 | printf("\t.globl _%s\n",CurrentFuncName.data()); 51 | printf("_%s:\n",CurrentFuncName.data()); 52 | #endif 53 | 54 | int offset = 0; 55 | for (auto &sym : node->FSym->Locals) { 56 | offset += sym->Ty->Size; 57 | offset = AlignTo(offset, sym->Ty->Align); 58 | sym->Offset = -offset; 59 | } 60 | 61 | offset = AlignTo(offset, 16); 62 | 63 | printf("\tpush %%rbp\n"); 64 | printf("\tmov %%rsp, %%rbp\n"); 65 | printf("\tsub $%d, %%rsp\n", offset); 66 | 67 | int i = 0; 68 | for (auto &sym : node->FSym->Params) { 69 | if (sym->Ty->Size == 1) { 70 | printf("\tmov %s, %d(%%rbp)\n", Reg8[i++], sym->Offset); 71 | }else if (sym->Ty->Size == 2) { 72 | printf("\tmov %s, %d(%%rbp)\n", Reg16[i++], sym->Offset); 73 | }else if (sym->Ty->Size == 4) { 74 | printf("\tmov %s, %d(%%rbp)\n", Reg32[i++], sym->Offset); 75 | }else if (sym->Ty->Size == 8) { 76 | printf("\tmov %s, %d(%%rbp)\n", Reg64[i++], sym->Offset); 77 | }else { 78 | assert(0); 79 | } 80 | } 81 | 82 | node->BlockStmt->Accept(this); 83 | 84 | printf(".LReturn_%s:\n", CurrentFuncName.data()); 85 | printf("\tmov %%rbp, %%rsp\n"); 86 | printf("\tpop %%rbp\n"); 87 | printf("\tret\n"); 88 | } 89 | 90 | void CodeGen::VisitorBinaryExprNode(BinaryExpr *node) 91 | { 92 | node->Rhs->Accept(this); 93 | Push(); 94 | node->Lhs->Accept(this); 95 | Pop("%rdi"); 96 | 97 | switch (node->BinOp) { 98 | case BinaryOperator::Add: 99 | printf("\tadd %%rdi, %%rax\n"); 100 | break; 101 | case BinaryOperator::Sub: 102 | printf("\tsub %%rdi, %%rax\n"); 103 | break; 104 | case BinaryOperator::Mul: 105 | printf("\timul %%rdi, %%rax\n"); 106 | break; 107 | case BinaryOperator::Div: { 108 | printf("\tcqo\n"); 109 | printf("\tidiv %%rdi\n"); 110 | break; 111 | } 112 | case BinaryOperator::Equal:{ 113 | printf("\tcmp %%rdi, %%rax\n"); 114 | printf("\tsete %%al\n"); 115 | printf("\tmovzb %%al, %%rax\n"); 116 | break; 117 | } 118 | case BinaryOperator::PipeEqual: { 119 | printf("\tcmp %%rdi, %%rax\n"); 120 | printf("\tsetne %%al\n"); 121 | printf("\tmovzb %%al, %%rax\n"); 122 | break; 123 | } 124 | case BinaryOperator::Greater: { 125 | printf("\tcmp %%rdi, %%rax\n"); 126 | printf("\tsetg %%al\n"); 127 | printf("\tmovzb %%al, %%rax\n"); 128 | break; 129 | } 130 | case BinaryOperator::GreaterEqual: { 131 | printf("\tcmp %%rdi, %%rax\n"); 132 | printf("\tsetge %%al\n"); 133 | printf("\tmovzb %%al, %%rax\n"); 134 | break; 135 | } 136 | case BinaryOperator::Lesser: { 137 | printf("\tcmp %%rdi, %%rax\n"); 138 | printf("\tsetl %%al\n"); 139 | printf("\tmovzb %%al, %%rax\n"); 140 | break; 141 | } 142 | case BinaryOperator::LesserEqual: { 143 | printf("\tcmp %%rdi, %%rax\n"); 144 | printf("\tsetle %%al\n"); 145 | printf("\tmovzb %%al, %%rax\n"); 146 | break; 147 | } 148 | default: 149 | assert(0); 150 | break; 151 | } 152 | } 153 | 154 | void CodeGen::VisitorNumExprNode(NumExpr *node) 155 | { 156 | printf("\tmovabs $%ld, %%rax\n", node->Value); 157 | } 158 | 159 | void CodeGen::Push() 160 | { 161 | printf("\tpush %%rax\n"); 162 | StackLevel++; 163 | } 164 | 165 | void CodeGen::Pop(const char *reg) 166 | { 167 | printf("\tpop %s\n", reg); 168 | StackLevel--; 169 | } 170 | 171 | void CodeGen::VisitorExprStmtNode(ExprStmtNode *node) { 172 | if (node->Lhs) 173 | node->Lhs->Accept(this); 174 | } 175 | 176 | void CodeGen::VisitorAssignExprNode(AssignExpr *node) { 177 | GenAddr(node->Lhs.get()); 178 | Push(); 179 | node->Rhs->Accept(this); 180 | Store(node->Ty); 181 | } 182 | 183 | void CodeGen::VisitorVarExprNode(VarExpr *node) { 184 | GenAddr(node); 185 | Load(node->Ty); 186 | } 187 | 188 | void CodeGen::VisitorMemberExprNode(MemberExpr *node) { 189 | GenAddr(node); 190 | Load(node->Ty); 191 | } 192 | 193 | void CodeGen::VisitorIfStmtNode(IfStmtNode *node) { 194 | /// 1. 判断条件 195 | int n = Sequence++; 196 | node->Cond->Accept(this); 197 | printf("\tcmp $0, %%rax\n"); 198 | if (node->Else) { 199 | printf("\tje .L.else_%d\n",n); 200 | }else { 201 | printf("\tje .L.end_%d\n", n); 202 | } 203 | 204 | node->Then->Accept(this); 205 | printf("\tjmp .L.end_%d\n", n); 206 | 207 | if (node->Else) { 208 | printf(".L.else_%d:\n", n); 209 | node->Else->Accept(this); 210 | printf("\tjmp .L.end_%d\n", n); 211 | } 212 | 213 | printf(".L.end_%d:\n", n); 214 | } 215 | 216 | void CodeGen::VisitorBlockStmtNode(BlockStmtNode *node) 217 | { 218 | for (auto &d : node->Decls) 219 | d->Accept(this); 220 | for (auto &s : node->Stmts) 221 | s->Accept(this); 222 | } 223 | 224 | void CodeGen::VisitorWhileStmtNode(WhileStmtNode *node) 225 | { 226 | int n = Sequence++; 227 | LabelStack.push(n); 228 | printf(".LContinue_%d:\n", n); 229 | node->Cond->Accept(this); 230 | printf("\tcmp $0, %%rax\n"); 231 | printf("\tje .LBreak_%d\n", n); 232 | node->Then->Accept(this); 233 | printf("\tjmp .LContinue_%d\n", n); 234 | printf(".LBreak_%d:\n", n); 235 | LabelStack.pop(); 236 | } 237 | 238 | void CodeGen::VisitorDoWhileStmtNode(DoWhileStmtNode *node) 239 | { 240 | int n = Sequence++; 241 | LabelStack.push(n); 242 | printf(".LBegin_%d:\n", n); 243 | node->Stmt->Accept(this); 244 | printf(".LContinue_%d:\n", n); 245 | node->Cond->Accept(this); 246 | printf("\tcmp $0, %%rax\n"); 247 | printf("\tje .LBreak_%d\n", n); 248 | printf("\tjmp .LBegin_%d\n", n); 249 | printf(".LBreak_%d:\n", n); 250 | LabelStack.pop(); 251 | } 252 | 253 | void CodeGen::VisitorForStmtNode(ForStmtNode *node) 254 | { 255 | int n = Sequence++; 256 | LabelStack.push(n); 257 | 258 | if (node->InitExpr) 259 | node->InitExpr->Accept(this); 260 | else if (node->InitDecl) { 261 | node->InitDecl->Accept(this); 262 | } 263 | printf(".LBegin_%d:\n", n); 264 | if (node->Cond) { 265 | node->Cond->Accept(this); 266 | printf("\tcmp $0, %%rax\n"); 267 | printf("\tje .LBreak_%d\n", n); 268 | } 269 | node->Stmt->Accept(this); 270 | printf(".LContinue_%d:\n", n); 271 | if (node->Inc) { 272 | node->Inc->Accept(this); 273 | } 274 | printf("\tjmp .LBegin_%d\n", n); 275 | printf(".LBreak_%d:\n", n); 276 | 277 | LabelStack.pop(); 278 | } 279 | 280 | void CodeGen::VisitorStmtExprNode(StmtExpr *node) { 281 | for (auto &decl : node->Decls) { 282 | decl->Accept(this); 283 | } 284 | for (auto &s : node->Stmts) 285 | s->Accept(this); 286 | } 287 | 288 | void CodeGen::VisitorFuncCallExprNode(FuncCallExpr *node) { 289 | for(auto &arg : node->Args) { 290 | arg->Accept(this); 291 | Push(); 292 | } 293 | for(int i = node->Args.size()-1; i >= 0; i--) { 294 | Pop(Reg64[i]); 295 | } 296 | 297 | std::string FuncName(node->FuncName); 298 | printf("\tmov $0, %%rax\n"); 299 | #ifdef __linux__ 300 | printf("\tcall %s\n",FuncName.data()); 301 | #else 302 | printf("\tcall _%s\n",FuncName.data()); 303 | #endif 304 | } 305 | 306 | void CodeGen::VisitorReturnStmtNode(ReturnStmtNode *node) { 307 | node->Lhs->Accept(this); 308 | printf("\tjmp .LReturn_%s\n",CurrentFuncName.data()); 309 | } 310 | 311 | void CodeGen::VisitorBreakStmtNode(BreakStmtNode *node) { 312 | printf("\tjmp .LBreak_%d\n", LabelStack.top()); 313 | } 314 | 315 | void CodeGen::VisitorContinueStmtNode(ContinueStmtNode *node) { 316 | printf("\tjmp .LContinue_%d\n", LabelStack.top()); 317 | } 318 | 319 | void CodeGen::VisitorGotoStmtNode(GotoStmtNode *node) { 320 | printf("\tjmp .LLabel_%s_%s\n", CurrentFuncName.data(), std::string(node->LabelName).data()); 321 | } 322 | 323 | void CodeGen::VisitorLabelStmtNode(LabelStmtNode *node) { 324 | printf(".LLabel_%s_%s:\n",CurrentFuncName.data(), std::string(node->LabelName).data()); 325 | node->Stmt->Accept(this); 326 | } 327 | 328 | void CodeGen::VisitorCaseStmtNode(CaseStmtNode *node) { 329 | printf("\t.LCaseLabel_%d:\n", node->Label); 330 | node->Stmt->Accept(this); 331 | } 332 | 333 | void CodeGen::VisitorDefaultStmtNode(DefaultStmtNode *node) { 334 | printf("\t.LDefaultLabel_%d:\n", node->Label); 335 | node->Stmt->Accept(this); 336 | } 337 | 338 | void CodeGen::VisitorSwitchStmtNode(SwitchStmtNode *node) { 339 | int seq = Sequence++; 340 | LabelStack.push(seq); 341 | 342 | node->Expr->Accept(this); 343 | printf("\tmov %%rax, %%rdi\n"); 344 | 345 | for (auto &caseStmt : node->CaseStmtList) { 346 | caseStmt->Label = Sequence++; 347 | caseStmt->Expr->Accept(this); 348 | printf("\tcmp %%rax, %%rdi\n"); 349 | printf("\tje .LCaseLabel_%d\n", caseStmt->Label); 350 | } 351 | 352 | if (node->DefaultStmt) { 353 | node->DefaultStmt->Label = Sequence++; 354 | printf("\tjmp .LDefaultLabel_%d\n", node->DefaultStmt->Label); 355 | } 356 | 357 | printf("\tjmp .LBreak_%d\n", seq); 358 | 359 | node->Stmt->Accept(this); 360 | 361 | printf("\t.LBreak_%d:\n", seq); 362 | LabelStack.pop(); 363 | } 364 | 365 | 366 | void CodeGen::VisitorUnaryExprNode(UnaryExpr *node) { 367 | switch (node->Uop) { 368 | case UnaryOperator::Plus: { 369 | node->Lhs->Accept(this); 370 | break; 371 | } 372 | case UnaryOperator::Minus: { 373 | node->Lhs->Accept(this); 374 | printf("\tneg %%rax\n"); 375 | break; 376 | } 377 | case UnaryOperator::Star: { 378 | GenAddr(node); 379 | Load(node->Ty); 380 | break; 381 | } 382 | case UnaryOperator::Amp: { 383 | GenAddr(node->Lhs.get()); 384 | break; 385 | } 386 | default: 387 | break; 388 | } 389 | } 390 | 391 | void CodeGen::GenAddr(AstNode *node) { 392 | 393 | if (auto varNode = dynamic_cast(node)) { 394 | printf("\tlea %d(%%rbp), %%rax\n", varNode->Sym->Offset); 395 | } 396 | else if (auto unaryNode = dynamic_cast(node)) { 397 | if (unaryNode->Uop == UnaryOperator::Star) { 398 | unaryNode->Lhs->Accept(this); 399 | }else { 400 | GenDiag(node->Tok->Location,"unaryNode must be dereference operation"); 401 | } 402 | }else if (auto memberAccessNode = dynamic_cast(node)) { 403 | GenAddr(memberAccessNode->Lhs.get()); 404 | printf("\tadd $%d, %%rax\n", memberAccessNode->Fld->Offset); 405 | } 406 | ///GenDiag(sym->Loc, "not a lvalue"); 407 | } 408 | 409 | void CodeGen::VisitorSizeOfExprNode(SizeOfExpr *node) { 410 | printf("\tmov $%d, %%rax\n", node->Ty->Size); 411 | } 412 | 413 | void CodeGen::Load(std::shared_ptr ty) { 414 | if (ty->IsArrayTy() || ty->IsRecordTy()) { 415 | return; 416 | } 417 | if (ty->Size == 1) { 418 | printf("\tmovsbq (%%rax), %%rax\n"); 419 | }else if (ty->Size == 2) { 420 | printf("\tmovswq (%%rax), %%rax\n"); 421 | }else if (ty->Size == 4) { 422 | printf("\tmovslq (%%rax), %%rax\n"); 423 | }else { 424 | printf("\tmov (%%rax), %%rax\n"); 425 | } 426 | } 427 | 428 | void CodeGen::Store(std::shared_ptr ty) { 429 | Pop("%rdi"); 430 | if (ty->Size == 1) { 431 | printf("\tmov %%al, (%%rdi)\n"); 432 | }else if (ty->Size == 2) { 433 | printf("\tmov %%ax, (%%rdi)\n"); 434 | }else if (ty->Size == 4) { 435 | printf("\tmov %%eax, (%%rdi)\n"); 436 | }else if (ty->Size == 8){ 437 | printf("\tmov %%rax, (%%rdi)\n"); 438 | }else { 439 | printf("size = %d\n", ty->Size); 440 | assert(0); 441 | } 442 | } 443 | 444 | -------------------------------------------------------------------------------- /src/Gen/CodeGen.h: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: Gen.h 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/3 9 | ***********************************/ 10 | 11 | #ifndef CCC_CODEGEN_H 12 | #define CCC_CODEGEN_H 13 | 14 | #include "AstVisitor.h" 15 | #include 16 | #include "Type.h" 17 | #include "SymbolTable.h" 18 | #include 19 | 20 | namespace CCC { 21 | class CodeGen : public AstVisitor 22 | { 23 | private: 24 | int StackLevel{0}; 25 | int Sequence{0}; 26 | const char *Reg8[6] = {"%dil", "%sil", "%dl", "%cl", "%r8b", "%r9b"}; 27 | const char *Reg16[6] = {"%di", "%si", "%dx", "%cx", "%r8w", "%r9w"}; 28 | const char *Reg32[6] = {"%edi", "%esi", "%edx", "%ecx", "%r8d", "%r9d"}; 29 | const char *Reg64[6] = {"%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9"}; 30 | std::string CurrentFuncName; 31 | std::stack LabelStack; 32 | public: 33 | CodeGen() {} 34 | 35 | void VisitorTranslationUnitNode(TranslationUnit *node) override; 36 | 37 | private: 38 | void VisitorFunctionNode(Function *node) override; 39 | void VisitorDeclarationNode(Declaration *node) override; 40 | 41 | void VisitorExprStmtNode(ExprStmtNode *node) override; 42 | void VisitorIfStmtNode(IfStmtNode *node) override; 43 | void VisitorWhileStmtNode(WhileStmtNode *node) override; 44 | void VisitorDoWhileStmtNode(DoWhileStmtNode *node) override; 45 | void VisitorForStmtNode(ForStmtNode *node) override; 46 | void VisitorBlockStmtNode(BlockStmtNode *node) override; 47 | void VisitorReturnStmtNode(ReturnStmtNode *node) override; 48 | void VisitorBreakStmtNode(BreakStmtNode *node) override; 49 | void VisitorContinueStmtNode(ContinueStmtNode *node) override; 50 | void VisitorGotoStmtNode(GotoStmtNode *node) override; 51 | void VisitorLabelStmtNode(LabelStmtNode *node) override; 52 | void VisitorCaseStmtNode(CaseStmtNode *node) override; 53 | void VisitorDefaultStmtNode(DefaultStmtNode *node) override; 54 | void VisitorSwitchStmtNode(SwitchStmtNode *node) override; 55 | 56 | void VisitorAssignExprNode(AssignExpr *node) override; 57 | void VisitorSizeOfExprNode(SizeOfExpr *node) override; 58 | void VisitorBinaryExprNode(BinaryExpr *node) override; 59 | void VisitorUnaryExprNode(UnaryExpr *node) override; 60 | void VisitorNumExprNode(NumExpr *node) override; 61 | void VisitorVarExprNode(VarExpr *node) override; 62 | void VisitorFuncCallExprNode(FuncCallExpr *node) override; 63 | void VisitorStmtExprNode(StmtExpr *node) override; 64 | void VisitorMemberExprNode(MemberExpr *node) override; 65 | 66 | 67 | void Push(); 68 | void Pop(const char *reg); 69 | 70 | void GenAddr(AstNode *node); 71 | void Load(std::shared_ptr ty); 72 | void Store(std::shared_ptr ty); 73 | 74 | 75 | }; 76 | } 77 | 78 | #endif // CCC_CODEGEN_H 79 | -------------------------------------------------------------------------------- /src/Lex/Lexer.cpp: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: Lexer.cpp.cc 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/3 9 | ***********************************/ 10 | 11 | #include "Lexer.h" 12 | #include "Basic/Diag.h" 13 | #include 14 | #include 15 | #include 16 | #include "ReserveWord.cpp" 17 | 18 | using namespace CCC; 19 | 20 | void Lexer::GetNextChar() { 21 | if (Cursor == SourceCode.size()) { 22 | CurChar = '\0'; 23 | Cursor++; 24 | }else { 25 | CurChar = SourceCode[Cursor++]; 26 | } 27 | } 28 | 29 | void Lexer::GetNextToken() { 30 | /// 1. skip write space 31 | SkipWhiteSpace(); 32 | 33 | SourceLocation Location; 34 | Location.Line = Line; 35 | Location.Col = Cursor-1-LineHead; 36 | Location.LineHead = LineHead; 37 | Location.FilePath = CurrentFilePath; 38 | Location.Code = SourceCode; 39 | 40 | TokenKind kind; 41 | int value = 0; 42 | int startPos = Cursor - 1; 43 | if (CurChar == '\0') 44 | { 45 | kind = TokenKind::Eof; 46 | } 47 | else if (CurChar == '+'){ 48 | kind = TokenKind::Plus; 49 | GetNextChar(); 50 | } 51 | else if (CurChar == '-') { 52 | if (PeekChar(1) == '>') { 53 | GetNextChar(); 54 | kind = TokenKind::Arrow; 55 | }else { 56 | kind = TokenKind::Minus; 57 | } 58 | GetNextChar(); 59 | } 60 | else if (CurChar == '*') { 61 | kind = TokenKind::Star; 62 | GetNextChar(); 63 | } 64 | else if (CurChar == '/') { 65 | kind = TokenKind::Slash; 66 | GetNextChar(); 67 | } 68 | else if (CurChar == '&') { 69 | kind = TokenKind::Amp; 70 | GetNextChar(); 71 | } 72 | else if (CurChar == '(') { 73 | kind = TokenKind::LParen; 74 | GetNextChar(); 75 | } 76 | else if (CurChar == ')') { 77 | kind = TokenKind::RParen; 78 | GetNextChar(); 79 | } 80 | else if (CurChar == '[') { 81 | kind = TokenKind::LBracket; 82 | GetNextChar(); 83 | } 84 | else if (CurChar == ']') { 85 | kind = TokenKind::RBracket; 86 | GetNextChar(); 87 | } 88 | else if (CurChar == '{') { 89 | kind = TokenKind::LBrace; 90 | GetNextChar(); 91 | } 92 | else if (CurChar == '}') { 93 | kind = TokenKind::RBrace; 94 | GetNextChar(); 95 | } 96 | else if (CurChar == ';') { 97 | kind = TokenKind::Semicolon; 98 | GetNextChar(); 99 | } 100 | else if (CurChar == ':') { 101 | kind = TokenKind::Colon; 102 | GetNextChar(); 103 | } 104 | else if (CurChar == ',') { 105 | kind = TokenKind::Comma; 106 | GetNextChar(); 107 | } 108 | else if (CurChar == '.') { 109 | if (PeekChar(1) == '.' && PeekChar(2) == '.') { 110 | GetNextChar(); 111 | GetNextChar(); 112 | kind = TokenKind::Ellipsis; 113 | }else { 114 | kind = TokenKind::Period; 115 | } 116 | GetNextChar(); 117 | } 118 | else if (CurChar == '=') { 119 | if (PeekChar(1) == '=') { 120 | GetNextChar(); 121 | kind = TokenKind::Equal; 122 | }else { 123 | kind = TokenKind::Assign; 124 | } 125 | GetNextChar(); 126 | } 127 | else if (CurChar == '!') { 128 | if (PeekChar(1) == '=') { 129 | GetNextChar(); 130 | kind = TokenKind::PipeEqual; 131 | }else { 132 | LexDiag(Location, "current '%c' is illegal", CurChar); 133 | } 134 | GetNextChar(); 135 | } 136 | else if (CurChar == '>') { 137 | if (PeekChar(1) == '=') { 138 | GetNextChar(); 139 | kind = TokenKind::GreaterEqual; 140 | }else { 141 | kind = TokenKind::Greater; 142 | } 143 | GetNextChar(); 144 | } 145 | else if (CurChar == '<') { 146 | if (PeekChar(1) == '=') { 147 | GetNextChar(); 148 | kind = TokenKind::LesserEqual; 149 | }else { 150 | kind = TokenKind::Lesser; 151 | } 152 | GetNextChar(); 153 | } 154 | else if (isdigit(CurChar)) { 155 | kind = TokenKind::Num; 156 | value = 0; 157 | do { 158 | value = value * 10 + CurChar - '0'; 159 | GetNextChar(); 160 | } while (isdigit(CurChar)); 161 | }else { 162 | if (IsLetter()) { 163 | while (IsLetterOrDigit()) { 164 | GetNextChar(); 165 | } 166 | kind = TokenKind::Id; 167 | std::string_view content = SourceCode.substr(startPos, Cursor-1-startPos); 168 | if (NameToTokenKindMap.find(content) != NameToTokenKindMap.end()) { 169 | kind = NameToTokenKindMap[content]; 170 | } 171 | }else { 172 | LexDiag(Location, "current '%c' is illegal", CurChar); 173 | } 174 | } 175 | CurrentToken = std::make_shared(); 176 | CurrentToken->Kind = kind; 177 | CurrentToken->Value = value; 178 | CurrentToken->Location = Location; 179 | CurrentToken->Content = SourceCode.substr(startPos, Cursor-1-startPos); 180 | } 181 | 182 | bool Lexer::IsLetter() 183 | { 184 | return (CurChar >= 'a' && CurChar <= 'z') || (CurChar >= 'A' && CurChar <= 'Z') || (CurChar == '_'); 185 | } 186 | 187 | bool Lexer::IsDigit() 188 | { 189 | return CurChar >= '0' && CurChar <= '9'; 190 | } 191 | 192 | bool Lexer::IsLetterOrDigit() 193 | { 194 | return IsLetter() || IsDigit(); 195 | } 196 | 197 | void Lexer::ExpectToken(TokenKind kind) 198 | { 199 | if (CurrentToken->Kind == kind) { 200 | GetNextToken(); 201 | }else { 202 | LexDiag(CurrentToken->Location, "'%s' expected", GetTokenSimpleSpelling(kind)); 203 | } 204 | } 205 | 206 | void Lexer::SkipToken(TokenKind kind) 207 | { 208 | if (CurrentToken->Kind == kind) { 209 | GetNextToken(); 210 | }else { 211 | LexDiag(CurrentToken->Location, "'%s' skipped", GetTokenSimpleSpelling(kind)); 212 | } 213 | } 214 | 215 | bool Lexer::Match(TokenKind kind) { 216 | return CurrentToken->Kind == kind; 217 | } 218 | 219 | const char *Lexer::GetTokenSimpleSpelling(TokenKind kind){ 220 | if (kind == TokenKind::Eof) 221 | return "eof"; 222 | if (TokenKindToNameMap.find(kind) != TokenKindToNameMap.end()) { 223 | return TokenKindToNameMap[kind].data(); 224 | } 225 | return nullptr; 226 | } 227 | 228 | char Lexer::PeekChar(int distance) 229 | { 230 | assert(distance>=0); 231 | if (Cursor - 1 + distance < SourceCode.size()) { 232 | return SourceCode[Cursor-1+distance]; 233 | }else { 234 | return '\0'; 235 | } 236 | } 237 | 238 | 239 | void Lexer::BeginPeekToken() { 240 | PeekPt.CurChar = CurChar; 241 | PeekPt.Cursor = Cursor; 242 | PeekPt.Line = Line; 243 | PeekPt.LineHead = LineHead; 244 | PeekPt.CurrentToken = CurrentToken; 245 | } 246 | 247 | void Lexer::EndPeekToken() { 248 | CurChar = PeekPt.CurChar; 249 | Cursor = PeekPt.Cursor; 250 | Line = PeekPt.Line; 251 | LineHead = PeekPt.LineHead; 252 | CurrentToken = PeekPt.CurrentToken; 253 | } 254 | 255 | void Lexer::SkipWhiteSpace() { 256 | while (isspace(CurChar) 257 | || (CurChar == '/' && PeekChar(1) == '/') 258 | || (CurChar == '/' && PeekChar(1) == '*')) { 259 | if (CurChar == '/') { 260 | SkipComment(); 261 | continue; 262 | }else if (CurChar == '\n') { 263 | Line++; 264 | LineHead = Cursor; 265 | } 266 | GetNextChar(); 267 | } 268 | } 269 | 270 | void Lexer::SkipComment() { 271 | if (CurChar == '/' && PeekChar(1) == '/') { 272 | while (CurChar != '\n') 273 | GetNextChar(); 274 | }else { 275 | auto pos = SourceCode.find("*/", Cursor+1); 276 | if (pos == std::string_view::npos) { 277 | LexDiag(GetLocation(), "unclosed \"*/\""); 278 | assert(0); 279 | }else { 280 | CurChar = PeekChar((pos + 2) - (Cursor - 1)); 281 | Cursor = pos + 3; 282 | } 283 | } 284 | } 285 | 286 | SourceLocation Lexer::GetLocation() { 287 | SourceLocation Location; 288 | Location.Line = Line; 289 | Location.Col = Cursor-1-LineHead; 290 | Location.LineHead = LineHead; 291 | Location.FilePath = CurrentFilePath; 292 | Location.Code = SourceCode; 293 | return Location; 294 | } 295 | -------------------------------------------------------------------------------- /src/Lex/Lexer.h: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: Lexer.h 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/3 9 | ***********************************/ 10 | 11 | #ifndef CCC_LEXER_H 12 | #define CCC_LEXER_H 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace CCC 21 | { 22 | enum class TokenKind 23 | { 24 | Id, 25 | 26 | If, Else, While, Do, For, Return, 27 | Auto, Static, Extern, Typedef, Register, 28 | Void, Bool, Char, Short, Int, Long, 29 | Float, Double, Signed, UnSigned, 30 | Const, Restrict, Volatile, 31 | SizeOf, Struct, Union, Enum, Break, Continue, 32 | Goto, Switch, Case, Default, 33 | 34 | Plus, Minus, Star, Slash, LParen, 35 | RParen, LBracket, RBracket, LBrace, RBrace, 36 | Semicolon, Assign, Comma, Amp, Equal, 37 | PipeEqual, Greater, GreaterEqual, Lesser, 38 | LesserEqual, Period, Arrow, Ellipsis, LongLong, Colon, 39 | 40 | Num, 41 | Eof 42 | }; 43 | 44 | struct SourceLocation 45 | { 46 | const char *FilePath; 47 | std::string_view Code; 48 | int LineHead; 49 | int Line; 50 | int Col; 51 | }; 52 | 53 | class Token 54 | { 55 | public: 56 | TokenKind Kind; 57 | int Value; 58 | SourceLocation Location; 59 | std::string_view Content; 60 | }; 61 | 62 | class PeekPoint 63 | { 64 | public: 65 | char CurChar; 66 | int Cursor; 67 | int Line; 68 | int LineHead; 69 | std::shared_ptr CurrentToken; 70 | }; 71 | 72 | class Lexer 73 | { 74 | private: 75 | char CurChar{' '}; 76 | int Cursor{0}; 77 | int Line{0}; 78 | int LineHead{0}; 79 | PeekPoint PeekPt; 80 | std::string_view SourceCode; 81 | char *CodeBuf{nullptr}; 82 | const char *CurrentFilePath{nullptr}; 83 | public: 84 | std::shared_ptr CurrentToken; 85 | public: 86 | Lexer(const char *filePath){ 87 | CurrentFilePath = filePath; 88 | FILE *fp = fopen(filePath, "r"); 89 | if (fp) { 90 | fseek(fp, 0, SEEK_END); 91 | long fileSize = ftell(fp); 92 | CodeBuf = (char *)malloc(fileSize + 1); 93 | CodeBuf[fileSize] = '\0'; 94 | fseek(fp, 0, SEEK_SET); 95 | fread(CodeBuf, fileSize, 1, fp); 96 | fclose(fp); 97 | }else { 98 | printf("%s open failed\n", filePath); 99 | assert(0); 100 | } 101 | SourceCode = CodeBuf; 102 | } 103 | void GetNextToken(); 104 | void GetNextChar(); 105 | void ExpectToken(TokenKind kind); 106 | void SkipToken(TokenKind kind); 107 | bool Match(TokenKind kind); 108 | 109 | void BeginPeekToken(); 110 | void EndPeekToken(); 111 | 112 | private: 113 | bool IsLetter(); 114 | bool IsDigit(); 115 | bool IsLetterOrDigit(); 116 | 117 | char PeekChar(int distance); 118 | 119 | void SkipWhiteSpace(); 120 | void SkipComment(); 121 | 122 | SourceLocation GetLocation(); 123 | 124 | const char *GetTokenSimpleSpelling(TokenKind kind); 125 | }; 126 | } 127 | 128 | #endif // CCC_LEXER_H 129 | -------------------------------------------------------------------------------- /src/Lex/ReserveWord.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Lexer.h" 4 | 5 | namespace CCC { 6 | static std::unordered_map NameToTokenKindMap = { 7 | {"auto" , TokenKind::Auto}, 8 | {"register" , TokenKind::Register}, 9 | {"static" , TokenKind::Static}, 10 | {"extern" , TokenKind::Extern}, 11 | {"typedef" , TokenKind::Typedef}, 12 | {"void" , TokenKind::Void}, 13 | {"_Bool" , TokenKind::Bool}, 14 | {"char" , TokenKind::Char}, 15 | {"short" , TokenKind::Short}, 16 | {"int" , TokenKind::Int}, 17 | {"long" , TokenKind::Long}, 18 | {"float" , TokenKind::Float}, 19 | {"double" , TokenKind::Double}, 20 | {"signed" , TokenKind::Signed}, 21 | {"unsigned" , TokenKind::UnSigned}, 22 | {"struct", TokenKind::Struct}, 23 | {"union", TokenKind::Union}, 24 | {"enum", TokenKind::Enum}, 25 | {"const" , TokenKind::Const}, 26 | {"restrict" , TokenKind::Restrict}, 27 | {"volatile" , TokenKind::Volatile}, 28 | {"if" , TokenKind::If}, 29 | {"else" , TokenKind::Else}, 30 | {"return" , TokenKind::Return}, 31 | {"while" , TokenKind::While}, 32 | {"do" , TokenKind::Do}, 33 | {"for" , TokenKind::For}, 34 | {"sizeof", TokenKind::SizeOf}, 35 | {"break", TokenKind::Break}, 36 | {"continue", TokenKind::Continue}, 37 | {"goto" , TokenKind::Goto }, 38 | {"switch" , TokenKind::Switch }, 39 | {"case" , TokenKind::Case }, 40 | {"default" , TokenKind::Default }, 41 | 42 | {"+", TokenKind::Plus}, 43 | {"-", TokenKind::Minus}, 44 | {"*", TokenKind::Star}, 45 | {"/", TokenKind::Slash}, 46 | {"(", TokenKind::LParen}, 47 | {")", TokenKind::RParen}, 48 | {"[", TokenKind::LBracket}, 49 | {"]", TokenKind::RBracket}, 50 | {"{", TokenKind::LBrace}, 51 | {"}", TokenKind::RBrace}, 52 | {";", TokenKind::Semicolon}, 53 | {"=",TokenKind::Assign}, 54 | {",",TokenKind::Comma}, 55 | {"&",TokenKind::Amp}, 56 | {"==",TokenKind::Equal}, 57 | {"!=",TokenKind::PipeEqual}, 58 | {">",TokenKind::Greater}, 59 | {">=",TokenKind::GreaterEqual}, 60 | {"<",TokenKind::Lesser}, 61 | {"<=",TokenKind::LesserEqual}, 62 | {".",TokenKind::Period}, 63 | {"->",TokenKind::Arrow}, 64 | {"...",TokenKind::Ellipsis}, 65 | {":",TokenKind::Colon} 66 | }; 67 | 68 | 69 | static std::unordered_map TokenKindToNameMap = { 70 | {TokenKind::Auto, "auto"}, 71 | {TokenKind::Register, "register"}, 72 | {TokenKind::Static, "static"}, 73 | {TokenKind::Extern, "extern"}, 74 | {TokenKind::Typedef, "typedef"}, 75 | {TokenKind::Void, "void"}, 76 | {TokenKind::Bool, "_Bool"}, 77 | {TokenKind::Char, "char"}, 78 | {TokenKind::Short, "short"}, 79 | {TokenKind::Int, "int"}, 80 | {TokenKind::Long, "long"}, 81 | {TokenKind::Float, "float"}, 82 | {TokenKind::Double, "double"}, 83 | {TokenKind::Signed, "signed"}, 84 | {TokenKind::UnSigned, "unsigned"}, 85 | {TokenKind::Struct, "struct"}, 86 | {TokenKind::Union, "union"}, 87 | {TokenKind::Enum, "enum"}, 88 | {TokenKind::Const, "const"}, 89 | {TokenKind::Restrict, "restrict"}, 90 | {TokenKind::Volatile, "volatile"}, 91 | {TokenKind::If, "if"}, 92 | {TokenKind::Else, "else"}, 93 | {TokenKind::Return, "return"}, 94 | {TokenKind::While, "while"}, 95 | {TokenKind::Do, "do"}, 96 | {TokenKind::For, "for"}, 97 | {TokenKind::SizeOf, "sizeof"}, 98 | {TokenKind::Break, "break"}, 99 | {TokenKind::Continue, "continue"}, 100 | {TokenKind::Goto ,"goto" }, 101 | {TokenKind::Switch ,"switch" }, 102 | {TokenKind::Case ,"case" }, 103 | { TokenKind::Default ,"default"}, 104 | 105 | {TokenKind::Plus, "+"}, 106 | {TokenKind::Minus, "-"}, 107 | {TokenKind::Star, "*"}, 108 | {TokenKind::Slash, "/"}, 109 | {TokenKind::LParen, "("}, 110 | {TokenKind::RParen, ")"}, 111 | {TokenKind::LBracket, "["}, 112 | {TokenKind::RBracket, "]"}, 113 | {TokenKind::LBrace, "{"}, 114 | {TokenKind::RBrace, "}"}, 115 | {TokenKind::Semicolon, ";"}, 116 | {TokenKind::Assign, "="}, 117 | {TokenKind::Comma, ","}, 118 | {TokenKind::Amp, "&"}, 119 | {TokenKind::Equal, "=="}, 120 | {TokenKind::PipeEqual, "!="}, 121 | {TokenKind::Greater, ">"}, 122 | {TokenKind::GreaterEqual, ">="}, 123 | {TokenKind::Lesser, " <"}, 124 | {TokenKind::LesserEqual, "<="}, 125 | {TokenKind::Period, "."}, 126 | {TokenKind::Arrow, "->"}, 127 | {TokenKind::Ellipsis, "..."} , 128 | {TokenKind::Colon, ":"} 129 | }; 130 | } -------------------------------------------------------------------------------- /src/Parse/Decl.cpp: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: Decl.cpp.cc 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/30 9 | ***********************************/ 10 | 11 | #include "Decl.h" 12 | #include "Parser.h" 13 | 14 | namespace CCC 15 | { 16 | /** 17 | translation-unit: 18 | external-declaration 19 | translation-unit external-declaration 20 | 21 | external-declaration: 22 | function-definition 23 | declaration 24 | */ 25 | std::shared_ptr Parser::ParseTranslationUnit() 26 | { 27 | auto node = std::make_shared(Lex.CurrentToken); 28 | while (!Lex.Match(TokenKind::Eof)) { 29 | node->ExtDecl.push_back(ParseExternalDeclaration()); 30 | } 31 | return node; 32 | } 33 | 34 | /** 35 | declaration: 36 | declaration-specifiers init-declarator-list? ; 37 | 38 | function-definition: 39 | declaration-specifiers declarator declaration-list? compound-statement 40 | */ 41 | std::shared_ptr Parser::ParseExternalDeclaration() 42 | { 43 | auto decl = ParseCommonHeader(); 44 | 45 | auto OnlyOneDec = [&decl]()->bool { 46 | return decl->DecList.size() == 1 && decl->DecList.front()->Init == nullptr; 47 | }; 48 | 49 | if (OnlyOneDec()) 50 | { 51 | std::string_view funcName; 52 | bool isFunc = IsFunctionDeclaration(decl->DecList.front()->Dec, funcName); 53 | if(isFunc) { 54 | 55 | /// function declaration 56 | /// void (*a())(int); 57 | if (Lex.Match(TokenKind::Semicolon)) { 58 | decl->IsLocalDecl = false; 59 | Lex.SkipToken(TokenKind::Semicolon); 60 | return decl; 61 | } 62 | 63 | /// function definition 64 | /// void (*a())(int) {} 65 | auto funcNode = std::make_shared(Lex.CurrentToken); 66 | funcNode->FuncName = funcName; 67 | funcNode->Spec = decl->Spec; 68 | funcNode->Dec = decl->DecList.front()->Dec; 69 | funcNode->BlockStmt = ParseBlockStmt(); 70 | return funcNode; 71 | } 72 | } 73 | 74 | /// global declaration 75 | Lex.ExpectToken(TokenKind::Semicolon); 76 | decl->IsLocalDecl = false; 77 | return decl; 78 | } 79 | 80 | /** 81 | /// common header ? 82 | declaration-specifiers init-declarator-list? 83 | 84 | init-declarator-list: 85 | init-declarator 86 | init-declarator-list , init-declarator 87 | */ 88 | std::shared_ptr Parser::ParseCommonHeader() { 89 | auto node = std::make_shared(Lex.CurrentToken); 90 | node->Spec = ParseDeclSpecifier(); 91 | if (!Lex.Match(TokenKind::Semicolon)) { 92 | node->DecList.push_back(ParseInitDeclarator()); 93 | while (Lex.CurrentToken->Kind == TokenKind::Comma) { 94 | Lex.SkipToken(TokenKind::Comma); 95 | node->DecList.push_back(ParseInitDeclarator()); 96 | } 97 | } 98 | return node; 99 | } 100 | 101 | /** 102 | declaration: 103 | declaration-specifiers init-declarator-list? ; 104 | */ 105 | std::shared_ptr Parser::ParseDeclaration() 106 | { 107 | auto node = ParseCommonHeader(); 108 | Lex.ExpectToken(TokenKind::Semicolon); 109 | return node; 110 | } 111 | 112 | /** 113 | storage-class-specifier: 114 | typedef extern static auto register 115 | 116 | type-specifier: 117 | void char short int long 118 | float double signed unsigned _Bool 119 | _Complex 120 | struct-or-union-specifier 121 | enum-specifier 122 | typedef-name 123 | 124 | type-qualifier: 125 | const restrict volatile 126 | 127 | declaration-specifiers: 128 | storage-class-specifier declaration-specifiers? 129 | type-specifier declaration-specifiers? 130 | type-qualifier declaration-specifiers? 131 | function-specifier declaration-specifiers? 132 | */ 133 | 134 | std::shared_ptr Parser::ParseDeclSpecifier() 135 | { 136 | auto node = std::make_shared(Lex.CurrentToken); 137 | while (true) { 138 | switch (Lex.CurrentToken->Kind) { 139 | case TokenKind::Auto: 140 | case TokenKind::Static: 141 | case TokenKind::Extern: 142 | case TokenKind::Typedef: 143 | case TokenKind::Register: { 144 | auto astTok = std::make_shared(Lex.CurrentToken); 145 | node->StorageClsList.push_back(astTok); 146 | Lex.GetNextToken(); 147 | break; 148 | } 149 | case TokenKind::Const: 150 | case TokenKind::Volatile: 151 | case TokenKind::Restrict: { 152 | auto astTok = std::make_shared(Lex.CurrentToken); 153 | node->TyQualifyList.push_back(astTok); 154 | Lex.GetNextToken(); 155 | break; 156 | } 157 | case TokenKind::Void: 158 | case TokenKind::Bool: 159 | case TokenKind::Char: 160 | case TokenKind::Short: 161 | case TokenKind::Int: 162 | case TokenKind::Long: 163 | case TokenKind::Float: 164 | case TokenKind::Double: 165 | case TokenKind::Signed: 166 | case TokenKind::UnSigned:{ 167 | auto astTok = std::make_shared(Lex.CurrentToken); 168 | node->TySpecList.push_back(astTok); 169 | Lex.GetNextToken(); 170 | break; 171 | } 172 | case TokenKind::Struct: 173 | case TokenKind::Union: { 174 | node->TySpecList.push_back(ParseStructOrUnionSpecifier()); 175 | break; 176 | } 177 | case TokenKind::Enum: { 178 | node->TySpecList.push_back(ParseEnumSpecifier()); 179 | break; 180 | } 181 | default: 182 | return node; 183 | } 184 | } 185 | } 186 | 187 | /** 188 | init-declarator: 189 | declarator 190 | declarator = initializer 191 | */ 192 | std::shared_ptr Parser::ParseInitDeclarator() { 193 | auto node = std::make_shared(Lex.CurrentToken); 194 | node->Dec = ParseDeclarator(); 195 | node->Id = node->Dec->Id; 196 | if (Lex.Match(TokenKind::Assign)) { 197 | Lex.SkipToken(TokenKind::Assign); 198 | node->Init = ParseInitializer(); 199 | } 200 | return node; 201 | } 202 | 203 | /** 204 | declarator: 205 | pointer? direct-declarator 206 | 207 | 208 | type-qualifier-list: 209 | type-qualifier 210 | type-qualifier-list type-qualifier 211 | */ 212 | 213 | std::shared_ptr Parser::ParseDeclarator() 214 | { 215 | std::shared_ptr dec = ParsePointerDeclarator(); 216 | if (!dec) { 217 | return ParseDirectDeclarator(); 218 | } 219 | 220 | auto p = dec; 221 | while (p && p->Dec) { 222 | p = p->Dec; 223 | } 224 | p->Dec = ParseDirectDeclarator(); 225 | p->Id = p->Dec->Id; 226 | 227 | return dec; 228 | } 229 | 230 | /** 231 | pointer: 232 | * type-qualifier-list? 233 | * type-qualifier-list? pointer 234 | */ 235 | std::shared_ptr Parser::ParsePointerDeclarator() 236 | { 237 | if (Lex.CurrentToken->Kind == TokenKind::Star) { 238 | auto node = std::make_shared(Lex.CurrentToken); 239 | Lex.SkipToken(TokenKind::Star); 240 | node->Dec = ParsePointerDeclarator(); 241 | return node; 242 | } 243 | return nullptr; 244 | } 245 | 246 | /** 247 | direct-declarator: 248 | identifier 249 | ( declarator ) 250 | direct-declarator [ type-qualifier-list? assignment-expression? ] 251 | direct-declarator [ static type-qualifier-list? assignment-expression ] 252 | direct-declarator [ type-qualifier-list static assignment-expression ] 253 | direct-declarator [ type-qualifier-list? * ] 254 | direct-declarator ( parameter-type-list ) 255 | direct-declarator ( identifier-list? ) 256 | 257 | */ 258 | std::shared_ptr Parser::ParseDirectDeclarator() 259 | { 260 | std::shared_ptr dec; 261 | 262 | if (Lex.Match(TokenKind::LParen)) { 263 | Lex.SkipToken(TokenKind::LParen); 264 | dec = ParseDeclarator(); 265 | Lex.ExpectToken(TokenKind::RParen); 266 | }else { 267 | if (!Lex.Match(TokenKind::Id)) { 268 | ParseDiag(Lex.CurrentToken->Location, "expected a identifier"); 269 | } 270 | dec = std::make_shared(Lex.CurrentToken); 271 | dec->Id = Lex.CurrentToken->Content; 272 | Lex.SkipToken(TokenKind::Id); 273 | } 274 | 275 | while (true) 276 | { 277 | if (Lex.Match(TokenKind::LBracket)) 278 | { 279 | auto arrayDec = std::make_shared(Lex.CurrentToken); 280 | arrayDec->Dec = dec; 281 | arrayDec->Id = dec->Id; 282 | Lex.SkipToken(TokenKind::LBracket); 283 | if (Lex.CurrentToken->Kind != TokenKind::Num) { 284 | ParseDiag(Lex.CurrentToken->Location, "expected a num"); 285 | } 286 | // arrayDec->Expr = ParseConstantExpression(); 287 | arrayDec->ArrayLen = Lex.CurrentToken->Value; 288 | Lex.SkipToken(TokenKind::Num); 289 | Lex.ExpectToken(TokenKind::RBracket); 290 | dec = arrayDec; 291 | } 292 | else if (Lex.Match(TokenKind::LParen)) 293 | { 294 | auto funcDec = std::make_shared(Lex.CurrentToken); 295 | funcDec->Dec = dec; 296 | funcDec->Id = dec->Id; 297 | Lex.SkipToken(TokenKind::LParen); 298 | funcDec->ParamTyLists = ParseParamTypeList(); 299 | Lex.ExpectToken(TokenKind::RParen); 300 | dec = funcDec; 301 | } 302 | else { 303 | break; 304 | } 305 | } 306 | return dec; 307 | } 308 | 309 | /** 310 | parameter-type-list: 311 | parameter-list 312 | parameter-list , ... 313 | 314 | parameter-list: 315 | parameter-declaration 316 | parameter-list , parameter-declaration 317 | */ 318 | std::shared_ptr Parser::ParseParamTypeList() 319 | { 320 | auto node = std::make_shared(Lex.CurrentToken); 321 | if (!Lex.Match(TokenKind::RParen)) { 322 | node->ParamDecl.push_back(ParseParamDeclaration()); 323 | } 324 | while (!Lex.Match(TokenKind::RParen)) { 325 | Lex.ExpectToken(TokenKind::Comma); 326 | if (Lex.CurrentToken->Kind == TokenKind::Ellipsis) { 327 | node->HaveEllipsis = true; 328 | break; 329 | } 330 | node->ParamDecl.push_back(ParseParamDeclaration()); 331 | } 332 | return node; 333 | } 334 | 335 | /** 336 | parameter-declaration: 337 | declaration-specifiers declarator 338 | declaration-specifiers abstract-declarator? 339 | */ 340 | std::shared_ptr Parser::ParseParamDeclaration() { 341 | auto node = std::make_shared(Lex.CurrentToken); 342 | node->Spec = ParseDeclSpecifier(); 343 | node->Dec = ParseDeclarator(); 344 | return node; 345 | } 346 | 347 | /** 348 | initializer: 349 | assignment-expression 350 | { initializer-list } 351 | { initializer-list , } 352 | 353 | initializer-list: 354 | designation? initializer 355 | initializer-list , designation? initializer 356 | 357 | designation: 358 | designator-list = 359 | 360 | designator-list: 361 | designator 362 | designator-list designator 363 | 364 | designator: 365 | [ constant-expression ] 366 | . identifier 367 | */ 368 | std::shared_ptr Parser::ParseInitializer() { 369 | auto node = std::make_shared(Lex.CurrentToken); 370 | /// 开头视野 371 | if (Lex.Match(TokenKind::LBrace)) { 372 | node->LBrace = true; 373 | Lex.SkipToken(TokenKind::LBrace); 374 | node->Initials = ParseInitializer(); 375 | auto tail = node->Initials; 376 | /// 内部视野 377 | while (Lex.Match(TokenKind::Comma)) { 378 | Lex.SkipToken(TokenKind::Comma); 379 | if (Lex.Match(TokenKind::RBrace)) { 380 | break; 381 | } 382 | tail->Next = ParseInitializer(); 383 | tail = tail->Next; 384 | } 385 | Lex.ExpectToken(TokenKind::RBrace); 386 | }else { 387 | node->LBrace = false; 388 | node->Expr = ParseAssignExpr(); 389 | } 390 | return node; 391 | } 392 | 393 | 394 | /** 395 | struct-or-union-specifier: 396 | struct-or-union identifier? { struct-declaration-list } 397 | struct-or-union identifier 398 | 399 | struct-or-union: 400 | struct union 401 | 402 | struct-declaration-list: 403 | struct-declaration 404 | struct-declaration-list struct-declaration 405 | */ 406 | std::shared_ptr Parser::ParseStructOrUnionSpecifier() 407 | { 408 | DeclClass cls = DeclClass::StructSpecifier; 409 | if (Lex.Match(TokenKind::Union)) { 410 | cls = DeclClass::UnionSpecifier; 411 | } 412 | auto node = std::make_shared(Lex.CurrentToken); 413 | node->Cls = cls; 414 | Lex.GetNextToken(); 415 | 416 | if (Lex.Match(TokenKind::Id)) { 417 | node->Id = Lex.CurrentToken->Content; 418 | Lex.SkipToken(TokenKind::Id); 419 | } 420 | 421 | if (!Lex.Match(TokenKind::LBrace)) { 422 | return node; 423 | } 424 | 425 | node->HasLBrace = true; 426 | Lex.ExpectToken(TokenKind::LBrace); 427 | while (!Lex.Match(TokenKind::RBrace)) { 428 | node->DeclList.push_back(ParseStructDeclaration()); 429 | } 430 | Lex.ExpectToken(TokenKind::RBrace); 431 | return node; 432 | } 433 | 434 | /** 435 | struct-declaration: 436 | specifier-qualifier-list struct-declarator-list ; 437 | 438 | specifier-qualifier-list: 439 | type-specifier specifier-qualifier-list? 440 | type-qualifier specifier-qualifier-list? 441 | 442 | struct-declarator-list: 443 | struct-declarator 444 | struct-declarator-list , struct-declarator 445 | */ 446 | std::shared_ptr Parser::ParseStructDeclaration() 447 | { 448 | auto node = std::make_shared(Lex.CurrentToken); 449 | node->Spec = ParseDeclSpecifier(); 450 | node->DecList.push_back(ParseStructDeclarator()); 451 | while (Lex.Match(TokenKind::Comma)) { 452 | Lex.SkipToken(TokenKind::Comma); 453 | node->DecList.push_back(ParseStructDeclarator()); 454 | } 455 | Lex.ExpectToken(TokenKind::Semicolon); 456 | return node; 457 | } 458 | 459 | /** 460 | struct-declarator: 461 | declarator 462 | declarator? : constant-expression 463 | */ 464 | std::shared_ptr Parser::ParseStructDeclarator() { 465 | auto node = std::make_shared(Lex.CurrentToken); 466 | node->Dec = ParseDeclarator(); 467 | return node; 468 | } 469 | 470 | /** 471 | enum-specifier: 472 | enum identifier? { enumerator-list } 473 | enum identifier? { enumerator-list , } 474 | enum identifier 475 | 476 | enumerator-list: 477 | enumerator 478 | enumerator-list , enumerator 479 | */ 480 | std::shared_ptr Parser::ParseEnumSpecifier() 481 | { 482 | auto node = std::make_shared(Lex.CurrentToken); 483 | Lex.SkipToken(TokenKind::Enum); 484 | 485 | if (Lex.Match(TokenKind::Id)) { 486 | Lex.SkipToken(TokenKind::Id); 487 | node->Id = Lex.CurrentToken->Content; 488 | } 489 | if (!Lex.Match(TokenKind::LBrace)) { 490 | return node; 491 | } 492 | Lex.ExpectToken(TokenKind::LBrace); 493 | node->DecList.push_back(ParseEnumDeclarator()); 494 | while (Lex.Match(TokenKind::Comma)) { 495 | Lex.SkipToken(TokenKind::Comma); 496 | if (Lex.Match(TokenKind::RBrace)) { 497 | break; 498 | } 499 | node->DecList.push_back(ParseEnumDeclarator()); 500 | } 501 | Lex.ExpectToken(TokenKind::RBrace); 502 | return node; 503 | } 504 | 505 | std::shared_ptr Parser::ParseEnumDeclarator() { 506 | auto node = std::make_shared(Lex.CurrentToken); 507 | if (!Lex.Match(TokenKind::Id)) { 508 | ParseDiag(Lex.CurrentToken->Location, "expected a identifier"); 509 | } 510 | node->Id = Lex.CurrentToken->Content; 511 | return node; 512 | } 513 | 514 | void DeclSpecToken::Accept(AstVisitor *visitor) { 515 | visitor->VisitorDeclSpecTokenNode(this); 516 | } 517 | 518 | void InitDeclarator::Accept(AstVisitor *visitor) { 519 | visitor->VisitorInitDeclaratorNode(this); 520 | } 521 | 522 | void DeclSpecifier::Accept(AstVisitor *visitor) { 523 | visitor->VisitorDeclSpecifierNode(this); 524 | } 525 | 526 | void Initializer::Accept(AstVisitor *visitor) { 527 | visitor->VisitorInitializerNode(this); 528 | } 529 | 530 | void ParamTypeList::Accept(AstVisitor *visitor) { 531 | visitor->VisitorParamTypeListNode(this); 532 | } 533 | 534 | void ParamDeclaration::Accept(AstVisitor *visitor) { 535 | visitor->VisitorParamDeclarationNode(this); 536 | } 537 | 538 | void NameDeclarator::Accept(AstVisitor *visitor) { 539 | visitor->VisitorNameDeclaratorNode(this); 540 | } 541 | 542 | void PointerDeclarator::Accept(AstVisitor *visitor) { 543 | visitor->VisitorPointerDeclaratorNode(this); 544 | } 545 | 546 | void ArrayDeclarator::Accept(AstVisitor *visitor) { 547 | visitor->VisitorArrayDeclaratorNode(this); 548 | } 549 | 550 | void FunctionDeclarator::Accept(AstVisitor *visitor) { 551 | visitor->VisitorFuncDeclaratorNode(this); 552 | } 553 | 554 | void StructSpecifier::Accept(AstVisitor *visitor) { 555 | visitor->VisitorStructSpecifierNode(this); 556 | } 557 | 558 | void StructDeclaration::Accept(AstVisitor *visitor) { 559 | visitor->VisitorStructDeclarationNode(this); 560 | } 561 | 562 | void StructDeclarator::Accept(AstVisitor *visitor) { 563 | visitor->VisitorStructDeclaratorNode(this); 564 | } 565 | 566 | void EnumSpecifier::Accept(AstVisitor *visitor) { 567 | visitor->VisitorEnumSpecifierNode(this); 568 | } 569 | 570 | void EnumDeclarator::Accept(AstVisitor *visitor) { 571 | visitor->VisitorEnumDeclaratorNode(this); 572 | } 573 | 574 | void Declaration::Accept(AstVisitor *visitor) { 575 | visitor->VisitorDeclarationNode(this); 576 | } 577 | 578 | void Function::Accept(AstVisitor *visitor) { 579 | visitor->VisitorFunctionNode(this); 580 | } 581 | 582 | void TranslationUnit::Accept(AstVisitor *visitor) { 583 | visitor->VisitorTranslationUnitNode(this); 584 | } 585 | } 586 | -------------------------------------------------------------------------------- /src/Parse/Decl.h: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: Decl.h 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/30 9 | ***********************************/ 10 | 11 | #ifndef CCC_SRC_DECL_H 12 | #define CCC_SRC_DECL_H 13 | 14 | #include "AstVisitor.h" 15 | #include "Symbol.h" 16 | #include 17 | #include 18 | 19 | namespace CCC { 20 | 21 | enum class DeclClass { 22 | TranslationUnit, 23 | Function, 24 | Declaration, 25 | DeclSpecifier, 26 | StructSpecifier, 27 | UnionSpecifier, 28 | StructDeclaration, 29 | StructDeclarator, 30 | EnumSpecifier, 31 | EnumDeclarator, 32 | DeclSpecToken, 33 | PointerDeclarator, 34 | NameDeclarator, 35 | FunctionDeclarator, 36 | ArrayDeclarator, 37 | InitDeclarator, 38 | Initializer, 39 | ParamTypeList, 40 | ParamDeclaration 41 | }; 42 | 43 | class DeclBase : public AstNode 44 | { 45 | public: 46 | virtual ~DeclBase() {} 47 | DeclClass Cls; 48 | std::shared_ptr Ty; 49 | DeclBase(std::shared_ptr tok) : AstNode(tok) {} 50 | virtual void Accept(AstVisitor *visitor) = 0; 51 | }; 52 | 53 | class DeclSpecToken : public DeclBase 54 | { 55 | public: 56 | DeclSpecToken(std::shared_ptr tok) : DeclBase(tok) { 57 | Cls = DeclClass::DeclSpecToken; 58 | } 59 | void Accept(AstVisitor *visitor) override; 60 | }; 61 | 62 | class DeclSpecifier : public DeclBase 63 | { 64 | public: 65 | std::list> StorageClsList; 66 | std::list> TyQualifyList; 67 | std::list> TySpecList; 68 | DeclSpecifier(std::shared_ptr tok) : DeclBase(tok) { 69 | Cls = DeclClass::DeclSpecifier; 70 | } 71 | void Accept(AstVisitor *visitor) override; 72 | 73 | public: 74 | /// sema 75 | StorageClass SClass; 76 | TypeQualifier TyQualify; 77 | std::string_view TagName; 78 | }; 79 | 80 | class Declarator : public DeclBase 81 | { 82 | public: 83 | std::string_view Id{}; 84 | std::shared_ptr Dec{nullptr}; 85 | Declarator(std::shared_ptr tok) : DeclBase(tok) {} 86 | virtual void Accept(AstVisitor *visitor) = 0; 87 | 88 | public: 89 | std::shared_ptr BaseTy; 90 | }; 91 | 92 | class PointerDeclarator : public Declarator 93 | { 94 | public: 95 | PointerDeclarator(std::shared_ptr tok) : Declarator(tok) { 96 | Cls = DeclClass::PointerDeclarator; 97 | } 98 | void Accept(AstVisitor *visitor) override; 99 | }; 100 | 101 | class NameDeclarator : public Declarator 102 | { 103 | public: 104 | NameDeclarator(std::shared_ptr tok) : Declarator(tok) { 105 | Cls = DeclClass::NameDeclarator; 106 | } 107 | void Accept(AstVisitor *visitor) override; 108 | }; 109 | 110 | class FunctionDeclarator : public Declarator 111 | { 112 | public: 113 | std::shared_ptr ParamTyLists; 114 | FunctionDeclarator(std::shared_ptr tok) : Declarator(tok) { 115 | Cls = DeclClass::FunctionDeclarator; 116 | } 117 | void Accept(AstVisitor *visitor) override; 118 | }; 119 | 120 | class ArrayDeclarator : public Declarator 121 | { 122 | public: 123 | // std::shared_ptr Expr; 124 | int ArrayLen{0}; 125 | ArrayDeclarator(std::shared_ptr tok) : Declarator(tok) { 126 | Cls = DeclClass::ArrayDeclarator; 127 | } 128 | void Accept(AstVisitor *visitor) override; 129 | }; 130 | 131 | class Initializer : public DeclBase 132 | { 133 | public: 134 | bool LBrace{false}; 135 | std::shared_ptr Initials{nullptr}; 136 | std::shared_ptr Expr{nullptr}; 137 | std::shared_ptr Next{nullptr}; 138 | Initializer(std::shared_ptr tok) : DeclBase(tok) { 139 | Cls = DeclClass::Initializer; 140 | } 141 | void Accept(AstVisitor *visitor) override; 142 | public: 143 | ///sema 144 | std::shared_ptr IData; 145 | }; 146 | 147 | class InitDeclarator : public DeclBase 148 | { 149 | public: 150 | std::shared_ptr Dec; 151 | std::shared_ptr Init{nullptr}; 152 | InitDeclarator(std::shared_ptr tok) : DeclBase(tok) { 153 | Cls = DeclClass::InitDeclarator; 154 | } 155 | void Accept(AstVisitor *visitor) override; 156 | 157 | public: 158 | /// sema 159 | std::shared_ptr BaseTy; 160 | std::string_view Id; 161 | std::shared_ptr Sym; 162 | }; 163 | 164 | 165 | /** 166 | struct-declarator: 167 | declarator 168 | declarator? : constant-expression 169 | */ 170 | class StructDeclarator : public DeclBase 171 | { 172 | public: 173 | std::shared_ptr Dec; 174 | StructDeclarator(std::shared_ptr tok) : DeclBase(tok) { 175 | Cls = DeclClass::StructDeclarator; 176 | } 177 | void Accept(AstVisitor *visitor) override; 178 | 179 | public: 180 | /// sema 181 | std::shared_ptr RecordTy; 182 | std::shared_ptr BaseTy; 183 | std::string_view Id; 184 | }; 185 | 186 | class StructDeclaration : public DeclBase 187 | { 188 | public: 189 | std::shared_ptr Spec; 190 | std::list> DecList; 191 | StructDeclaration(std::shared_ptr tok) : DeclBase(tok) { 192 | Cls = DeclClass::StructDeclaration; 193 | } 194 | void Accept(AstVisitor *visitor) override; 195 | 196 | public: 197 | /// sema 198 | std::shared_ptr RecordTy; 199 | }; 200 | 201 | class StructSpecifier : public DeclBase 202 | { 203 | public: 204 | std::string_view Id; 205 | bool HasLBrace{false}; 206 | std::list> DeclList; 207 | StructSpecifier(std::shared_ptr tok) : DeclBase(tok) { 208 | } 209 | void Accept(AstVisitor *visitor) override; 210 | }; 211 | 212 | class EnumDeclarator : public DeclBase 213 | { 214 | public: 215 | std::string_view Id; 216 | std::shared_ptr Expr; 217 | EnumDeclarator(std::shared_ptr tok) : DeclBase(tok) { 218 | Cls = DeclClass::EnumDeclarator; 219 | } 220 | void Accept(AstVisitor *visitor) override; 221 | }; 222 | 223 | class EnumSpecifier : public DeclBase 224 | { 225 | public: 226 | std::string_view Id; 227 | std::list> DecList; 228 | EnumSpecifier(std::shared_ptr tok) : DeclBase(tok) { 229 | Cls = DeclClass::EnumSpecifier; 230 | } 231 | void Accept(AstVisitor *visitor) override; 232 | }; 233 | 234 | class Declaration : public DeclBase 235 | { 236 | public: 237 | bool IsLocalDecl{true}; 238 | std::shared_ptr Spec; 239 | std::list> DecList; 240 | Declaration(std::shared_ptr tok) : DeclBase(tok) { 241 | Cls = DeclClass::Declaration; 242 | } 243 | void Accept(AstVisitor *visitor) override; 244 | }; 245 | 246 | class ParamDeclaration : public DeclBase 247 | { 248 | public: 249 | std::shared_ptr Spec; 250 | std::shared_ptr Dec; 251 | ParamDeclaration(std::shared_ptr tok) : DeclBase(tok) { 252 | Cls = DeclClass::ParamDeclaration; 253 | } 254 | void Accept(AstVisitor *visitor) override; 255 | 256 | public: 257 | /// sema 258 | std::shared_ptr FunTy; 259 | }; 260 | 261 | class ParamTypeList : public DeclBase 262 | { 263 | public: 264 | bool HaveEllipsis{false}; 265 | std::list> ParamDecl; 266 | ParamTypeList(std::shared_ptr tok) : DeclBase(tok) { 267 | Cls = DeclClass::ParamTypeList; 268 | } 269 | void Accept(AstVisitor *visitor) override; 270 | 271 | public: 272 | /// sema 273 | std::shared_ptr FunTy; 274 | }; 275 | 276 | struct Label 277 | { 278 | bool Defined{false}; 279 | std::string_view Id; 280 | Label(std::string_view id) : Id(id) {} 281 | }; 282 | 283 | class Symbol; 284 | class Function : public DeclBase 285 | { 286 | public: 287 | /// parse 288 | std::string_view FuncName; 289 | std::shared_ptr Spec; 290 | std::shared_ptr Dec; 291 | std::shared_ptr BlockStmt; 292 | 293 | Function(std::shared_ptr tok) : DeclBase(tok) { 294 | Cls = DeclClass::Function; 295 | } 296 | void Accept(AstVisitor *visitor) override; 297 | 298 | public: 299 | /// sema 300 | std::shared_ptr FSym; 301 | std::stack LoopStmts; 302 | std::stack Breakables; 303 | std::stack SwitchStmts; 304 | std::unordered_map> LabelsMap; 305 | }; 306 | 307 | class TranslationUnit : public DeclBase 308 | { 309 | public: 310 | std::list> ExtDecl; 311 | TranslationUnit(std::shared_ptr tok) : DeclBase(tok) { 312 | Cls = DeclClass::TranslationUnit; 313 | } 314 | void Accept(AstVisitor *visitor) override; 315 | }; 316 | } 317 | 318 | #endif // CCC_SRC_DECL_H 319 | -------------------------------------------------------------------------------- /src/Parse/Expr.cpp: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: Expr.cpp.cc 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/30 9 | ***********************************/ 10 | 11 | #include "Expr.h" 12 | #include "Parser.h" 13 | #include "Type.h" 14 | 15 | namespace CCC 16 | { 17 | 18 | /** 19 | expression: 20 | assignment-expression 21 | expression , assignment-expression 22 | */ 23 | std::shared_ptr Parser::ParseExpr() 24 | { 25 | return ParseAssignExpr(); 26 | } 27 | 28 | /** 29 | constant-expression: 30 | conditional-expression 31 | */ 32 | std::shared_ptr Parser::ParseConstantExpression() 33 | { 34 | return ParseAssignExpr(); 35 | } 36 | 37 | /** 38 | conditional-expression: 39 | logical-OR-expression 40 | logical-OR-expression ? expression : conditional-expression 41 | */ 42 | std::shared_ptr Parser::ParseConditionalExpression() 43 | { 44 | return nullptr; 45 | } 46 | 47 | /** 48 | assignment-expression: 49 | conditional-expression 50 | unary-expression assignment-operator assignment-expression 51 | 52 | assignment-operator: one of 53 | = *= /= %= += -= <<= >>= &= ^= |= 54 | */ 55 | std::shared_ptr Parser::ParseAssignExpr() 56 | { 57 | auto left = ParseEqualExpr(); 58 | 59 | if (Lex.Match(TokenKind::Assign)) { 60 | auto node = std::make_shared(Lex.CurrentToken); 61 | Lex.SkipToken(TokenKind::Assign); 62 | node->Lhs = left; 63 | node->Rhs = ParseAssignExpr(); 64 | return node; 65 | } 66 | return left; 67 | } 68 | 69 | /** 70 | equality-expression: 71 | relational-expression 72 | equality-expression == relational-expression 73 | equality-expression != relational-expression 74 | */ 75 | std::shared_ptr Parser::ParseEqualExpr() { 76 | auto left = ParseRelationalExpr(); 77 | while (Lex.Match(TokenKind::Equal) || 78 | Lex.Match(TokenKind::PipeEqual) ) { 79 | BinaryOperator op = BinaryOperator::Equal; 80 | if (Lex.Match(TokenKind::PipeEqual)) 81 | op = BinaryOperator::PipeEqual; 82 | auto node = std::make_shared(op, Lex.CurrentToken); 83 | Lex.GetNextToken(); 84 | node->Lhs = left; 85 | node->Rhs = ParseRelationalExpr(); 86 | left = node; 87 | } 88 | return left; 89 | } 90 | 91 | /** 92 | relational-expression: 93 | shift-expression 94 | relational-expression < shift-expression 95 | relational-expression > shift-expression 96 | relational-expression <= shift-expression 97 | relational-expression >= shift-expression 98 | */ 99 | std::shared_ptr Parser::ParseRelationalExpr() { 100 | auto left = ParseAddExpr(); 101 | while (Lex.Match(TokenKind::Greater) || 102 | Lex.Match(TokenKind::GreaterEqual) || 103 | Lex.Match(TokenKind::Lesser) || 104 | Lex.Match(TokenKind::LesserEqual)) { 105 | 106 | BinaryOperator op = BinaryOperator::Greater; 107 | if (Lex.Match(TokenKind::GreaterEqual)) 108 | op = BinaryOperator::GreaterEqual; 109 | else if (Lex.Match(TokenKind::Lesser)) 110 | op = BinaryOperator::Lesser; 111 | else if (Lex.Match(TokenKind::LesserEqual)) 112 | op = BinaryOperator::LesserEqual; 113 | 114 | auto node = std::make_shared(op, Lex.CurrentToken); 115 | Lex.GetNextToken(); 116 | node->Lhs = left; 117 | node->Rhs = ParseAddExpr(); 118 | left = node; 119 | } 120 | return left; 121 | } 122 | 123 | /** 124 | additive-expression: 125 | multiplicative-expression 126 | additive-expression + multiplicative-expression 127 | additive-expression - multiplicative-expression 128 | */ 129 | std::shared_ptr Parser::ParseAddExpr() 130 | { 131 | std::shared_ptr left = ParseMultiExpr(); 132 | while (Lex.Match(TokenKind::Plus) 133 | || Lex.Match(TokenKind::Minus)) { 134 | 135 | BinaryOperator bop = BinaryOperator::Add; 136 | if (Lex.Match(TokenKind::Minus)) 137 | bop = BinaryOperator::Sub; 138 | 139 | auto node = std::make_shared(bop, Lex.CurrentToken); 140 | Lex.GetNextToken(); 141 | node->Lhs = left; 142 | node->Rhs = ParseMultiExpr(); 143 | left = node; 144 | } 145 | return left; 146 | } 147 | 148 | /** 149 | multiplicative-expression: 150 | cast-expression 151 | multiplicative-expression * cast-expression 152 | multiplicative-expression / cast-expression 153 | multiplicative-expression % cast-expression 154 | */ 155 | std::shared_ptr Parser::ParseMultiExpr() 156 | { 157 | std::shared_ptr left = ParseUnaryExpr(); 158 | while (Lex.Match(TokenKind::Star) 159 | || Lex.Match(TokenKind::Slash)) { 160 | BinaryOperator anOperator = BinaryOperator::Mul; 161 | if (Lex.Match(TokenKind::Slash)) 162 | anOperator = BinaryOperator::Div; 163 | auto node = std::make_shared(anOperator, Lex.CurrentToken); 164 | Lex.GetNextToken(); 165 | node->Lhs = left; 166 | node->Rhs = ParseUnaryExpr(); 167 | left = node; 168 | } 169 | return left; 170 | } 171 | 172 | /** 173 | unary-expression: 174 | postfix-expression 175 | ++ unary-expression 176 | -- unary-expression 177 | unary-operator cast-expression 178 | sizeof unary-expression 179 | sizeof ( type-name ) 180 | 181 | unary-operator: 182 | one of & * + - ~ ! 183 | */ 184 | std::shared_ptr Parser::ParseUnaryExpr() { 185 | switch (Lex.CurrentToken->Kind) { 186 | case TokenKind::Plus: { 187 | auto node = std::make_shared(UnaryOperator::Plus, Lex.CurrentToken); 188 | Lex.GetNextToken(); 189 | node->Lhs = ParseUnaryExpr(); 190 | return node; 191 | } 192 | case TokenKind::Minus: { 193 | auto node = std::make_shared(UnaryOperator::Minus, Lex.CurrentToken); 194 | Lex.GetNextToken(); 195 | node->Lhs = ParseUnaryExpr(); 196 | return node; 197 | } 198 | case TokenKind::Star: { 199 | auto node = std::make_shared(UnaryOperator::Star, Lex.CurrentToken); 200 | Lex.GetNextToken(); 201 | node->Lhs = ParseUnaryExpr(); 202 | return node; 203 | } 204 | case TokenKind::Amp: { 205 | auto node = std::make_shared(UnaryOperator::Amp, Lex.CurrentToken); 206 | Lex.GetNextToken(); 207 | node->Lhs = ParseUnaryExpr(); 208 | return node; 209 | } 210 | case TokenKind::SizeOf: { 211 | return ParseSizeofExpr(); 212 | } 213 | default: 214 | return ParsePostFixExpr(); 215 | } 216 | } 217 | 218 | /** 219 | postfix-expression: 220 | primary-expression 221 | postfix-expression [ expression ] 222 | postfix-expression ( argument-expression-list? ) 223 | postfix-expression . identifier 224 | postfix-expression -> identifier 225 | postfix-expression ++ 226 | postfix-expression -- 227 | ( type-name ) { initializer-list } 228 | ( type-name ) { initializer-list , } 229 | */ 230 | 231 | std::shared_ptr Parser::ParsePostFixExpr() { 232 | auto expr = ParsePrimaryExpr(); 233 | while (true) { 234 | switch (Lex.CurrentToken->Kind) { 235 | case TokenKind::LBracket: { 236 | /// a[3] => *(a + 3) 237 | auto starNode = std::make_shared(UnaryOperator::Star, expr->Tok); 238 | auto addNode = std::make_shared(BinaryOperator::Add, expr->Tok); 239 | addNode->Lhs = expr; 240 | Lex.SkipToken(TokenKind::LBracket); 241 | addNode->Rhs = ParseExpr(); 242 | Lex.SkipToken(TokenKind::RBracket); 243 | starNode->Lhs = addNode; 244 | 245 | expr= starNode; 246 | break; 247 | } 248 | case TokenKind::LParen: { 249 | expr = ParseFuncCallNode(expr); 250 | break; 251 | } 252 | case TokenKind::Period: { 253 | expr = ParseMemberNode(expr); 254 | break; 255 | } 256 | case TokenKind::Arrow: { 257 | /// a->b => (*a).b; 258 | auto starNode = std::make_shared(UnaryOperator::Star, expr->Tok); 259 | starNode->Lhs = expr; 260 | expr = ParseMemberNode(starNode); 261 | break; 262 | } 263 | default: 264 | return expr; 265 | } 266 | } 267 | } 268 | 269 | std::shared_ptr Parser::ParseFuncCallNode(std::shared_ptr expr) { 270 | 271 | Lex.SkipToken(TokenKind::LParen); 272 | auto node = std::make_shared(expr->Tok); 273 | node->FuncName = expr->Tok->Content; 274 | if (!Lex.Match(TokenKind::RParen)) { 275 | node->Args.push_back(ParseAssignExpr()); 276 | while (Lex.Match(TokenKind::Comma)) { 277 | Lex.SkipToken(TokenKind::Comma); 278 | node->Args.push_back(ParseAssignExpr()); 279 | } 280 | } 281 | Lex.ExpectToken(TokenKind::RParen); 282 | return node; 283 | } 284 | 285 | std::shared_ptr Parser::ParseMemberNode(std::shared_ptr expr) 286 | { 287 | auto node = std::make_shared(Lex.CurrentToken); 288 | Lex.GetNextToken(); 289 | node->Lhs = expr; 290 | if (!Lex.Match(TokenKind::Id)) { 291 | ParseDiag(Lex.CurrentToken->Location, "expected a identifier as Struct or Union member"); 292 | } 293 | node->RhsName = Lex.CurrentToken->Content; 294 | Lex.SkipToken(TokenKind::Id); 295 | return node; 296 | } 297 | /** 298 | primary-expression: 299 | identifier 300 | constant 301 | string-literal 302 | ( expression ) 303 | ({}) 304 | */ 305 | std::shared_ptr Parser::ParsePrimaryExpr() 306 | { 307 | if (Lex.Match(TokenKind::LParen)) { 308 | Lex.BeginPeekToken(); 309 | Lex.GetNextToken(); 310 | if (Lex.Match(TokenKind::LBrace)) { 311 | Lex.EndPeekToken(); 312 | return ParseStmtExpr(); 313 | } 314 | Lex.EndPeekToken(); 315 | 316 | Lex.GetNextToken(); 317 | auto node = ParseExpr(); 318 | Lex.ExpectToken(TokenKind::RParen); 319 | return node; 320 | }else if (Lex.Match(TokenKind::Num)) { 321 | return ParseNumExpr(); 322 | }else if (Lex.Match(TokenKind::Id)) { 323 | return ParseVarExpr(); 324 | }else { 325 | ParseDiag(Lex.CurrentToken->Location, "error expr or not supported"); 326 | } 327 | return nullptr; 328 | } 329 | 330 | std::shared_ptr Parser::ParseStmtExpr() 331 | { 332 | auto node = std::make_shared(Lex.CurrentToken); 333 | 334 | Lex.SkipToken(TokenKind::LParen); 335 | Lex.SkipToken(TokenKind::LBrace); 336 | 337 | 338 | while (!Lex.Match(TokenKind::RBrace)) { 339 | if (FirstDeclarationSet.find(Lex.CurrentToken->Kind) != FirstDeclarationSet.end()) { 340 | node->Decls.push_back(ParseDeclaration()); 341 | }else { 342 | node->Stmts.push_back(ParseStmt()); 343 | } 344 | } 345 | 346 | Lex.SkipToken(TokenKind::RBrace); 347 | Lex.ExpectToken(TokenKind::RParen); 348 | 349 | return node; 350 | } 351 | 352 | std::shared_ptr Parser::ParseNumExpr() 353 | { 354 | auto node = std::make_shared(Lex.CurrentToken); 355 | node->Value = Lex.CurrentToken->Value; 356 | node->Ty = Type::LongTy; 357 | Lex.GetNextToken(); 358 | return node; 359 | } 360 | 361 | std::shared_ptr Parser::ParseVarExpr() 362 | { 363 | auto node = std::make_shared(Lex.CurrentToken); 364 | node->VarName = Lex.CurrentToken->Content; 365 | Lex.GetNextToken(); 366 | return node; 367 | } 368 | 369 | std::shared_ptr Parser::ParseSizeofExpr() 370 | { 371 | auto node = std::make_shared(Lex.CurrentToken); 372 | Lex.SkipToken(TokenKind::SizeOf); 373 | node->Lhs = ParseUnaryExpr(); 374 | return node; 375 | } 376 | 377 | void AssignExpr::Accept(AstVisitor *visitor) { 378 | visitor->VisitorAssignExprNode(this); 379 | } 380 | 381 | void SizeOfExpr::Accept(AstVisitor *visitor) { 382 | visitor->VisitorSizeOfExprNode(this); 383 | } 384 | 385 | void BinaryExpr::Accept(AstVisitor *visitor) { 386 | visitor->VisitorBinaryExprNode(this); 387 | } 388 | 389 | void UnaryExpr::Accept(AstVisitor *visitor) { 390 | visitor->VisitorUnaryExprNode(this); 391 | } 392 | 393 | void NumExpr::Accept(AstVisitor *visitor) { 394 | visitor->VisitorNumExprNode(this); 395 | } 396 | 397 | void VarExpr::Accept(AstVisitor *visitor) { 398 | visitor->VisitorVarExprNode(this); 399 | } 400 | 401 | void FuncCallExpr::Accept(AstVisitor *visitor) { 402 | visitor->VisitorFuncCallExprNode(this); 403 | } 404 | 405 | void StmtExpr::Accept(AstVisitor *visitor) { 406 | visitor->VisitorStmtExprNode(this); 407 | } 408 | 409 | void MemberExpr::Accept(AstVisitor *visitor) { 410 | visitor->VisitorMemberExprNode(this); 411 | } 412 | } 413 | -------------------------------------------------------------------------------- /src/Parse/Expr.h: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: Expr.h 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/30 9 | ***********************************/ 10 | 11 | #ifndef CCC_SRC_EXPR_H 12 | #define CCC_SRC_EXPR_H 13 | 14 | #include "AstVisitor.h" 15 | #include "SymbolTable.h" 16 | 17 | namespace CCC { 18 | 19 | class Type; 20 | class ExprNode : public AstNode 21 | { 22 | public: 23 | std::shared_ptr Ty; 24 | ExprNode(std::shared_ptr tok) : AstNode(tok) {} 25 | virtual void Accept(AstVisitor *visitor) = 0; 26 | }; 27 | 28 | class AssignExpr : public ExprNode 29 | { 30 | public: 31 | std::shared_ptr Lhs{nullptr}; 32 | std::shared_ptr Rhs{nullptr}; 33 | AssignExpr(std::shared_ptr tok) : ExprNode(tok) {} 34 | void Accept(AstVisitor *visitor) override; 35 | }; 36 | 37 | class SizeOfExpr : public ExprNode 38 | { 39 | public: 40 | std::shared_ptr Lhs{nullptr}; 41 | SizeOfExpr(std::shared_ptr tok) : ExprNode(tok) {} 42 | void Accept(AstVisitor *visitor) override; 43 | }; 44 | 45 | enum class BinaryOperator 46 | { 47 | Add, Sub, Mul, Div, 48 | Equal, PipeEqual, Greater, GreaterEqual, 49 | Lesser, LesserEqual 50 | }; 51 | 52 | class BinaryExpr : public ExprNode 53 | { 54 | public: 55 | BinaryOperator BinOp; 56 | std::shared_ptr Lhs{nullptr}; 57 | std::shared_ptr Rhs{nullptr}; 58 | BinaryExpr(BinaryOperator op, std::shared_ptr tok) : ExprNode(tok), BinOp(op) {} 59 | void Accept(AstVisitor *visitor) override; 60 | }; 61 | 62 | enum class UnaryOperator 63 | { 64 | Plus, Minus, Star, Amp 65 | }; 66 | class UnaryExpr : public ExprNode 67 | { 68 | public: 69 | UnaryOperator Uop; 70 | std::shared_ptr Lhs{nullptr}; 71 | UnaryExpr(UnaryOperator op, std::shared_ptr tok) : ExprNode(tok), Uop(op) {} 72 | void Accept(AstVisitor *visitor) override; 73 | }; 74 | 75 | class NumExpr : public ExprNode 76 | { 77 | public: 78 | long Value; 79 | NumExpr(std::shared_ptr tok) : ExprNode(tok) {} 80 | void Accept(AstVisitor *visitor) override; 81 | }; 82 | 83 | class VarExpr : public ExprNode 84 | { 85 | public: 86 | std::string_view VarName; 87 | VarExpr(std::shared_ptr tok) : ExprNode(tok) {} 88 | void Accept(AstVisitor *visitor) override; 89 | 90 | public: 91 | /// sema 92 | std::shared_ptr Sym; 93 | }; 94 | 95 | class FuncCallExpr : public ExprNode 96 | { 97 | public: 98 | std::string_view FuncName; 99 | std::vector> Args; 100 | FuncCallExpr(std::shared_ptr tok) : ExprNode(tok) {} 101 | void Accept(AstVisitor *visitor) override; 102 | }; 103 | 104 | class StmtExpr : public ExprNode 105 | { 106 | public: 107 | std::list> Decls; 108 | std::list> Stmts; 109 | StmtExpr(std::shared_ptr tok) : ExprNode(tok) {} 110 | void Accept(AstVisitor *visitor) override; 111 | }; 112 | 113 | class MemberExpr : public ExprNode 114 | { 115 | public: 116 | std::shared_ptr Lhs; 117 | std::string_view RhsName; 118 | MemberExpr(std::shared_ptr tok) : ExprNode(tok) {} 119 | void Accept(AstVisitor *visitor) override; 120 | 121 | public: 122 | /// sema 123 | std::shared_ptr Fld{nullptr}; 124 | }; 125 | } 126 | 127 | #endif // CCC_SRC_EXPR_H 128 | -------------------------------------------------------------------------------- /src/Parse/Parser.cpp: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: Parser.cpp.cc 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/3 9 | ***********************************/ 10 | 11 | #include "Parser.h" 12 | #include 13 | 14 | namespace CCC { 15 | Parser::Parser(Lexer &lex) : Lex(lex) { 16 | Lex.GetNextToken(); 17 | FirstDeclarationSet = { 18 | TokenKind::Void, TokenKind::Bool, TokenKind::Char, TokenKind::Short, TokenKind::Int, 19 | TokenKind::Long, TokenKind::Float, TokenKind::Double, TokenKind::Signed, TokenKind::UnSigned, 20 | TokenKind::Struct, TokenKind::Union, TokenKind::Enum, 21 | TokenKind::Auto, TokenKind::Static, TokenKind::Register, TokenKind::Extern, TokenKind::Typedef, 22 | TokenKind::Const, TokenKind::Volatile,TokenKind::Restrict 23 | }; 24 | } 25 | 26 | bool Parser::IsFunctionDeclaration(std::shared_ptr dec, std::string_view &funcName) 27 | { 28 | while (dec) { 29 | /// void (*a(int a))(int a); 30 | /// func->point->func->name 31 | if (dec->Cls == DeclClass::FunctionDeclarator && 32 | dec->Dec && dec->Dec->Cls == DeclClass::NameDeclarator) { 33 | funcName = dec->Dec->Id; 34 | return true; 35 | } 36 | dec = dec->Dec; 37 | } 38 | return false; 39 | } 40 | } 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/Parse/Parser.h: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: Parser.h 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/3 9 | ***********************************/ 10 | 11 | #ifndef CCC_PARSER_H 12 | #define CCC_PARSER_H 13 | #include "AstVisitor.h" 14 | #include 15 | #include 16 | #include "Expr.h" 17 | #include "Stmt.h" 18 | #include "Decl.h" 19 | #include "Basic/Diag.h" 20 | 21 | namespace CCC 22 | { 23 | class Parser 24 | { 25 | private: 26 | Lexer &Lex; 27 | std::set FirstDeclarationSet; 28 | public: 29 | Parser(Lexer &lex); 30 | std::shared_ptr ParseTranslationUnit(); 31 | private: 32 | std::shared_ptr ParseExternalDeclaration(); 33 | std::shared_ptr ParseCommonHeader(); 34 | std::shared_ptr ParseDeclaration(); 35 | std::shared_ptr ParseDeclSpecifier(); 36 | std::shared_ptr ParseInitDeclarator(); 37 | std::shared_ptr ParseDeclarator(); 38 | std::shared_ptr ParsePointerDeclarator(); 39 | std::shared_ptr ParseDirectDeclarator(); 40 | std::shared_ptr ParseParamTypeList(); 41 | std::shared_ptr ParseParamDeclaration(); 42 | std::shared_ptr ParseInitializer(); 43 | std::shared_ptr ParseStructOrUnionSpecifier(); 44 | std::shared_ptr ParseStructDeclaration(); 45 | std::shared_ptr ParseStructDeclarator(); 46 | std::shared_ptr ParseEnumSpecifier(); 47 | std::shared_ptr ParseEnumDeclarator(); 48 | 49 | std::shared_ptr ParseStmt(); 50 | std::shared_ptr ParseIfStmt(); 51 | std::shared_ptr ParseDoWhileStmt(); 52 | std::shared_ptr ParseWhileStmt(); 53 | std::shared_ptr ParseForStmt(); 54 | std::shared_ptr ParseBlockStmt(); 55 | std::shared_ptr ParseReturnStmt(); 56 | std::shared_ptr ParseExprStmt(); 57 | std::shared_ptr ParseBreakStmt(); 58 | std::shared_ptr ParseContinueStmt(); 59 | std::shared_ptr ParseGotoStmt(); 60 | std::shared_ptr ParseLabelStmt(); 61 | std::shared_ptr ParseCaseStmt(); 62 | std::shared_ptr ParseDefaultStmt(); 63 | std::shared_ptr ParseSwitchStmt(); 64 | 65 | std::shared_ptr ParseExpr(); 66 | std::shared_ptr ParseConstantExpression(); 67 | std::shared_ptr ParseConditionalExpression(); 68 | std::shared_ptr ParseAssignExpr(); 69 | std::shared_ptr ParseEqualExpr(); 70 | std::shared_ptr ParseRelationalExpr(); 71 | std::shared_ptr ParseAddExpr(); 72 | std::shared_ptr ParseMultiExpr(); 73 | std::shared_ptr ParseUnaryExpr(); 74 | std::shared_ptr ParsePostFixExpr(); 75 | std::shared_ptr ParseFuncCallNode(std::shared_ptr expr); 76 | std::shared_ptr ParseMemberNode(std::shared_ptr expr); 77 | 78 | std::shared_ptr ParsePrimaryExpr(); 79 | std::shared_ptr ParseStmtExpr(); 80 | std::shared_ptr ParseNumExpr(); 81 | std::shared_ptr ParseVarExpr(); 82 | std::shared_ptr ParseSizeofExpr(); 83 | 84 | private: 85 | bool IsFunctionDeclaration(std::shared_ptr dec, std::string_view &funcName); 86 | }; 87 | } 88 | 89 | #endif // CCC_PARSER_H 90 | -------------------------------------------------------------------------------- /src/Parse/Stmt.cpp: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: Stmt.cpp.cc 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/30 9 | ***********************************/ 10 | 11 | #include "Stmt.h" 12 | #include "Parser.h" 13 | 14 | namespace CCC 15 | { 16 | std::shared_ptr Parser::ParseStmt() 17 | { 18 | if (Lex.Match(TokenKind::If)) { 19 | return ParseIfStmt(); 20 | } 21 | else if (Lex.Match(TokenKind::While)) { 22 | return ParseWhileStmt(); 23 | } 24 | else if (Lex.Match(TokenKind::Do)) { 25 | return ParseDoWhileStmt(); 26 | } 27 | else if (Lex.Match(TokenKind::For)) { 28 | return ParseForStmt(); 29 | } 30 | else if (Lex.Match(TokenKind::LBrace)) { 31 | return ParseBlockStmt(); 32 | } 33 | else if (Lex.Match(TokenKind::Return)) { 34 | return ParseReturnStmt(); 35 | } 36 | else if (Lex.Match(TokenKind::Break)) { 37 | return ParseBreakStmt(); 38 | } 39 | else if (Lex.Match(TokenKind::Continue)) { 40 | return ParseContinueStmt(); 41 | } 42 | else if (Lex.Match(TokenKind::Goto)) { 43 | return ParseGotoStmt(); 44 | } 45 | else if (Lex.Match(TokenKind::Case)) { 46 | return ParseCaseStmt(); 47 | } 48 | else if (Lex.Match(TokenKind::Default)) { 49 | return ParseDefaultStmt(); 50 | } 51 | else if (Lex.Match(TokenKind::Switch)) { 52 | return ParseSwitchStmt(); 53 | } 54 | else if (Lex.Match(TokenKind::Id)) { 55 | return ParseLabelStmt(); 56 | } 57 | else { 58 | return ParseExprStmt(); 59 | } 60 | } 61 | 62 | std::shared_ptr Parser::ParseIfStmt() 63 | { 64 | auto node = std::make_shared(Lex.CurrentToken); 65 | Lex.SkipToken(TokenKind::If); 66 | Lex.ExpectToken(TokenKind::LParen); 67 | node->Cond = ParseExpr(); 68 | Lex.ExpectToken(TokenKind::RParen); 69 | node->Then = ParseStmt(); 70 | if (Lex.Match(TokenKind::Else)) { 71 | Lex.SkipToken(TokenKind::Else); 72 | node->Else = ParseStmt(); 73 | } 74 | return node; 75 | } 76 | 77 | std::shared_ptr Parser::ParseWhileStmt() 78 | { 79 | auto node = std::make_shared(Lex.CurrentToken); 80 | Lex.SkipToken(TokenKind::While); 81 | Lex.ExpectToken(TokenKind::LParen); 82 | node->Cond = ParseExpr(); 83 | Lex.ExpectToken(TokenKind::RParen); 84 | node->Then = ParseStmt(); 85 | return node; 86 | } 87 | 88 | std::shared_ptr Parser::ParseDoWhileStmt() 89 | { 90 | auto node = std::make_shared(Lex.CurrentToken); 91 | Lex.SkipToken(TokenKind::Do); 92 | node->Stmt = ParseStmt(); 93 | Lex.ExpectToken(TokenKind::While); 94 | Lex.ExpectToken(TokenKind::LParen); 95 | node->Cond = ParseExpr(); 96 | Lex.ExpectToken(TokenKind::RParen); 97 | Lex.ExpectToken(TokenKind::Semicolon); 98 | return node; 99 | } 100 | 101 | std::shared_ptr Parser::ParseForStmt() 102 | { 103 | auto node = std::make_shared(Lex.CurrentToken); 104 | Lex.SkipToken(TokenKind::For); 105 | Lex.ExpectToken(TokenKind::LParen); 106 | if (!Lex.Match(TokenKind::Semicolon)) { 107 | if (FirstDeclarationSet.find(Lex.CurrentToken->Kind) != FirstDeclarationSet.end()) { 108 | node->InitDecl = ParseDeclaration(); 109 | }else { 110 | node->InitExpr = ParseExpr(); 111 | Lex.ExpectToken(TokenKind::Semicolon); 112 | } 113 | }else { 114 | Lex.ExpectToken(TokenKind::Semicolon); 115 | } 116 | if (!Lex.Match(TokenKind::Semicolon)) 117 | node->Cond = ParseExpr(); 118 | Lex.ExpectToken(TokenKind::Semicolon); 119 | if (!Lex.Match(TokenKind::RParen)) 120 | node->Inc = ParseExpr(); 121 | Lex.ExpectToken(TokenKind::RParen); 122 | node->Stmt = ParseStmt(); 123 | return node; 124 | } 125 | 126 | std::shared_ptr Parser::ParseBlockStmt() 127 | { 128 | auto node = std::make_shared(Lex.CurrentToken); 129 | Lex.SkipToken(TokenKind::LBrace); 130 | while (!Lex.Match(TokenKind::RBrace)) { 131 | if (FirstDeclarationSet.find(Lex.CurrentToken->Kind) != FirstDeclarationSet.end()) { 132 | auto decl = ParseDeclaration(); 133 | decl->IsLocalDecl = true; 134 | node->Decls.push_back(decl); 135 | }else { 136 | node->Stmts.push_back(ParseStmt()); 137 | } 138 | } 139 | Lex.ExpectToken(TokenKind::RBrace); 140 | 141 | return node; 142 | } 143 | 144 | std::shared_ptr Parser::ParseReturnStmt() 145 | { 146 | auto node = std::make_shared(Lex.CurrentToken); 147 | Lex.SkipToken(TokenKind::Return); 148 | node->Lhs = ParseExpr(); 149 | Lex.ExpectToken(TokenKind::Semicolon); 150 | return node; 151 | } 152 | 153 | std::shared_ptr Parser::ParseExprStmt() 154 | { 155 | auto node = std::make_shared(Lex.CurrentToken); 156 | if (!Lex.Match(TokenKind::Semicolon)) { 157 | node->Lhs = ParseExpr(); 158 | } 159 | Lex.ExpectToken(TokenKind::Semicolon); 160 | return node; 161 | } 162 | 163 | std::shared_ptr Parser::ParseBreakStmt() { 164 | auto node = std::make_shared(Lex.CurrentToken); 165 | Lex.ExpectToken(TokenKind::Break); 166 | Lex.ExpectToken(TokenKind::Semicolon); 167 | return node; 168 | } 169 | 170 | std::shared_ptr Parser::ParseContinueStmt() { 171 | auto node = std::make_shared(Lex.CurrentToken); 172 | Lex.ExpectToken(TokenKind::Continue); 173 | Lex.ExpectToken(TokenKind::Semicolon); 174 | return node; 175 | } 176 | 177 | std::shared_ptr Parser::ParseGotoStmt() { 178 | auto node = std::make_shared(Lex.CurrentToken); 179 | Lex.SkipToken(TokenKind::Goto); 180 | if (!Lex.Match(TokenKind::Id)) { 181 | ParseDiag(node->Tok->Location, "expected a identifier"); 182 | } 183 | node->LabelName = Lex.CurrentToken->Content; 184 | Lex.SkipToken(TokenKind::Id); 185 | Lex.ExpectToken(TokenKind::Semicolon); 186 | return node; 187 | } 188 | 189 | std::shared_ptr Parser::ParseLabelStmt() { 190 | Lex.BeginPeekToken(); 191 | Lex.GetNextToken(); 192 | if (Lex.Match(TokenKind::Colon)) { 193 | Lex.EndPeekToken(); 194 | auto node = std::make_shared(Lex.CurrentToken); 195 | node->LabelName = Lex.CurrentToken->Content; 196 | Lex.SkipToken(TokenKind::Id); 197 | Lex.SkipToken(TokenKind::Colon); 198 | node->Stmt = ParseStmt(); 199 | return node; 200 | } 201 | Lex.EndPeekToken(); 202 | return ParseExprStmt(); 203 | } 204 | 205 | std::shared_ptr Parser::ParseCaseStmt() { 206 | auto node = std::make_shared(Lex.CurrentToken); 207 | Lex.SkipToken(TokenKind::Case); 208 | node->Expr = ParseExpr(); 209 | Lex.ExpectToken(TokenKind::Colon); 210 | node->Stmt = ParseStmt(); 211 | return node; 212 | } 213 | 214 | std::shared_ptr Parser::ParseDefaultStmt() { 215 | auto node = std::make_shared(Lex.CurrentToken); 216 | Lex.SkipToken(TokenKind::Default); 217 | Lex.ExpectToken(TokenKind::Colon); 218 | node->Stmt = ParseStmt(); 219 | return node; 220 | } 221 | 222 | std::shared_ptr Parser::ParseSwitchStmt() { 223 | auto node = std::make_shared(Lex.CurrentToken); 224 | Lex.SkipToken(TokenKind::Switch); 225 | Lex.ExpectToken(TokenKind::LParen); 226 | node->Expr = ParseExpr(); 227 | Lex.ExpectToken(TokenKind::RParen); 228 | node->Stmt = ParseStmt(); 229 | return node; 230 | } 231 | 232 | void IfStmtNode::Accept(AstVisitor *visitor) { 233 | visitor->VisitorIfStmtNode(this); 234 | } 235 | 236 | void DoWhileStmtNode::Accept(AstVisitor *visitor) { 237 | visitor->VisitorDoWhileStmtNode(this); 238 | } 239 | 240 | void WhileStmtNode::Accept(AstVisitor *visitor) { 241 | visitor->VisitorWhileStmtNode(this); 242 | } 243 | 244 | void ForStmtNode::Accept(AstVisitor *visitor) { 245 | visitor->VisitorForStmtNode(this); 246 | } 247 | 248 | void ReturnStmtNode::Accept(AstVisitor *visitor) { 249 | visitor->VisitorReturnStmtNode(this); 250 | } 251 | 252 | void BlockStmtNode::Accept(AstVisitor *visitor) { 253 | visitor->VisitorBlockStmtNode(this); 254 | } 255 | 256 | void ExprStmtNode::Accept(AstVisitor *visitor) { 257 | visitor->VisitorExprStmtNode(this); 258 | } 259 | 260 | void BreakStmtNode::Accept(AstVisitor *visitor) { 261 | visitor->VisitorBreakStmtNode(this); 262 | } 263 | 264 | void ContinueStmtNode::Accept(AstVisitor *visitor) { 265 | visitor->VisitorContinueStmtNode(this); 266 | } 267 | 268 | void GotoStmtNode::Accept(AstVisitor *visitor) { 269 | visitor->VisitorGotoStmtNode(this); 270 | } 271 | 272 | void LabelStmtNode::Accept(AstVisitor *visitor) { 273 | visitor->VisitorLabelStmtNode(this); 274 | } 275 | 276 | void CaseStmtNode::Accept(AstVisitor *visitor) { 277 | visitor->VisitorCaseStmtNode(this); 278 | } 279 | 280 | void DefaultStmtNode::Accept(AstVisitor *visitor) { 281 | visitor->VisitorDefaultStmtNode(this); 282 | } 283 | 284 | void SwitchStmtNode::Accept(AstVisitor *visitor) { 285 | visitor->VisitorSwitchStmtNode(this); 286 | } 287 | } -------------------------------------------------------------------------------- /src/Parse/Stmt.h: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: Stmt.h 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/30 9 | ***********************************/ 10 | 11 | #ifndef CCC_SRC_STMT_H 12 | #define CCC_SRC_STMT_H 13 | 14 | #include "AstVisitor.h" 15 | 16 | namespace CCC 17 | { 18 | enum class StmtNodeClass { 19 | ExprStmtNode, 20 | IfStmtNode, 21 | WhileStmtNode, 22 | DoWhileStmtNode, 23 | ForStmtNode, 24 | BlockStmtNode, 25 | ReturnStmtNode, 26 | BreakStmtNode, 27 | ContinueStmtNode, 28 | GotoStmtNode, 29 | LabelStmtNode, 30 | CaseStmtNode, 31 | DefaultStmtNode, 32 | SwitchStmtNode 33 | }; 34 | 35 | class StmtNode : public AstNode 36 | { 37 | public: 38 | StmtNodeClass Cls; 39 | StmtNode(std::shared_ptr tok) : AstNode(tok) {} 40 | virtual void Accept(AstVisitor *visitor) = 0; 41 | }; 42 | 43 | class ExprStmtNode : public StmtNode 44 | { 45 | public: 46 | std::shared_ptr Lhs{nullptr}; 47 | ExprStmtNode(std::shared_ptr tok) : StmtNode(tok) { 48 | Cls = StmtNodeClass::ExprStmtNode; 49 | } 50 | void Accept(AstVisitor *visitor) override; 51 | }; 52 | 53 | class IfStmtNode : public StmtNode 54 | { 55 | public: 56 | std::shared_ptr Cond{nullptr}; 57 | std::shared_ptr Then{nullptr}; 58 | std::shared_ptr Else{nullptr}; 59 | IfStmtNode(std::shared_ptr tok) : StmtNode(tok) { 60 | Cls = StmtNodeClass::IfStmtNode; 61 | } 62 | void Accept(AstVisitor *visitor) override; 63 | }; 64 | 65 | class WhileStmtNode : public StmtNode 66 | { 67 | public: 68 | std::shared_ptr Cond{nullptr}; 69 | std::shared_ptr Then{nullptr}; 70 | WhileStmtNode(std::shared_ptr tok) : StmtNode(tok) { 71 | Cls = StmtNodeClass::WhileStmtNode; 72 | } 73 | void Accept(AstVisitor *visitor) override; 74 | }; 75 | 76 | class DoWhileStmtNode : public StmtNode 77 | { 78 | public: 79 | std::shared_ptr Stmt{nullptr}; 80 | std::shared_ptr Cond{nullptr}; 81 | DoWhileStmtNode(std::shared_ptr tok) : StmtNode(tok) { 82 | Cls = StmtNodeClass::DoWhileStmtNode; 83 | } 84 | void Accept(AstVisitor *visitor) override; 85 | }; 86 | 87 | class ForStmtNode : public StmtNode 88 | { 89 | public: 90 | std::shared_ptr InitExpr{nullptr}; 91 | std::shared_ptr InitDecl{nullptr}; 92 | std::shared_ptr Cond{nullptr}; 93 | std::shared_ptr Inc{nullptr}; 94 | std::shared_ptr Stmt{nullptr}; 95 | ForStmtNode(std::shared_ptr tok) : StmtNode(tok) { 96 | Cls = StmtNodeClass::ForStmtNode; 97 | } 98 | void Accept(AstVisitor *visitor) override; 99 | }; 100 | 101 | class BlockStmtNode : public StmtNode 102 | { 103 | public: 104 | std::list> Decls; 105 | std::list> Stmts; 106 | BlockStmtNode(std::shared_ptr tok) : StmtNode(tok) { 107 | Cls = StmtNodeClass::BlockStmtNode; 108 | } 109 | void Accept(AstVisitor *visitor) override; 110 | 111 | public: 112 | /// sema 113 | bool needEnterScope{true}; 114 | }; 115 | 116 | class ReturnStmtNode : public StmtNode 117 | { 118 | public: 119 | std::shared_ptr Lhs{nullptr}; 120 | ReturnStmtNode(std::shared_ptr tok) : StmtNode(tok) { 121 | Cls = StmtNodeClass::ReturnStmtNode; 122 | } 123 | void Accept(AstVisitor *visitor) override; 124 | }; 125 | 126 | class BreakStmtNode : public StmtNode 127 | { 128 | public: 129 | BreakStmtNode(std::shared_ptr tok) : StmtNode(tok) { 130 | Cls = StmtNodeClass::BreakStmtNode; 131 | } 132 | void Accept(AstVisitor *visitor) override; 133 | }; 134 | 135 | class ContinueStmtNode : public StmtNode 136 | { 137 | public: 138 | ContinueStmtNode(std::shared_ptr tok) : StmtNode(tok) { 139 | Cls = StmtNodeClass::ContinueStmtNode; 140 | } 141 | void Accept(AstVisitor *visitor) override; 142 | }; 143 | 144 | class GotoStmtNode : public StmtNode 145 | { 146 | public: 147 | std::string_view LabelName; 148 | GotoStmtNode(std::shared_ptr tok) : StmtNode(tok) { 149 | Cls = StmtNodeClass::GotoStmtNode; 150 | } 151 | void Accept(AstVisitor *visitor) override; 152 | }; 153 | 154 | class LabelStmtNode : public StmtNode 155 | { 156 | public: 157 | std::string_view LabelName; 158 | std::shared_ptr Stmt; 159 | LabelStmtNode(std::shared_ptr tok) : StmtNode(tok) { 160 | Cls = StmtNodeClass::LabelStmtNode; 161 | } 162 | void Accept(AstVisitor *visitor) override; 163 | }; 164 | 165 | class CaseStmtNode : public StmtNode 166 | { 167 | public: 168 | std::shared_ptr Expr; 169 | std::shared_ptr Stmt; 170 | CaseStmtNode(std::shared_ptr tok) : StmtNode(tok) { 171 | Cls = StmtNodeClass::CaseStmtNode; 172 | } 173 | void Accept(AstVisitor *visitor) override; 174 | public: 175 | /// codegen 176 | int Label{0}; 177 | }; 178 | 179 | class DefaultStmtNode : public StmtNode 180 | { 181 | public: 182 | std::shared_ptr Stmt; 183 | DefaultStmtNode(std::shared_ptr tok) : StmtNode(tok) { 184 | Cls = StmtNodeClass::DefaultStmtNode; 185 | } 186 | void Accept(AstVisitor *visitor) override; 187 | public: 188 | /// codegen 189 | int Label{0}; 190 | }; 191 | 192 | class SwitchStmtNode : public StmtNode 193 | { 194 | public: 195 | std::shared_ptr Expr; 196 | std::shared_ptr Stmt; 197 | SwitchStmtNode(std::shared_ptr tok) : StmtNode(tok) { 198 | Cls = StmtNodeClass::SwitchStmtNode; 199 | } 200 | void Accept(AstVisitor *visitor) override; 201 | 202 | public: 203 | /// sema 204 | std::list CaseStmtList; 205 | DefaultStmtNode *DefaultStmt{nullptr}; 206 | }; 207 | } 208 | 209 | #endif // CCC_SRC_STMT_H 210 | -------------------------------------------------------------------------------- /src/Sema/DeclSema.cpp: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: DeclSema.cpp.cc 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/31 9 | ***********************************/ 10 | 11 | #include "Sema.h" 12 | #include 13 | 14 | namespace CCC { 15 | 16 | /** 17 | translation-unit: 18 | external-declaration 19 | translation-unit external-declaration 20 | 21 | external-declaration: 22 | function-definition 23 | declaration 24 | */ 25 | void Sema::VisitorTranslationUnitNode(TranslationUnit *node) 26 | { 27 | SymTable.EnterScope(); 28 | for (auto &extDec : node->ExtDecl) { 29 | extDec->Accept(this); 30 | } 31 | SymTable.ExitScope(); 32 | } 33 | 34 | /** 35 | function-definition: 36 | declaration-specifiers declarator declaration-list? compound-statement 37 | */ 38 | void Sema::VisitorFunctionNode(Function *node) 39 | { 40 | node->Spec->Accept(this); 41 | 42 | node->Dec->BaseTy = node->Spec->Ty; 43 | node->Dec->Accept(this); 44 | node->Ty = node->Dec->Ty; 45 | 46 | std::shared_ptr fSym = SymTable.FindVar(node->FuncName); 47 | if (fSym == nullptr) { 48 | node->FSym = SymTable.AddFunction(node->FuncName, node->Ty, node->Tok->Location); 49 | } 50 | else if (!fSym->Ty->IsFuncTy()) { 51 | SemaDiag(node->Tok->Location, "Redeclaration as a function"); 52 | } 53 | else { 54 | if (node->FSym->Defined) { 55 | SemaDiag(node->Tok->Location, "Function redefinition"); 56 | } 57 | } 58 | node->FSym->Defined = true; 59 | 60 | CurrentFunc = node; 61 | 62 | SymTable.EnterScope(); 63 | 64 | auto funTy = std::dynamic_pointer_cast(node->Ty); 65 | for (auto ¶m : funTy->Params) { 66 | auto sym = SymTable.AddVariable(param->Tok->Content, param->Ty, param->Tok->Location); 67 | node->FSym->Params.push_back(sym); 68 | node->FSym->Locals.push_back(sym); 69 | } 70 | 71 | // SymTable.ExitScope(); 72 | node->BlockStmt->needEnterScope = false; 73 | node->BlockStmt->Accept(this); 74 | 75 | SymTable.ExitScope(); 76 | CurrentFunc = nullptr; 77 | } 78 | 79 | void Sema::VisitorDeclarationNode(Declaration *node) { 80 | if (node->IsLocalDecl) { 81 | CheckLocalDeclaration(node); 82 | }else { 83 | CheckGlobalDeclaration(node); 84 | } 85 | } 86 | 87 | /** 88 | storage-class-specifier: 89 | typedef extern static auto register 90 | 91 | type-specifier: 92 | void char short int long 93 | float double signed unsigned _Bool 94 | _Complex 95 | struct-or-union-specifier 96 | enum-specifier 97 | typedef-name 98 | 99 | type-qualifier: 100 | const restrict volatile 101 | 102 | declaration-specifiers: 103 | storage-class-specifier declaration-specifiers? 104 | type-specifier declaration-specifiers? 105 | type-qualifier declaration-specifiers? 106 | function-specifier declaration-specifiers? 107 | */ 108 | void Sema::VisitorDeclSpecifierNode(DeclSpecifier *node) 109 | { 110 | CheckStorageSpecifier(node); 111 | CheckTypeSpecifier(node); 112 | } 113 | 114 | void Sema::VisitorNameDeclaratorNode(NameDeclarator *node) { 115 | auto ty = node->BaseTy; 116 | if (node->Dec != nullptr) { 117 | node->Dec->BaseTy = ty; 118 | node->Dec->Accept(this); 119 | node->Ty = node->Dec->Ty; 120 | node->Id = node->Dec->Id; 121 | }else { 122 | node->Ty = ty; 123 | } 124 | } 125 | 126 | void Sema::VisitorFuncDeclaratorNode(FunctionDeclarator *node) { 127 | auto ty = std::make_shared(node->BaseTy); 128 | node->ParamTyLists->FunTy = ty; 129 | node->ParamTyLists->Accept(this); 130 | 131 | if (node->Dec != nullptr) { 132 | node->Dec->BaseTy = ty; 133 | node->Dec->Accept(this); 134 | node->Ty = node->Dec->Ty; 135 | node->Id = node->Dec->Id; 136 | }else { 137 | node->Ty = ty; 138 | } 139 | } 140 | 141 | void Sema::VisitorArrayDeclaratorNode(ArrayDeclarator *node) 142 | { 143 | auto ty = std::make_shared(node->BaseTy, node->ArrayLen); 144 | if (node->Dec) { 145 | node->Dec->BaseTy = ty; 146 | node->Dec->Accept(this); 147 | node->Ty = node->Dec->Ty; 148 | node->Id = node->Dec->Id; 149 | }else { 150 | node->Ty = ty; 151 | } 152 | } 153 | 154 | void Sema::VisitorPointerDeclaratorNode(PointerDeclarator *node) { 155 | auto ty = std::make_shared(node->BaseTy); 156 | if (node->Dec) { 157 | node->Dec->BaseTy = ty; 158 | node->Dec->Accept(this); 159 | node->Ty = node->Dec->Ty; 160 | node->Id = node->Dec->Id; 161 | }else { 162 | node->Ty = ty; 163 | } 164 | } 165 | 166 | void Sema::VisitorInitDeclaratorNode(InitDeclarator *node) { 167 | node->Dec->BaseTy = node->BaseTy; 168 | node->Dec->Accept(this); 169 | node->Ty = node->Dec->Ty; 170 | node->Id = node->Dec->Id; 171 | 172 | if (node->Init) { 173 | node->Init->Ty = node->Ty; 174 | node->Init->Accept(this); 175 | } 176 | } 177 | 178 | void Sema::VisitorInitializerNode(Initializer *node) { 179 | CheckInitializerInternal(node); 180 | } 181 | 182 | /** 183 | parameter-type-list: 184 | parameter-list 185 | parameter-list , ... 186 | 187 | parameter-list: 188 | parameter-declaration 189 | parameter-list , parameter-declaration 190 | */ 191 | void Sema::VisitorParamTypeListNode(ParamTypeList *node) { 192 | for (auto &p : node->ParamDecl) { 193 | p->FunTy = node->FunTy; 194 | p->Accept(this); 195 | } 196 | } 197 | 198 | /** 199 | parameter-declaration: 200 | declaration-specifiers declarator 201 | declaration-specifiers abstract-declarator? 202 | */ 203 | void Sema::VisitorParamDeclarationNode(ParamDeclaration *node) { 204 | node->Spec->Accept(this); 205 | node->Dec->BaseTy = node->Spec->Ty; 206 | node->Dec->Accept(this); 207 | node->Ty = node->Dec->Ty; 208 | 209 | auto param = std::make_shared(); 210 | param->Ty = node->Ty; 211 | param->Ty = param->Ty->AdjustParameter(param->Ty); 212 | param->Tok = node->Dec->Tok; 213 | node->FunTy->Params.push_back(param); 214 | } 215 | 216 | void Sema::VisitorStructSpecifierNode(StructSpecifier *node) { 217 | 218 | std::shared_ptr tag; 219 | std::shared_ptr ty; 220 | TypeClass cls = node->Cls == DeclClass::StructSpecifier ? TypeClass::Struct : TypeClass::Union; 221 | if (!node->Id.empty() && !node->HasLBrace) { 222 | /// struct-or-union id 223 | tag = SymTable.FindTag(node->Id); 224 | if (tag == nullptr) { 225 | ty = std::make_shared(cls); 226 | tag = SymTable.AddTag(node->Id, ty, node->Tok->Location); 227 | }else { 228 | ty = std::dynamic_pointer_cast(tag->Ty); 229 | if (ty->TyCls != cls) { 230 | SemaDiag(node->Tok->Location, "Inconsistent tag declaration."); 231 | } 232 | } 233 | }else if (node->Id.empty() && node->HasLBrace) { 234 | /// struct-or-union {struct-declaration-list} 235 | ty = std::make_shared(cls); 236 | ty->Complete = true; 237 | }else if (!node->Id.empty() && node->HasLBrace) { 238 | /// struct-or-union id {struct-declaration-list} 239 | tag = SymTable.FindTag(node->Id); 240 | if (tag == nullptr) { 241 | ty = std::make_shared(cls); 242 | ty->Complete = true; 243 | tag = SymTable.AddTag(node->Id, ty, node->Tok->Location); 244 | }else { 245 | if (tag->Level < SymTable.Level) { 246 | ty = std::make_shared(cls); 247 | ty->Complete = true; 248 | tag = SymTable.AddTag(node->Id, ty, node->Tok->Location); 249 | }else { 250 | ty = std::dynamic_pointer_cast(tag->Ty); 251 | if (ty->TyCls != cls) { 252 | SemaDiag(node->Tok->Location, "use of '%s' with tag type that does not match previous declaration", 253 | tag->Name.data()); 254 | } 255 | if (ty->Complete) { 256 | SemaDiag(node->Tok->Location, "redefinition"); 257 | } 258 | ty->Complete = true; 259 | } 260 | } 261 | } 262 | for (auto &decl : node->DeclList) { 263 | decl->RecordTy = ty; 264 | decl->Accept(this); 265 | } 266 | 267 | ty->FinishLayout(0); 268 | 269 | node->Ty = ty; 270 | } 271 | 272 | void Sema::VisitorStructDeclarationNode(StructDeclaration *node) 273 | { 274 | node->Spec->Accept(this); 275 | 276 | if (node->DecList.size() == 0) 277 | { 278 | if(node->Spec->Ty->IsRecordTy()) { 279 | /** 280 | struct A{ 281 | struct{ 282 | int b; 283 | ^ here 284 | }; 285 | }; 286 | */ 287 | if (node->Spec->TagName.empty()) { 288 | node->RecordTy->AddField(std::make_shared(node->Spec->Ty, 0)); 289 | return; 290 | } 291 | } 292 | /** 293 | struct A{ 294 | struct C{ 295 | int b; 296 | ^ unable to use, ignore, warning 297 | }; 298 | }; 299 | 300 | struct A {int;} 301 | ^ unable to use, ignore, warning 302 | */ 303 | return; 304 | } 305 | 306 | /** 307 | * struct D { 308 | * struct Data {int a; int b;} s1, s2; 309 | * ^ ^ 310 | * } 311 | */ 312 | for (auto &dec : node->DecList) { 313 | dec->RecordTy = node->RecordTy; 314 | dec->BaseTy = node->Spec->Ty; 315 | dec->Accept(this); 316 | dec->Ty = dec->Dec->Ty; 317 | } 318 | } 319 | 320 | /** 321 | struct-declarator: 322 | declarator 323 | declarator? : constant-expression 324 | */ 325 | void Sema::VisitorStructDeclaratorNode(StructDeclarator *node) 326 | { 327 | if (node->Dec != nullptr) 328 | { 329 | node->Dec->BaseTy = node->BaseTy; 330 | node->Dec->Accept(this); 331 | node->Ty = node->Dec->Ty; 332 | node->Id = node->Dec->Id; 333 | }else { 334 | node->Ty = node->BaseTy; 335 | } 336 | 337 | if (!node->Id.empty() && node->RecordTy->FindField(node->Id) != nullptr) 338 | { 339 | SemaDiag(node->Tok->Location, "member redefinition"); 340 | } 341 | node->RecordTy->AddField(std::make_shared(node->Id, node->Ty, 0)); 342 | } 343 | 344 | void Sema::VisitorEnumSpecifierNode(EnumSpecifier *node) { 345 | 346 | } 347 | 348 | void Sema::VisitorEnumDeclaratorNode(EnumDeclarator *node) { 349 | 350 | } 351 | 352 | void Sema::VisitorDeclSpecTokenNode(DeclSpecToken *node) { 353 | /// nop 354 | } 355 | 356 | void Sema::CheckLocalDeclaration(Declaration *decl) 357 | { 358 | decl->Spec->Accept(this); 359 | 360 | for (auto &initDec : decl->DecList) 361 | { 362 | initDec->BaseTy = decl->Spec->Ty; 363 | initDec->Accept(this); 364 | initDec->Ty = initDec->Dec->Ty; 365 | 366 | std::shared_ptr varSym = SymTable.FindVar(initDec->Id); 367 | if (varSym == nullptr || varSym->Level < SymTable.Level) 368 | { 369 | auto sym = SymTable.AddVariable(initDec->Id, initDec->Ty, initDec->Tok->Location); 370 | if (initDec->Init) { 371 | sym->Init = initDec->Init->IData; 372 | } 373 | initDec->Sym = sym; 374 | CurrentFunc->FSym->Locals.push_back(sym); 375 | }else 376 | { 377 | if(initDec->Ty->TyCls == varSym->Ty->TyCls){ 378 | SemaDiag(initDec->Tok->Location,"redefinition of \'%s\' ",std::string(initDec->Id).data()); 379 | }else{ 380 | SemaDiag(initDec->Tok->Location,"redefinition of \'%s\' as different kind of symbol", std::string(initDec->Id).data()); 381 | } 382 | } 383 | } 384 | } 385 | 386 | void Sema::CheckGlobalDeclaration(Declaration *decl) 387 | { 388 | decl->Spec->Accept(this); 389 | 390 | for (auto &initDec : decl->DecList) { 391 | initDec->BaseTy = decl->Spec->Ty; 392 | initDec->Accept(this); 393 | 394 | if (initDec->Ty->IsFuncTy()) 395 | { 396 | if (initDec->Init) 397 | SemaDiag(initDec->Tok->Location, "please don't initialize function"); 398 | 399 | std::shared_ptr sym = SymTable.FindVar(initDec->Id); 400 | if (sym == nullptr) 401 | sym = SymTable.AddFunction(initDec->Id, initDec->Ty, initDec->Tok->Location); 402 | } 403 | else 404 | { 405 | /** 406 | Check for global variables 407 | */ 408 | std::shared_ptr sym = SymTable.FindVar(initDec->Id); 409 | if (sym == nullptr) 410 | sym = SymTable.AddVariable(initDec->Id, initDec->Ty, initDec->Tok->Location); 411 | 412 | if (initDec->Init) 413 | { 414 | if (sym->Defined){ 415 | SemaDiag(initDec->Tok->Location, "redefinition of %s", std::string(initDec->Id).data()); 416 | } 417 | else{ 418 | sym->Init = initDec->Init->IData; 419 | sym->Defined = true; 420 | } 421 | } 422 | } 423 | } 424 | } 425 | 426 | void Sema::CheckInitializerInternal(Initializer* node) 427 | { 428 | if (node->Ty->IsScalarType()) 429 | { 430 | if(node->LBrace){ 431 | SemaDiag(node->Tok->Location,"braces around scalar initializer"); 432 | } 433 | node->Expr->Accept(this); 434 | 435 | auto iData = std::make_shared(); 436 | iData->Expr = node->Expr; 437 | iData->Next = nullptr; 438 | node->IData = iData; 439 | return; 440 | } 441 | 442 | SemaDiag(node->Tok->Location, "not support yet"); 443 | } 444 | } 445 | -------------------------------------------------------------------------------- /src/Sema/ExprSema.cpp: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: ExprSema.cpp.c 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/31 9 | ***********************************/ 10 | 11 | #include "Sema.h" 12 | 13 | namespace CCC 14 | { 15 | void Sema::VisitorAssignExprNode(AssignExpr *node) { 16 | node->Lhs->Accept(this); 17 | node->Rhs->Accept(this); 18 | node->Ty = node->Lhs->Ty; 19 | } 20 | 21 | void Sema::VisitorSizeOfExprNode(SizeOfExpr *node) { 22 | node->Lhs->Accept(this); 23 | node->Ty = node->Lhs->Ty; 24 | } 25 | 26 | void Sema::VisitorBinaryExprNode(BinaryExpr *node) { 27 | switch (node->BinOp) { 28 | case BinaryOperator::Add: 29 | CheckAddOperator(node); 30 | break; 31 | case BinaryOperator::Sub: 32 | CheckSubOperator(node); 33 | break; 34 | case BinaryOperator::Mul: 35 | case BinaryOperator::Div: { 36 | node->Lhs->Accept(this); 37 | node->Rhs->Accept(this); 38 | node->Ty = node->Lhs->Ty; 39 | if (!node->Lhs->Ty->IsArithTy() && !node->Rhs->Ty->IsArithTy()) { 40 | SemaDiag(node->Tok->Location, "Invalid operands"); 41 | } 42 | break; 43 | } 44 | case BinaryOperator::Equal: 45 | case BinaryOperator::PipeEqual: 46 | case BinaryOperator::Greater: 47 | case BinaryOperator::GreaterEqual: 48 | case BinaryOperator::Lesser: 49 | case BinaryOperator::LesserEqual: { 50 | node->Lhs->Accept(this); 51 | node->Rhs->Accept(this); 52 | node->Ty = Type::LongTy; 53 | break; 54 | } 55 | default: 56 | break; 57 | } 58 | } 59 | 60 | void Sema::VisitorUnaryExprNode(UnaryExpr *node) { 61 | node->Lhs->Accept(this); 62 | switch (node->Uop) 63 | { 64 | case UnaryOperator::Plus: 65 | case UnaryOperator::Minus: { 66 | node->Ty = node->Lhs->Ty; 67 | break; 68 | } 69 | case UnaryOperator::Amp: { 70 | node->Ty = std::make_shared(node->Lhs->Ty); 71 | break; 72 | } 73 | case UnaryOperator::Star: { 74 | if (node->Lhs->Ty->IsPointerTy()) { 75 | node->Ty = std::dynamic_pointer_cast(node->Lhs->Ty)->BaseTy; 76 | }else if (node->Lhs->Ty->IsArrayTy()) { 77 | node->Ty = std::dynamic_pointer_cast(node->Lhs->Ty)->ElementType; 78 | } 79 | else { 80 | SemaDiag(node->Tok->Location, "invalid dereference operation"); 81 | assert(0); 82 | } 83 | break; 84 | } 85 | default: 86 | break; 87 | } 88 | } 89 | 90 | void Sema::VisitorNumExprNode(NumExpr *node) 91 | { 92 | node->Ty = Type::LongTy; 93 | } 94 | 95 | void Sema::VisitorVarExprNode(VarExpr *node) 96 | { 97 | std::shared_ptr sym = SymTable.FindVar(node->VarName); 98 | if (!sym) { 99 | SemaDiag(node->Tok->Location, "Undeclared variable"); 100 | } 101 | node->Sym = sym; 102 | node->Ty = sym->Ty; 103 | } 104 | 105 | void Sema::VisitorFuncCallExprNode(FuncCallExpr *node) { 106 | std::shared_ptr sym = SymTable.FindVar(node->FuncName); 107 | if (sym == nullptr) { 108 | SemaDiag(node->Tok->Location, "Undeclared function"); 109 | } 110 | for (auto &arg : node->Args) { 111 | arg->Accept(this); 112 | } 113 | node->Ty = Type::LongTy; 114 | } 115 | 116 | void Sema::VisitorStmtExprNode(StmtExpr *node) { 117 | SymTable.EnterScope(); 118 | 119 | for (auto &decl : node->Decls) { 120 | decl->Accept(this); 121 | } 122 | 123 | for (auto &stmt : node->Stmts) { 124 | stmt->Accept(this); 125 | } 126 | 127 | SymTable.ExitScope(); 128 | } 129 | 130 | void Sema::VisitorMemberExprNode(MemberExpr *node) 131 | { 132 | node->Lhs->Accept(this); 133 | 134 | if (!node->Lhs->Ty->IsRecordTy()) 135 | SemaDiag(node->Tok->Location, "Invalid left operands"); 136 | 137 | auto rty = std::dynamic_pointer_cast(node->Lhs->Ty); 138 | std::shared_ptr fld = rty->FindField(node->RhsName); 139 | if (fld == nullptr) 140 | SemaDiag(node->Tok->Location, "haven't the filed"); 141 | 142 | node->Ty = fld->Ty; 143 | node->Fld = fld; 144 | } 145 | 146 | void Sema::CheckAddOperator(BinaryExpr *expr) 147 | { 148 | expr->Lhs->Accept(this); 149 | expr->Rhs->Accept(this); 150 | expr->Ty = expr->Lhs->Ty; 151 | 152 | auto lhsTy = AdjustExprTy(expr->Lhs.get()); 153 | auto rhsTy = AdjustExprTy(expr->Rhs.get()); 154 | 155 | if (lhsTy->IsArithTy() && rhsTy->IsArithTy()) { 156 | return; 157 | } 158 | 159 | if (rhsTy->IsObjPtr() && lhsTy->IsIntegerTy()) { 160 | SwapKids(expr); 161 | lhsTy = AdjustExprTy(expr->Lhs.get()); 162 | rhsTy = AdjustExprTy(expr->Rhs.get()); 163 | } 164 | 165 | if (lhsTy->IsObjPtr() && rhsTy->IsIntegerTy()) { 166 | 167 | auto binNode = std::make_shared(BinaryOperator::Mul, expr->Tok); 168 | auto num = std::make_shared(expr->Tok); 169 | num->Value = std::dynamic_pointer_cast(lhsTy)->BaseTy->Size;; 170 | binNode->Lhs = num; 171 | binNode->Rhs = expr->Rhs; 172 | 173 | expr->Rhs = binNode; 174 | expr->Ty = expr->Lhs->Ty; 175 | return; 176 | } 177 | 178 | SemaDiag(expr->Tok->Location, "Invalid operands"); 179 | } 180 | 181 | void Sema::CheckSubOperator(BinaryExpr* expr) 182 | { 183 | expr->Lhs->Accept(this); 184 | expr->Rhs->Accept(this); 185 | expr->Ty = expr->Lhs->Ty; 186 | 187 | auto lhsTy = AdjustExprTy(expr->Lhs.get()); 188 | auto rhsTy = AdjustExprTy(expr->Rhs.get()); 189 | 190 | if (lhsTy->IsArithTy() && rhsTy->IsArithTy()) { 191 | return; 192 | } 193 | 194 | if (lhsTy->IsObjPtr() && rhsTy->IsIntegerTy()) { 195 | 196 | auto binNode = std::make_shared(BinaryOperator::Mul, expr->Tok); 197 | auto num = std::make_shared(expr->Tok); 198 | num->Value = std::dynamic_pointer_cast(lhsTy)->BaseTy->Size;; 199 | binNode->Lhs = num; 200 | binNode->Rhs = expr->Rhs; 201 | 202 | expr->Rhs = binNode; 203 | expr->Ty = expr->Lhs->Ty; 204 | return; 205 | } 206 | 207 | if (lhsTy->IsObjPtr() && rhsTy->IsObjPtr()) { 208 | expr->Ty = Type::LongTy; 209 | 210 | auto num = std::make_shared(expr->Tok); 211 | num->Value = std::dynamic_pointer_cast(lhsTy)->BaseTy->Size;; 212 | 213 | auto divLeft = std::make_shared(BinaryOperator::Div, expr->Tok); 214 | divLeft->Lhs = expr->Lhs; 215 | divLeft->Rhs = num; 216 | 217 | auto divRight = std::make_shared(BinaryOperator::Div, expr->Tok); 218 | divRight->Lhs = expr->Rhs; 219 | divRight->Rhs = num; 220 | 221 | expr->Lhs = divLeft; 222 | expr->Rhs = divRight; 223 | return; 224 | } 225 | 226 | SemaDiag(expr->Tok->Location, "Invalid operands"); 227 | } 228 | 229 | std::shared_ptr Sema::AdjustExprTy(ExprNode *expr) 230 | { 231 | if (expr->Ty->IsFuncTy()) { 232 | return std::make_shared(expr->Ty); 233 | }else if (expr->Ty->IsArrayTy()) { 234 | return std::make_shared(std::dynamic_pointer_cast(expr->Ty)->ElementType); 235 | } 236 | return expr->Ty; 237 | } 238 | 239 | void Sema::SwapKids(BinaryExpr *expr) 240 | { 241 | auto t = expr->Lhs; 242 | expr->Lhs = expr->Rhs; 243 | expr->Rhs = t; 244 | } 245 | } -------------------------------------------------------------------------------- /src/Sema/Sema.cpp: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: SemanticsVisitor.cpp.cc 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/28 9 | ***********************************/ 10 | 11 | #include "Sema.h" 12 | #include 13 | 14 | namespace CCC 15 | { 16 | void Sema::CheckStorageSpecifier(DeclSpecifier *declSpecifier) 17 | { 18 | /// storage class specifier 19 | if (declSpecifier->StorageClsList.size() == 0) { 20 | declSpecifier->SClass = StorageClass::UnSpecified; 21 | }else if (declSpecifier->StorageClsList.size() == 1) { 22 | auto tok = std::dynamic_pointer_cast(declSpecifier->StorageClsList.front())->Tok; 23 | switch (tok->Kind) { 24 | case TokenKind::Auto: 25 | declSpecifier->SClass = StorageClass::Auto; 26 | break; 27 | case TokenKind::Register: 28 | declSpecifier->SClass = StorageClass::Register; 29 | break; 30 | case TokenKind::Static: 31 | declSpecifier->SClass = StorageClass::Static; 32 | break; 33 | case TokenKind::Extern: 34 | declSpecifier->SClass = StorageClass::Extern; 35 | break; 36 | case TokenKind::Typedef: 37 | declSpecifier->SClass = StorageClass::Typedef; 38 | break; 39 | default: 40 | break; 41 | } 42 | }else { 43 | SemaDiag(declSpecifier->Tok->Location, "At most one storage class"); 44 | } 45 | } 46 | 47 | void Sema::CheckTypeSpecifier(DeclSpecifier *declSpecifier) 48 | { 49 | std::shared_ptr ty; 50 | 51 | int tyCnt = 0, signCnt = 0, sizeCnt = 0; 52 | TokenKind size = TokenKind::Eof, sign = TokenKind::Eof; 53 | 54 | for (auto &p : declSpecifier->TySpecList) 55 | { 56 | switch (p->Cls) 57 | { 58 | case DeclClass::StructSpecifier: 59 | case DeclClass::UnionSpecifier: 60 | { 61 | tyCnt++; 62 | p->Accept(this); 63 | ty = p->Ty; 64 | declSpecifier->TagName = std::dynamic_pointer_cast(p)->Id; 65 | break; 66 | } 67 | case DeclClass::EnumSpecifier: 68 | { 69 | tyCnt++; 70 | p->Accept(this); 71 | ty = p->Ty; 72 | declSpecifier->TagName = std::dynamic_pointer_cast(p)->Id; 73 | break; 74 | } 75 | default: 76 | { 77 | auto tok = std::dynamic_pointer_cast(p)->Tok; 78 | switch (tok->Kind) { 79 | case TokenKind::Float: 80 | case TokenKind::Double: { 81 | assert(0); 82 | break; 83 | } 84 | case TokenKind::Void: { 85 | tyCnt++; 86 | ty = Type::VoidTy; 87 | break; 88 | } 89 | case TokenKind::Bool: { 90 | tyCnt++; 91 | ty = Type::BoolTy; 92 | break; 93 | } 94 | case TokenKind::Char: { 95 | tyCnt++; 96 | ty = Type::CharTy; 97 | break; 98 | } 99 | case TokenKind::Int: { 100 | tyCnt++; 101 | ty = Type::IntTy; 102 | break; 103 | } 104 | case TokenKind::Signed: 105 | case TokenKind::UnSigned: { 106 | signCnt++; 107 | sign = tok->Kind; 108 | break; 109 | } 110 | case TokenKind::Short: { 111 | sizeCnt++; 112 | size = tok->Kind; 113 | break; 114 | } 115 | case TokenKind::Long: { 116 | if (size == TokenKind::Long && sizeCnt == 1) { 117 | size = TokenKind::LongLong; 118 | } else { 119 | sizeCnt++; 120 | size = TokenKind::Long; 121 | } 122 | break; 123 | } 124 | default: 125 | assert(0); 126 | } 127 | } 128 | } 129 | } 130 | 131 | ty = tyCnt == 0 ? Type::IntTy : ty; 132 | 133 | if (signCnt > 1 || sizeCnt > 1 || tyCnt > 1) { 134 | goto err; 135 | } 136 | 137 | if (ty == Type::CharTy) { 138 | sign = TokenKind::Eof; 139 | } 140 | 141 | if (ty == Type::IntTy) 142 | { 143 | switch (size) 144 | { 145 | case TokenKind::Short: { 146 | ty = Type::ShortTy; 147 | break; 148 | } 149 | case TokenKind::Long: { 150 | ty = Type::LongTy; 151 | break; 152 | } 153 | case TokenKind::LongLong: { 154 | ty = Type::LongTy; 155 | break; 156 | } 157 | default: 158 | assert(size == TokenKind::Eof); 159 | break; 160 | } 161 | } 162 | else if (sign != TokenKind::Eof || size != TokenKind::Eof) { 163 | goto err; 164 | } 165 | declSpecifier->Ty = ty; 166 | return; 167 | 168 | err: 169 | SemaDiag(declSpecifier->Tok->Location, "Illegal type specifier."); 170 | declSpecifier->Ty = Type::IntTy; 171 | return; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/Sema/Sema.h: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: SemanticsVisitor.h 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/28 9 | ***********************************/ 10 | 11 | #ifndef CCC_SRC_SEMANTICSVISITOR_H 12 | #define CCC_SRC_SEMANTICSVISITOR_H 13 | 14 | #include "AstVisitor.h" 15 | #include "SymbolTable.h" 16 | #include 17 | #include 18 | #include "Decl.h" 19 | #include "Expr.h" 20 | #include "Stmt.h" 21 | #include "Type.h" 22 | #include "Basic/Diag.h" 23 | #include 24 | 25 | namespace CCC 26 | { 27 | class Sema : public AstVisitor 28 | { 29 | private: 30 | SymbolTable SymTable; 31 | Function *CurrentFunc; 32 | public: 33 | void VisitorTranslationUnitNode(TranslationUnit *node) override; 34 | void VisitorFunctionNode(Function *node) override; 35 | void VisitorDeclarationNode(Declaration *node) override; 36 | void VisitorDeclSpecifierNode(DeclSpecifier *node) override; 37 | void VisitorPointerDeclaratorNode(PointerDeclarator *node) override; 38 | void VisitorNameDeclaratorNode(NameDeclarator *node) override; 39 | void VisitorFuncDeclaratorNode(FunctionDeclarator *node) override; 40 | void VisitorArrayDeclaratorNode(ArrayDeclarator *node) override; 41 | void VisitorInitDeclaratorNode(InitDeclarator *node) override; 42 | void VisitorInitializerNode(Initializer *node) override; 43 | void VisitorParamTypeListNode(ParamTypeList *node) override; 44 | void VisitorParamDeclarationNode(ParamDeclaration *node) override; 45 | void VisitorStructSpecifierNode(StructSpecifier *node) override; 46 | void VisitorStructDeclarationNode(StructDeclaration *node) override; 47 | void VisitorStructDeclaratorNode(StructDeclarator *node) override; 48 | void VisitorEnumSpecifierNode(EnumSpecifier *node) override; 49 | void VisitorEnumDeclaratorNode(EnumDeclarator *node) override; 50 | void VisitorDeclSpecTokenNode(DeclSpecToken *node) override; 51 | 52 | void VisitorExprStmtNode(ExprStmtNode *node) override; 53 | void VisitorIfStmtNode(IfStmtNode *node) override; 54 | void VisitorWhileStmtNode(WhileStmtNode *node) override; 55 | void VisitorDoWhileStmtNode(DoWhileStmtNode *node) override; 56 | void VisitorForStmtNode(ForStmtNode *node) override; 57 | void VisitorBlockStmtNode(BlockStmtNode *node) override; 58 | void VisitorReturnStmtNode(ReturnStmtNode *node) override; 59 | void VisitorBreakStmtNode(BreakStmtNode *node) override; 60 | void VisitorContinueStmtNode(ContinueStmtNode *node) override; 61 | void VisitorGotoStmtNode(GotoStmtNode *node) override; 62 | void VisitorLabelStmtNode(LabelStmtNode *node) override; 63 | void VisitorCaseStmtNode(CaseStmtNode *node) override; 64 | void VisitorDefaultStmtNode(DefaultStmtNode *node) override; 65 | void VisitorSwitchStmtNode(SwitchStmtNode *node) override; 66 | 67 | void VisitorAssignExprNode(AssignExpr *node) override; 68 | void VisitorSizeOfExprNode(SizeOfExpr *node) override; 69 | void VisitorBinaryExprNode(BinaryExpr *node) override; 70 | void VisitorUnaryExprNode(UnaryExpr *node) override; 71 | void VisitorNumExprNode(NumExpr *node) override; 72 | void VisitorVarExprNode(VarExpr *node) override; 73 | void VisitorFuncCallExprNode(FuncCallExpr *node) override; 74 | void VisitorStmtExprNode(StmtExpr *node) override; 75 | void VisitorMemberExprNode(MemberExpr *node) override; 76 | 77 | private: 78 | void CheckStorageSpecifier(DeclSpecifier *declSpecifier); 79 | void CheckTypeSpecifier(DeclSpecifier *declSpecifier); 80 | void CheckLocalDeclaration(Declaration *decl); 81 | void CheckGlobalDeclaration(Declaration *decl); 82 | 83 | void CheckAddOperator(BinaryExpr* expr); 84 | void CheckSubOperator(BinaryExpr* expr); 85 | std::shared_ptr AdjustExprTy(ExprNode *expr); 86 | void CheckInitializerInternal(Initializer* init); 87 | 88 | void SwapKids(BinaryExpr *expr); 89 | }; 90 | } 91 | 92 | #endif // CCC_SRC_SEMANTICSVISITOR_H 93 | -------------------------------------------------------------------------------- /src/Sema/StmtSema.cpp: -------------------------------------------------------------------------------- 1 | /********************************** 2 | * File: StmtSema.cpp.c 3 | * 4 | * Author: caipeng 5 | * 6 | * Email: iiicp@outlook.com 7 | * 8 | * Date: 2022/1/31 9 | ***********************************/ 10 | 11 | #include "Sema.h" 12 | 13 | namespace CCC 14 | { 15 | void Sema::VisitorExprStmtNode(ExprStmtNode *node) { 16 | if (node->Lhs) { 17 | node->Lhs->Accept(this); 18 | } 19 | } 20 | void Sema::VisitorIfStmtNode(IfStmtNode *node) { 21 | node->Cond->Accept(this); 22 | node->Then->Accept(this); 23 | if (node->Else) 24 | node->Else->Accept(this); 25 | } 26 | void Sema::VisitorWhileStmtNode(WhileStmtNode *node) { 27 | CurrentFunc->LoopStmts.push(node); 28 | CurrentFunc->Breakables.push(node); 29 | 30 | node->Cond->Accept(this); 31 | node->Then->Accept(this); 32 | 33 | CurrentFunc->LoopStmts.pop(); 34 | CurrentFunc->Breakables.pop(); 35 | } 36 | void Sema::VisitorDoWhileStmtNode(DoWhileStmtNode *node) { 37 | 38 | CurrentFunc->LoopStmts.push(node); 39 | CurrentFunc->Breakables.push(node); 40 | 41 | node->Stmt->Accept(this); 42 | node->Cond->Accept(this); 43 | 44 | CurrentFunc->LoopStmts.pop(); 45 | CurrentFunc->Breakables.pop(); 46 | } 47 | 48 | void Sema::VisitorForStmtNode(ForStmtNode *node) { 49 | CurrentFunc->LoopStmts.push(node); 50 | CurrentFunc->Breakables.push(node); 51 | 52 | if (node->InitExpr) 53 | node->InitExpr->Accept(this); 54 | else if (node->InitDecl) { 55 | SymTable.EnterScope(); 56 | node->InitDecl->Accept(this); 57 | } 58 | if (node->Cond) 59 | node->Cond->Accept(this); 60 | if (node->Inc) 61 | node->Inc->Accept(this); 62 | 63 | /// 如果语句是block语句,就不要重复进入作用域 64 | if (node->Stmt->Cls == StmtNodeClass::BlockStmtNode && node->InitDecl) { 65 | auto blockStmt = std::dynamic_pointer_cast(node->Stmt); 66 | blockStmt->needEnterScope = false; 67 | } 68 | node->Stmt->Accept(this); 69 | 70 | if (node->InitDecl) { 71 | SymTable.ExitScope(); 72 | } 73 | 74 | CurrentFunc->LoopStmts.pop(); 75 | CurrentFunc->Breakables.pop(); 76 | } 77 | void Sema::VisitorBlockStmtNode(BlockStmtNode *node) { 78 | 79 | if (node->needEnterScope) 80 | SymTable.EnterScope(); 81 | 82 | for (auto &decl : node->Decls) { 83 | decl->Accept(this); 84 | } 85 | 86 | for (auto &stmt : node->Stmts) { 87 | stmt->Accept(this); 88 | } 89 | 90 | if (node->needEnterScope) 91 | SymTable.ExitScope(); 92 | } 93 | 94 | void Sema::VisitorReturnStmtNode(ReturnStmtNode *node) { 95 | if (node->Lhs) { 96 | node->Lhs->Accept(this); 97 | } 98 | } 99 | 100 | void Sema::VisitorBreakStmtNode(BreakStmtNode *node) { 101 | if (CurrentFunc->Breakables.empty()) { 102 | SemaDiag(node->Tok->Location, "break shall in loop or switch stmt"); 103 | } 104 | } 105 | 106 | void Sema::VisitorContinueStmtNode(ContinueStmtNode *node) { 107 | if (CurrentFunc->LoopStmts.empty()) { 108 | SemaDiag(node->Tok->Location, "continue shall in loop stmt"); 109 | } 110 | } 111 | 112 | void Sema::VisitorGotoStmtNode(GotoStmtNode *node) { 113 | if (CurrentFunc->LabelsMap.find(node->LabelName) == CurrentFunc->LabelsMap.end()) { 114 | CurrentFunc->LabelsMap[node->LabelName] = std::make_shared