├── .gitignore
├── .idea
├── .gitignore
├── misc.xml
├── modules.xml
└── vcs.xml
├── CMakeLists.txt
├── crystal
├── Lab1BatchTest.sh
├── Lab2BatchTest.sh
├── Lab3BatchTest.sh
├── testLab1
│ ├── SyntaxTest.cmm
│ ├── extra10.cmm
│ ├── extra5.cmm
│ ├── extra6.cmm
│ ├── extra7.cmm
│ ├── extra8.cmm
│ ├── extra9.cmm
│ ├── output
│ │ ├── extra10.cmm.pst
│ │ ├── extra5.cmm.pst
│ │ ├── extra6.cmm.pst
│ │ ├── extra7.cmm.pst
│ │ ├── extra8.cmm.pst
│ │ ├── extra9.cmm.pst
│ │ ├── test1.cmm.pst
│ │ ├── test2.cmm.pst
│ │ ├── test3.cmm.pst
│ │ └── test4.cmm.pst
│ ├── relopTest.cmm
│ ├── test1.cmm
│ ├── test2.cmm
│ ├── test3.cmm
│ └── test4.cmm
├── testLab2
│ ├── extra1.cmm
│ ├── extra2.cmm
│ ├── extra3.cmm
│ ├── extra4.cmm
│ ├── extra5.cmm
│ ├── extra6.cmm
│ ├── output
│ │ ├── extra1.cmm.pst
│ │ ├── extra18.cmm.pst
│ │ ├── extra19.cmm.pst
│ │ ├── extra2.cmm.pst
│ │ ├── extra20.cmm.pst
│ │ ├── extra21.cmm.pst
│ │ ├── extra22.cmm.pst
│ │ ├── extra23.cmm.pst
│ │ ├── extra3.cmm.pst
│ │ ├── extra4.cmm.pst
│ │ ├── extra5.cmm.pst
│ │ ├── extra6.cmm.pst
│ │ ├── test1.cmm.pst
│ │ ├── test10.cmm.pst
│ │ ├── test11.cmm.pst
│ │ ├── test12.cmm.pst
│ │ ├── test13.cmm.pst
│ │ ├── test14.cmm.pst
│ │ ├── test15.cmm.pst
│ │ ├── test16.cmm.pst
│ │ ├── test17.cmm.pst
│ │ ├── test2.cmm.pst
│ │ ├── test3.cmm.pst
│ │ ├── test4.cmm.pst
│ │ ├── test5.cmm.pst
│ │ ├── test6.cmm.pst
│ │ ├── test7.cmm.pst
│ │ ├── test8.cmm.pst
│ │ └── test9.cmm.pst
│ ├── test1.cmm
│ ├── test10.cmm
│ ├── test11.cmm
│ ├── test12.cmm
│ ├── test13.cmm
│ ├── test14.cmm
│ ├── test15.cmm
│ ├── test16.cmm
│ ├── test17.cmm
│ ├── test2.cmm
│ ├── test3.cmm
│ ├── test4.cmm
│ ├── test5.cmm
│ ├── test6.cmm
│ ├── test7.cmm
│ ├── test8.cmm
│ └── test9.cmm
└── testLab3
│ ├── extra1.cmm
│ ├── extra2.cmm
│ ├── test1.cmm
│ └── test2.cmm
├── include
├── CmmParser.tab.h
├── CmmParserTypes.h
├── CmmScanner.tab.h
├── ErrorReporter.h
├── InterCodeGenerator.h
├── Lab1.h
├── Lab2.h
├── Lab3.h
├── SemanticAnalyzer.h
└── Structure
│ ├── ParserNodes.h
│ ├── SemanticInfo.h
│ ├── SimpleArray.h
│ ├── SimpleHashTable.h
│ ├── SimpleList.h
│ ├── SymbolTable.h
│ └── TokenName.h
├── readme.md
└── src
├── CmmLexer.l
├── CmmParser.y
├── ErrorReporter.c
├── InterCodeGenerator.c
├── Lab1.c
├── Lab2.c
├── Lab3.c
├── SemanticAnalyzer.c
└── Structure
├── ParserNodes.c
├── SemanticInfo.c
├── SimpleArray.c
├── SimpleHashTable.c
├── SimpleList.c
├── SymbolTable.c
└── TokenName.c
/.gitignore:
--------------------------------------------------------------------------------
1 | /CmakeDebug/
2 | /CmakeBuild/
3 | /.idea
4 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # 默认忽略的文件
2 | /shelf/
3 | /workspace.xml
4 | # 基于编辑器的 HTTP 客户端请求
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # ~~~~~~Basic CMakeList Settings~~~~~~
2 | cmake_minimum_required(VERSION 3.22)
3 | project(Lab1 C)
4 |
5 | set(CMAKE_C_STANDARD 11)
6 |
7 | # ~~~~~~Variables~~~~~~
8 | set(RequiredMinimumVersion_Flex 2.5.35)
9 | set(RequiredMinimumVersion_Bison 2.5.0)
10 | set(Lab1Source src/Lab1.c)
11 | set(Lab2Source src/Lab2.c)
12 | set(Lab3Source src/Lab3.c)
13 | # ~~~~~~End of Variables~~~~~~
14 |
15 | # Find Flex and Bison
16 | find_package(FLEX REQUIRED)
17 |
18 | if(NOT FLEX_FOUND)
19 | message(FATAL_ERROR "Flex is not found on your system.")
20 | elseif(${FLEX_VERSION} VERSION_LESS ${RequiredMinimumVersion_Flex})
21 | message(FATAL_ERROR "Flex version is less than the required minimum version. Required: ${FLEX_VERSION}")
22 | endif()
23 |
24 | find_package(BISON REQUIRED)
25 |
26 |
27 | if(NOT BISON_FOUND)
28 | message(FATAL_ERROR "Bison is not found on your system.")
29 | elseif(${BISON_VERSION} VERSION_LESS ${RequiredMinimumVersion_Bison})
30 | message(FATAL_ERROR "Bison version is less than the required minimum version. Required: ${BISON_VERSION}")
31 | endif()
32 |
33 | # Set output directories
34 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
35 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
36 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/crystal)
37 |
38 | # Collect source files
39 | aux_source_directory(src SRC)
40 | include_directories(include)
41 |
42 | # Generate lexer and parser
43 | flex_target(Lexer src/CmmLexer.l ${CMAKE_CURRENT_BINARY_DIR}/CmmScanner.c DEFINES_FILE ${CMAKE_CURRENT_SOURCE_DIR}/include/CmmScanner.tab.h COMPILE_FLAGS "-d")
44 | bison_target(Parser src/CmmParser.y ${CMAKE_CURRENT_BINARY_DIR}/CmmParser.c DEFINES_FILE ${CMAKE_CURRENT_SOURCE_DIR}/include/CmmParser.tab.h COMPILE_FLAGS "-d")
45 | add_flex_bison_dependency(Lexer Parser)
46 |
47 | # Add and Link lexer and parser
48 | add_library(Lexer STATIC ${FLEX_Lexer_OUTPUTS})
49 | add_library(Parser STATIC ${BISON_Parser_OUTPUTS})
50 | target_link_libraries(Lexer ${FLEX_LIBRARIES})
51 | target_link_libraries(Parser ${BISON_LIBRARIES})
52 |
53 | # Add Libs
54 | add_library(SimpleContainers STATIC src/Structure/SimpleArray.c src/Structure/SimpleHashTable.c src/Structure/SimpleList.c)
55 | add_library(ErrorReporter STATIC src/ErrorReporter.c)
56 | target_link_libraries(ErrorReporter SimpleContainers)
57 |
58 | add_library(ParserAnalyzer STATIC src/Structure/ParserNodes.c src/Structure/TokenName.c)
59 | target_link_libraries(ParserAnalyzer Parser Lexer ErrorReporter)
60 |
61 | add_library(SemanticAnalyzer STATIC src/Structure/SymbolTable.c src/Structure/SemanticInfo.c src/SemanticAnalyzer.c)
62 | target_link_libraries(SemanticAnalyzer ParserAnalyzer ErrorReporter)
63 |
64 | add_library(InterCodeGenerator STATIC src/InterCodeGenerator.c)
65 | target_link_libraries(InterCodeGenerator SemanticAnalyzer)
66 |
67 | # Compile the project
68 | add_executable(Lab1 ${Lab1Source})
69 | add_executable(Lab2 ${Lab2Source})
70 | add_executable(Lab3 ${Lab3Source})
71 |
72 | # Link the project
73 | target_link_libraries(Lab1 ParserAnalyzer)
74 | target_link_libraries(Lab2 SemanticAnalyzer)
75 | target_link_libraries(Lab3 InterCodeGenerator)
--------------------------------------------------------------------------------
/crystal/Lab1BatchTest.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if [ ! -f Lab1 ]; then
4 | echo "Lab1 not found, please compile it first"
5 | exit 1
6 | fi
7 |
8 | if [ ! -d testLab1 ]; then
9 | echo "test directory not found"
10 | exit 1
11 | fi
12 |
13 | if [ ! -d testLab1/output ]; then
14 | mkdir testLab1/output
15 | fi
16 |
17 | echo "---------------------------------"
18 | for file in testLab1/*.cmm
19 | do
20 | echo "Testing $file"
21 | ./Lab1 $file > "testLab1/output/${file#testLab1/}.pst"
22 | echo "---------------------------------"
23 | done
--------------------------------------------------------------------------------
/crystal/Lab2BatchTest.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if [ ! -f Lab2 ]; then
4 | echo "Lab2 not found, please compile it first"
5 | exit 1
6 | fi
7 |
8 | if [ ! -d testLab2 ]; then
9 | echo "testLab2 directory not found"
10 | exit 1
11 | fi
12 |
13 | if [ ! -d testLab2/output ]; then
14 | mkdir testLab2/output
15 | fi
16 |
17 | echo "---------------------------------"
18 | for file in testLab2/*.cmm
19 | do
20 | echo "Testing $file"
21 | ./Lab2 $file > "testLab2/output/${file#testLab2/}.pst"
22 | echo "---------------------------------"
23 | done
--------------------------------------------------------------------------------
/crystal/Lab3BatchTest.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if [ ! -f Lab3 ]; then
4 | echo "Lab3 not found, please compile it first"
5 | exit 1
6 | fi
7 |
8 | if [ ! -d testLab3 ]; then
9 | echo "testLab3 directory not found"
10 | exit 1
11 | fi
12 |
13 | if [ ! -d testLab3/output ]; then
14 | mkdir testLab3/output
15 | fi
16 |
17 | echo "---------------------------------"
18 | for file in testLab3/*.cmm
19 | do
20 | echo "Testing $file"
21 | ./Lab3 $file > "testLab3/output/${file#testLab3/}.ir"
22 | echo "---------------------------------"
23 | done
--------------------------------------------------------------------------------
/crystal/testLab1/SyntaxTest.cmm:
--------------------------------------------------------------------------------
1 | int main(int a{
2 | }
--------------------------------------------------------------------------------
/crystal/testLab1/extra10.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | /*
4 | comment
5 | /*
6 | nested comment
7 | */
8 | */
9 | int i = 1;
10 | }
--------------------------------------------------------------------------------
/crystal/testLab1/extra5.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | int i = 0123;
4 | int j = 0x3F;
5 | }
--------------------------------------------------------------------------------
/crystal/testLab1/extra6.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | int i = 09;
4 | int j = 0x3G;
5 | }
--------------------------------------------------------------------------------
/crystal/testLab1/extra7.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | float i = 1.05e-4;
4 | }
--------------------------------------------------------------------------------
/crystal/testLab1/extra8.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | float i = 1.05e;
4 | }
--------------------------------------------------------------------------------
/crystal/testLab1/extra9.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | // line comment
4 | /*
5 | block comment
6 | */
7 | int i=1;
8 | }
--------------------------------------------------------------------------------
/crystal/testLab1/output/extra10.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab1/output/extra10.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab1/output/extra5.cmm.pst:
--------------------------------------------------------------------------------
1 | Program (1)
2 | ExtDefList (1)
3 | ExtDef (1)
4 | Specifier (1)
5 | TYPE: int
6 | FunDec (1)
7 | ID: main
8 | LP
9 | RP
10 | CompSt (2)
11 | LC
12 | DefList (3)
13 | Def (3)
14 | Specifier (3)
15 | TYPE: int
16 | DecList (3)
17 | Dec (3)
18 | VarDec (3)
19 | ID: i
20 | ASSIGNOP
21 | Exp (3)
22 | INT: 83
23 | SEMI
24 | DefList (4)
25 | Def (4)
26 | Specifier (4)
27 | TYPE: int
28 | DecList (4)
29 | Dec (4)
30 | VarDec (4)
31 | ID: j
32 | ASSIGNOP
33 | Exp (4)
34 | INT: 63
35 | SEMI
36 | RC
37 |
--------------------------------------------------------------------------------
/crystal/testLab1/output/extra6.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab1/output/extra6.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab1/output/extra7.cmm.pst:
--------------------------------------------------------------------------------
1 | Program (1)
2 | ExtDefList (1)
3 | ExtDef (1)
4 | Specifier (1)
5 | TYPE: int
6 | FunDec (1)
7 | ID: main
8 | LP
9 | RP
10 | CompSt (2)
11 | LC
12 | DefList (3)
13 | Def (3)
14 | Specifier (3)
15 | TYPE: float
16 | DecList (3)
17 | Dec (3)
18 | VarDec (3)
19 | ID: i
20 | ASSIGNOP
21 | Exp (3)
22 | FLOAT: 0.000105
23 | SEMI
24 | RC
25 |
--------------------------------------------------------------------------------
/crystal/testLab1/output/extra8.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab1/output/extra8.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab1/output/extra9.cmm.pst:
--------------------------------------------------------------------------------
1 | Program (1)
2 | ExtDefList (1)
3 | ExtDef (1)
4 | Specifier (1)
5 | TYPE: int
6 | FunDec (1)
7 | ID: main
8 | LP
9 | RP
10 | CompSt (2)
11 | LC
12 | DefList (7)
13 | Def (7)
14 | Specifier (7)
15 | TYPE: int
16 | DecList (7)
17 | Dec (7)
18 | VarDec (7)
19 | ID: i
20 | ASSIGNOP
21 | Exp (7)
22 | INT: 1
23 | SEMI
24 | RC
25 |
--------------------------------------------------------------------------------
/crystal/testLab1/output/test1.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab1/output/test1.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab1/output/test2.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab1/output/test2.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab1/output/test3.cmm.pst:
--------------------------------------------------------------------------------
1 | Program (1)
2 | ExtDefList (1)
3 | ExtDef (1)
4 | Specifier (1)
5 | TYPE: int
6 | FunDec (1)
7 | ID: inc
8 | LP
9 | RP
10 | CompSt (2)
11 | LC
12 | DefList (3)
13 | Def (3)
14 | Specifier (3)
15 | TYPE: int
16 | DecList (3)
17 | Dec (3)
18 | VarDec (3)
19 | ID: i
20 | SEMI
21 | StmtList (4)
22 | Stmt (4)
23 | Exp (4)
24 | Exp (4)
25 | ID: i
26 | ASSIGNOP
27 | Exp (4)
28 | Exp (4)
29 | ID: i
30 | PLUS
31 | Exp (4)
32 | INT: 1
33 | SEMI
34 | RC
35 |
--------------------------------------------------------------------------------
/crystal/testLab1/output/test4.cmm.pst:
--------------------------------------------------------------------------------
1 | Program (1)
2 | ExtDefList (1)
3 | ExtDef (1)
4 | Specifier (1)
5 | StructSpecifier (1)
6 | STRUCT
7 | OptTag (1)
8 | ID: Complex
9 | LC
10 | DefList (3)
11 | Def (3)
12 | Specifier (3)
13 | TYPE: float
14 | DecList (3)
15 | Dec (3)
16 | VarDec (3)
17 | ID: real
18 | COMMA
19 | DecList (3)
20 | Dec (3)
21 | VarDec (3)
22 | ID: image
23 | SEMI
24 | RC
25 | SEMI
26 | ExtDefList (5)
27 | ExtDef (5)
28 | Specifier (5)
29 | TYPE: int
30 | FunDec (5)
31 | ID: main
32 | LP
33 | RP
34 | CompSt (6)
35 | LC
36 | DefList (7)
37 | Def (7)
38 | Specifier (7)
39 | StructSpecifier (7)
40 | STRUCT
41 | Tag (7)
42 | ID: Complex
43 | DecList (7)
44 | Dec (7)
45 | VarDec (7)
46 | ID: x
47 | SEMI
48 | StmtList (8)
49 | Stmt (8)
50 | Exp (8)
51 | Exp (8)
52 | Exp (8)
53 | ID: y
54 | DOT
55 | ID: image
56 | ASSIGNOP
57 | Exp (8)
58 | FLOAT: 3.500000
59 | SEMI
60 | RC
61 |
--------------------------------------------------------------------------------
/crystal/testLab1/relopTest.cmm:
--------------------------------------------------------------------------------
1 | int main ()
2 | {
3 | int i = 1;
4 | int j = 1 == 2;
5 | }
--------------------------------------------------------------------------------
/crystal/testLab1/test1.cmm:
--------------------------------------------------------------------------------
1 | int main ()
2 | {
3 | int i = 1;
4 | int j = ~i;
5 | }
--------------------------------------------------------------------------------
/crystal/testLab1/test2.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | float a[10][2];
4 | int i;
5 | a[5,3] = 1.5;
6 | if (a[1][2] == 0) i = 1 else i = 0;
7 | }
--------------------------------------------------------------------------------
/crystal/testLab1/test3.cmm:
--------------------------------------------------------------------------------
1 | int inc()
2 | {
3 | int i;
4 | i = i + 1;
5 | }
--------------------------------------------------------------------------------
/crystal/testLab1/test4.cmm:
--------------------------------------------------------------------------------
1 | struct Complex
2 | {
3 | float real,image;
4 | };
5 | int main()
6 | {
7 | struct Complex x;
8 | y.image=3.5;
9 | }
--------------------------------------------------------------------------------
/crystal/testLab2/extra1.cmm:
--------------------------------------------------------------------------------
1 | int func(int a);
2 |
3 | int func(int a)
4 | {
5 | return 1;
6 | }
7 |
8 | int main()
9 | {
10 |
11 | }
--------------------------------------------------------------------------------
/crystal/testLab2/extra2.cmm:
--------------------------------------------------------------------------------
1 | struct Position
2 | {
3 | float x,y;
4 | };
5 |
6 | int func(int a);
7 |
8 | int func(struct Position p);
9 |
10 | int main()
11 | {
12 |
13 | }
--------------------------------------------------------------------------------
/crystal/testLab2/extra3.cmm:
--------------------------------------------------------------------------------
1 | int func()
2 | {
3 | int i = 10;
4 | return i;
5 | }
6 |
7 | int main()
8 | {
9 | int i;
10 | i = func();
11 | }
--------------------------------------------------------------------------------
/crystal/testLab2/extra4.cmm:
--------------------------------------------------------------------------------
1 | int func(){
2 | int i = 10;
3 | return i;
4 | }
5 |
6 | int main()
7 | {
8 | int i;
9 | int i, j;
10 | i = func();
11 | }
--------------------------------------------------------------------------------
/crystal/testLab2/extra5.cmm:
--------------------------------------------------------------------------------
1 | struct Temp1
2 | {
3 | int i;
4 | float j;
5 | };
6 | struct Temp2
7 | {
8 | int x;
9 | float y;
10 | };
11 | int main()
12 | {
13 | struct Temp1 t1;
14 | struct Temp2 t2;
15 | t1 = t2;
16 | }
17 |
--------------------------------------------------------------------------------
/crystal/testLab2/extra6.cmm:
--------------------------------------------------------------------------------
1 | struct Temp1
2 | {
3 | int i;
4 | float j;
5 | };
6 |
7 | struct Temp2
8 | {
9 | int x;
10 | };
11 |
12 | int main()
13 | {
14 | struct Temp1 t1;
15 | struct Temp2 t2;
16 | t1 = t2;
17 | }
18 |
--------------------------------------------------------------------------------
/crystal/testLab2/output/extra1.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/extra1.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/extra18.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/extra18.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/extra19.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/extra19.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/extra2.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/extra2.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/extra20.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/extra20.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/extra21.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/extra21.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/extra22.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/extra22.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/extra23.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/extra23.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/extra3.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/extra3.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/extra4.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/extra4.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/extra5.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/extra5.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/extra6.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/extra6.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test1.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test1.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test10.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test10.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test11.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test11.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test12.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test12.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test13.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test13.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test14.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test14.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test15.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test15.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test16.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test16.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test17.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test17.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test2.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test2.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test3.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test3.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test4.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test4.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test5.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test5.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test6.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test6.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test7.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test7.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test8.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test8.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/output/test9.cmm.pst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrystalVapor/HITCompilerPrincipleLab/bed9bf9cdddf9b9e032665d29686d7c78cc535cc/crystal/testLab2/output/test9.cmm.pst
--------------------------------------------------------------------------------
/crystal/testLab2/test1.cmm:
--------------------------------------------------------------------------------
1 | int main(){
2 | int i = 0;
3 | j = i + 1;
4 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test10.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | int i;
4 | i[0];
5 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test11.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | int i;
4 | i(10);
5 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test12.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | int i[10];
4 | i[1.5] = 10;
5 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test13.cmm:
--------------------------------------------------------------------------------
1 | struct Position
2 | {
3 | float x, y;
4 | };
5 |
6 | int main()
7 | {
8 | int i;
9 | i.x;
10 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test14.cmm:
--------------------------------------------------------------------------------
1 | struct Position
2 | {
3 | float x, y;
4 | };
5 | int main()
6 | {
7 | struct Position p;
8 | if (p.n == 3.7)
9 | return 0;
10 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test15.cmm:
--------------------------------------------------------------------------------
1 | struct Position
2 | {
3 | float x, y;
4 | int x;
5 | };
6 | int main()
7 | {
8 |
9 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test16.cmm:
--------------------------------------------------------------------------------
1 | struct Position
2 | {
3 | float x;
4 | };
5 |
6 | struct Position
7 | {
8 | int y;
9 | };
10 |
11 | int main()
12 | {
13 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test17.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | struct Position pos;
4 | }
5 |
--------------------------------------------------------------------------------
/crystal/testLab2/test2.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | int i = 0;
4 | inc(i);
5 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test3.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | int i, j;
4 | int i;
5 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test4.cmm:
--------------------------------------------------------------------------------
1 | int func(int i)
2 | {
3 | return i;
4 | }
5 |
6 | int func()
7 | {
8 | return 0;
9 | }
10 |
11 | int main()
12 | {
13 | }
14 |
--------------------------------------------------------------------------------
/crystal/testLab2/test5.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | int i;
4 | i = 3.7;
5 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test6.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | int i;
4 | 10 = i;
5 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test7.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | float j;
4 | 10 + j;
5 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test8.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | float j = 1.7;
4 | return j;
5 | }
--------------------------------------------------------------------------------
/crystal/testLab2/test9.cmm:
--------------------------------------------------------------------------------
1 | int func(int i)
2 | {
3 | return i;
4 | }
5 |
6 | int main()
7 | {
8 | func(1, 2);
9 | }
--------------------------------------------------------------------------------
/crystal/testLab3/extra1.cmm:
--------------------------------------------------------------------------------
1 | struct Operands
2 | {
3 | int o1;
4 | int o2;
5 | };
6 |
7 | int add(struct Operands temp)
8 | {
9 | return (temp.o1 + temp.o2);
10 | }
11 |
12 | int main()
13 | {
14 | int n;
15 | struct Operands op;
16 | op.o1 = 1;
17 | op.o2 = 2;
18 | n = add(op);
19 | write(n);
20 | return 0;
21 | }
--------------------------------------------------------------------------------
/crystal/testLab3/extra2.cmm:
--------------------------------------------------------------------------------
1 | int add(int temp[2])
2 | {
3 | return (temp[0] + temp[1]);
4 | }
5 |
6 | int main()
7 | {
8 | int op[2];
9 | int r[1][2];
10 | int i = 0, j = 0;
11 | while (i < 2)
12 | {
13 | while (j < 2)
14 | {
15 | op[j] = i + j;
16 | j = j + 1;
17 | }
18 | r[0][i] = add(op);
19 | write(r[0][i]);
20 | i = i + 1;
21 | j = 0;
22 | }
23 | return 0;
24 | }
25 |
--------------------------------------------------------------------------------
/crystal/testLab3/test1.cmm:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | int n;
4 | n = read();
5 | if (n > 0) write(1);
6 | else if (n < 0) write (-1);
7 | else write(0);
8 | return 0;
9 | }
10 |
--------------------------------------------------------------------------------
/crystal/testLab3/test2.cmm:
--------------------------------------------------------------------------------
1 | int fact(int n)
2 | {
3 | if (n == 1)
4 | return n;
5 | else
6 | return (n * fact(n - 1));
7 | }
8 | int main()
9 | {
10 | int m, result;
11 | m = read();
12 | if (m > 1)
13 | result = fact(m);
14 | else
15 | result = 1;
16 | write(result);
17 | return 0;
18 | }
19 |
--------------------------------------------------------------------------------
/include/CmmParser.tab.h:
--------------------------------------------------------------------------------
1 | /* A Bison parser, made by GNU Bison 3.8.2. */
2 |
3 | /* Bison interface for Yacc-like parsers in C
4 |
5 | Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
6 | Inc.
7 |
8 | This program is free software: you can redistribute it and/or modify
9 | it under the terms of the GNU General Public License as published by
10 | the Free Software Foundation, either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have received a copy of the GNU General Public License
19 | along with this program. If not, see . */
20 |
21 | /* As a special exception, you may create a larger work that contains
22 | part or all of the Bison parser skeleton and distribute that work
23 | under terms of your choice, so long as that work isn't itself a
24 | parser generator using the skeleton or a modified version thereof
25 | as a parser skeleton. Alternatively, if you modify or redistribute
26 | the parser skeleton itself, you may (at your option) remove this
27 | special exception, which will cause the skeleton and the resulting
28 | Bison output files to be licensed under the GNU General Public
29 | License without this special exception.
30 |
31 | This special exception was added by the Free Software Foundation in
32 | version 2.2 of Bison. */
33 |
34 | /* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
35 | especially those whose name start with YY_ or yy_. They are
36 | private implementation details that can be changed or removed. */
37 |
38 | #ifndef YY_YY_HOME_CRYSTAL_COMPILERPRICIPLE_LAB_INCLUDE_CMMPARSER_TAB_H_INCLUDED
39 | # define YY_YY_HOME_CRYSTAL_COMPILERPRICIPLE_LAB_INCLUDE_CMMPARSER_TAB_H_INCLUDED
40 | /* Debug traces. */
41 | #ifndef YYDEBUG
42 | # define YYDEBUG 0
43 | #endif
44 | #if YYDEBUG
45 | extern int yydebug;
46 | #endif
47 |
48 | /* Token kinds. */
49 | #ifndef YYTOKENTYPE
50 | # define YYTOKENTYPE
51 | enum yytokentype
52 | {
53 | YYEMPTY = -2,
54 | YYEOF = 0, /* "end of file" */
55 | YYerror = 256, /* error */
56 | YYUNDEF = 257, /* "invalid token" */
57 | INT = 258, /* INT */
58 | FLOAT = 259, /* FLOAT */
59 | ID = 260, /* ID */
60 | SEMI = 261, /* SEMI */
61 | COMMA = 262, /* COMMA */
62 | ASSIGNOP = 263, /* ASSIGNOP */
63 | EQ = 264, /* EQ */
64 | NEQ = 265, /* NEQ */
65 | LE = 266, /* LE */
66 | LT = 267, /* LT */
67 | GE = 268, /* GE */
68 | GT = 269, /* GT */
69 | PLUS = 270, /* PLUS */
70 | MINUS = 271, /* MINUS */
71 | STAR = 272, /* STAR */
72 | DIV = 273, /* DIV */
73 | AND = 274, /* AND */
74 | OR = 275, /* OR */
75 | DOT = 276, /* DOT */
76 | NOT = 277, /* NOT */
77 | TYPE = 278, /* TYPE */
78 | LP = 279, /* LP */
79 | RP = 280, /* RP */
80 | LB = 281, /* LB */
81 | RB = 282, /* RB */
82 | LC = 283, /* LC */
83 | RC = 284, /* RC */
84 | STRUCT = 285, /* STRUCT */
85 | RETURN = 286, /* RETURN */
86 | IF = 287, /* IF */
87 | ELSE = 288, /* ELSE */
88 | WHILE = 289, /* WHILE */
89 | LELSE = 290, /* LELSE */
90 | pri3 = 291, /* pri3 */
91 | pri2 = 292, /* pri2 */
92 | pri1 = 293, /* pri1 */
93 | pri0 = 294 /* pri0 */
94 | };
95 | typedef enum yytokentype yytoken_kind_t;
96 | #endif
97 |
98 | /* Value type. */
99 | #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
100 | union YYSTYPE
101 | {
102 | #line 13 "/home/crystal/compilerPriciple/Lab/src/CmmParser.y"
103 |
104 | ParserNode_I nodeIndex;
105 |
106 | #line 107 "/home/crystal/compilerPriciple/Lab/include/CmmParser.tab.h"
107 |
108 | };
109 | typedef union YYSTYPE YYSTYPE;
110 | # define YYSTYPE_IS_TRIVIAL 1
111 | # define YYSTYPE_IS_DECLARED 1
112 | #endif
113 |
114 |
115 | extern YYSTYPE yylval;
116 |
117 |
118 | int yyparse (void);
119 |
120 |
121 | #endif /* !YY_YY_HOME_CRYSTAL_COMPILERPRICIPLE_LAB_INCLUDE_CMMPARSER_TAB_H_INCLUDED */
122 |
--------------------------------------------------------------------------------
/include/CmmParserTypes.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/17.
3 | //
4 |
5 | #ifndef LAB1_CMMPARSERTYPES_H
6 | #define LAB1_CMMPARSERTYPES_H
7 |
8 | struct SimpleArray_s;
9 | typedef struct SimpleArray_s* SimpleArray_t;
10 | enum yytokentype;
11 | typedef enum yytokentype yytoken;
12 |
13 | typedef struct ParserNode_s* ParserNode_t;
14 | typedef struct ParserNode_s ParserNode;
15 | typedef SimpleArray_t ParserNodeIndexContainer_t;
16 | typedef int ParserNode_I;
17 |
18 | typedef enum SyntaxToken_e{
19 | PROGRAM = 513,
20 | EXT_DEF_LIST = 514,
21 | EXT_DEF = 515,
22 | EXT_DEC_LIST = 516,
23 | SPECIFIER = 517,
24 | STRUCT_SPECIFIER = 518,
25 | OPT_TAG = 519,
26 | TAG = 520,
27 | VAR_DEC = 521,
28 | FUN_DEC = 522,
29 | VAR_LIST = 523,
30 | PARAM_DEC = 524,
31 | COMP_STM = 525,
32 | STMT_LIST = 526,
33 | STMT = 527,
34 | DEF_LIST = 528,
35 | DEF = 529,
36 | DEC_LIST = 530,
37 | DEC = 531,
38 | EXP = 532,
39 | ARGS = 533
40 | }SyntaxToken;
41 |
42 | struct YYSTYPE_s{
43 | ParserNode_I nodeIndex;
44 | };
45 | typedef struct YYSTYPE_s YYSTYPE;
46 |
47 | #define YYSTYPE_IS_DECLARED 1
48 | #include "CmmParser.tab.h"
49 |
50 | struct SemanticInfo_s;
51 |
52 | struct ParserNode_s{
53 | int token;
54 | int lineNum;
55 | ParserNodeIndexContainer_t children;
56 | union{
57 | int intVal;
58 | float floatVal;
59 | char* ID;
60 | };
61 | struct SemanticInfo_s* semanticInfo;
62 | };
63 |
64 | #ifndef NOINCLUDE_CMM_SCANNER_TAB_H
65 | #include "CmmScanner.tab.h"
66 | #endif
67 |
68 | #define IS_SYNTAX_TOKEN(token) ((token) >= PROGRAM && (token) <= ARGS)
69 | #define IS_TERMINAL_TOKEN(token) ((token) >= INT && (token) <= WHILE)
70 |
71 | #include "Structure/TokenName.h"
72 | #include "Structure/SimpleArray.h"
73 |
74 | #define NO_LINE_NUMBER (0)
75 | #endif //LAB1_CMMPARSERTYPES_H
76 |
--------------------------------------------------------------------------------
/include/CmmScanner.tab.h:
--------------------------------------------------------------------------------
1 | #ifndef yyHEADER_H
2 | #define yyHEADER_H 1
3 | #define yyIN_HEADER 1
4 |
5 | #line 6 "/home/crystal/compilerPriciple/Lab/include/CmmScanner.tab.h"
6 |
7 | #line 8 "/home/crystal/compilerPriciple/Lab/include/CmmScanner.tab.h"
8 |
9 | #define YY_INT_ALIGNED short int
10 |
11 | /* A lexical scanner generated by flex */
12 |
13 | /* %not-for-header */
14 |
15 | #define FLEX_SCANNER
16 | #define YY_FLEX_MAJOR_VERSION 2
17 | #define YY_FLEX_MINOR_VERSION 6
18 | #define YY_FLEX_SUBMINOR_VERSION 4
19 | #if YY_FLEX_SUBMINOR_VERSION > 0
20 | #define FLEX_BETA
21 | #endif
22 |
23 | /* %if-c++-only */
24 | /* %endif */
25 |
26 | /* %if-c-only */
27 |
28 | /* %endif */
29 |
30 | /* %if-c-only */
31 |
32 | /* %endif */
33 |
34 | /* First, we deal with platform-specific or compiler-specific issues. */
35 |
36 | /* begin standard C headers. */
37 | /* %if-c-only */
38 | #include
39 | #include
40 | #include
41 | #include
42 | /* %endif */
43 |
44 | /* %if-tables-serialization */
45 | /* %endif */
46 | /* end standard C headers. */
47 |
48 | /* %if-c-or-c++ */
49 | /* flex integer type definitions */
50 |
51 | #ifndef FLEXINT_H
52 | #define FLEXINT_H
53 |
54 | /* C99 systems have . Non-C99 systems may or may not. */
55 |
56 | #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
57 |
58 | /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
59 | * if you want the limit (max/min) macros for int types.
60 | */
61 | #ifndef __STDC_LIMIT_MACROS
62 | #define __STDC_LIMIT_MACROS 1
63 | #endif
64 |
65 | #include
66 | typedef int8_t flex_int8_t;
67 | typedef uint8_t flex_uint8_t;
68 | typedef int16_t flex_int16_t;
69 | typedef uint16_t flex_uint16_t;
70 | typedef int32_t flex_int32_t;
71 | typedef uint32_t flex_uint32_t;
72 | #else
73 | typedef signed char flex_int8_t;
74 | typedef short int flex_int16_t;
75 | typedef int flex_int32_t;
76 | typedef unsigned char flex_uint8_t;
77 | typedef unsigned short int flex_uint16_t;
78 | typedef unsigned int flex_uint32_t;
79 |
80 | /* Limits of integral types. */
81 | #ifndef INT8_MIN
82 | #define INT8_MIN (-128)
83 | #endif
84 | #ifndef INT16_MIN
85 | #define INT16_MIN (-32767-1)
86 | #endif
87 | #ifndef INT32_MIN
88 | #define INT32_MIN (-2147483647-1)
89 | #endif
90 | #ifndef INT8_MAX
91 | #define INT8_MAX (127)
92 | #endif
93 | #ifndef INT16_MAX
94 | #define INT16_MAX (32767)
95 | #endif
96 | #ifndef INT32_MAX
97 | #define INT32_MAX (2147483647)
98 | #endif
99 | #ifndef UINT8_MAX
100 | #define UINT8_MAX (255U)
101 | #endif
102 | #ifndef UINT16_MAX
103 | #define UINT16_MAX (65535U)
104 | #endif
105 | #ifndef UINT32_MAX
106 | #define UINT32_MAX (4294967295U)
107 | #endif
108 |
109 | #ifndef SIZE_MAX
110 | #define SIZE_MAX (~(size_t)0)
111 | #endif
112 |
113 | #endif /* ! C99 */
114 |
115 | #endif /* ! FLEXINT_H */
116 |
117 | /* %endif */
118 |
119 | /* begin standard C++ headers. */
120 | /* %if-c++-only */
121 | /* %endif */
122 |
123 | /* TODO: this is always defined, so inline it */
124 | #define yyconst const
125 |
126 | #if defined(__GNUC__) && __GNUC__ >= 3
127 | #define yynoreturn __attribute__((__noreturn__))
128 | #else
129 | #define yynoreturn
130 | #endif
131 |
132 | /* %not-for-header */
133 |
134 | /* %not-for-header */
135 |
136 | /* %if-reentrant */
137 | /* %endif */
138 |
139 | /* %if-not-reentrant */
140 |
141 | /* %endif */
142 |
143 | /* Size of default input buffer. */
144 | #ifndef YY_BUF_SIZE
145 | #ifdef __ia64__
146 | /* On IA-64, the buffer size is 16k, not 8k.
147 | * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
148 | * Ditto for the __ia64__ case accordingly.
149 | */
150 | #define YY_BUF_SIZE 32768
151 | #else
152 | #define YY_BUF_SIZE 16384
153 | #endif /* __ia64__ */
154 | #endif
155 |
156 | #ifndef YY_TYPEDEF_YY_BUFFER_STATE
157 | #define YY_TYPEDEF_YY_BUFFER_STATE
158 | typedef struct yy_buffer_state *YY_BUFFER_STATE;
159 | #endif
160 |
161 | #ifndef YY_TYPEDEF_YY_SIZE_T
162 | #define YY_TYPEDEF_YY_SIZE_T
163 | typedef size_t yy_size_t;
164 | #endif
165 |
166 | /* %if-not-reentrant */
167 | extern int yyleng;
168 | /* %endif */
169 |
170 | /* %if-c-only */
171 | /* %if-not-reentrant */
172 | extern FILE *yyin, *yyout;
173 | /* %endif */
174 | /* %endif */
175 |
176 | #ifndef YY_STRUCT_YY_BUFFER_STATE
177 | #define YY_STRUCT_YY_BUFFER_STATE
178 | struct yy_buffer_state
179 | {
180 | /* %if-c-only */
181 | FILE *yy_input_file;
182 | /* %endif */
183 |
184 | /* %if-c++-only */
185 | /* %endif */
186 |
187 | char *yy_ch_buf; /* input buffer */
188 | char *yy_buf_pos; /* current position in input buffer */
189 |
190 | /* Size of input buffer in bytes, not including room for EOB
191 | * characters.
192 | */
193 | int yy_buf_size;
194 |
195 | /* Number of characters read into yy_ch_buf, not including EOB
196 | * characters.
197 | */
198 | int yy_n_chars;
199 |
200 | /* Whether we "own" the buffer - i.e., we know we created it,
201 | * and can realloc() it to grow it, and should free() it to
202 | * delete it.
203 | */
204 | int yy_is_our_buffer;
205 |
206 | /* Whether this is an "interactive" input source; if so, and
207 | * if we're using stdio for input, then we want to use getc()
208 | * instead of fread(), to make sure we stop fetching input after
209 | * each newline.
210 | */
211 | int yy_is_interactive;
212 |
213 | /* Whether we're considered to be at the beginning of a line.
214 | * If so, '^' rules will be active on the next match, otherwise
215 | * not.
216 | */
217 | int yy_at_bol;
218 |
219 | int yy_bs_lineno; /**< The line count. */
220 | int yy_bs_column; /**< The column count. */
221 |
222 | /* Whether to try to fill the input buffer when we reach the
223 | * end of it.
224 | */
225 | int yy_fill_buffer;
226 |
227 | int yy_buffer_status;
228 |
229 | };
230 | #endif /* !YY_STRUCT_YY_BUFFER_STATE */
231 |
232 | /* %if-c-only Standard (non-C++) definition */
233 | /* %not-for-header */
234 |
235 | /* %endif */
236 |
237 | /* %if-c-only Standard (non-C++) definition */
238 |
239 | /* %if-not-reentrant */
240 | /* %not-for-header */
241 |
242 | /* %endif */
243 |
244 | void yyrestart ( FILE *input_file );
245 | void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer );
246 | YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size );
247 | void yy_delete_buffer ( YY_BUFFER_STATE b );
248 | void yy_flush_buffer ( YY_BUFFER_STATE b );
249 | void yypush_buffer_state ( YY_BUFFER_STATE new_buffer );
250 | void yypop_buffer_state ( void );
251 |
252 | YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size );
253 | YY_BUFFER_STATE yy_scan_string ( const char *yy_str );
254 | YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len );
255 |
256 | /* %endif */
257 |
258 | void *yyalloc ( yy_size_t );
259 | void *yyrealloc ( void *, yy_size_t );
260 | void yyfree ( void * );
261 |
262 | /* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */
263 | /* Begin user sect3 */
264 |
265 | #define FLEX_DEBUG
266 |
267 | extern int yylineno;
268 |
269 | extern char *yytext;
270 | #ifdef yytext_ptr
271 | #undef yytext_ptr
272 | #endif
273 | #define yytext_ptr yytext
274 |
275 | /* %if-c-only Standard (non-C++) definition */
276 |
277 | /* %endif */
278 |
279 | #ifdef YY_HEADER_EXPORT_START_CONDITIONS
280 | #define INITIAL 0
281 |
282 | #endif
283 |
284 | #ifndef YY_NO_UNISTD_H
285 | /* Special case for "unistd.h", since it is non-ANSI. We include it way
286 | * down here because we want the user's section 1 to have been scanned first.
287 | * The user has a chance to override it with an option.
288 | */
289 | /* %if-c-only */
290 | #include
291 | /* %endif */
292 | /* %if-c++-only */
293 | /* %endif */
294 | #endif
295 |
296 | #ifndef YY_EXTRA_TYPE
297 | #define YY_EXTRA_TYPE void *
298 | #endif
299 |
300 | /* %if-c-only Reentrant structure and macros (non-C++). */
301 | /* %if-reentrant */
302 | /* %if-c-only */
303 |
304 | /* %endif */
305 | /* %if-reentrant */
306 | /* %endif */
307 | /* %endif End reentrant structures and macros. */
308 |
309 | /* Accessor methods to globals.
310 | These are made visible to non-reentrant scanners for convenience. */
311 |
312 | int yylex_destroy ( void );
313 |
314 | int yyget_debug ( void );
315 |
316 | void yyset_debug ( int debug_flag );
317 |
318 | YY_EXTRA_TYPE yyget_extra ( void );
319 |
320 | void yyset_extra ( YY_EXTRA_TYPE user_defined );
321 |
322 | FILE *yyget_in ( void );
323 |
324 | void yyset_in ( FILE * _in_str );
325 |
326 | FILE *yyget_out ( void );
327 |
328 | void yyset_out ( FILE * _out_str );
329 |
330 | int yyget_leng ( void );
331 |
332 | char *yyget_text ( void );
333 |
334 | int yyget_lineno ( void );
335 |
336 | void yyset_lineno ( int _line_number );
337 |
338 | /* %if-bison-bridge */
339 | /* %endif */
340 |
341 | /* Macros after this point can all be overridden by user definitions in
342 | * section 1.
343 | */
344 |
345 | #ifndef YY_SKIP_YYWRAP
346 | #ifdef __cplusplus
347 | extern "C" int yywrap ( void );
348 | #else
349 | extern int yywrap ( void );
350 | #endif
351 | #endif
352 |
353 | /* %not-for-header */
354 |
355 | /* %endif */
356 |
357 | #ifndef yytext_ptr
358 | static void yy_flex_strncpy ( char *, const char *, int );
359 | #endif
360 |
361 | #ifdef YY_NEED_STRLEN
362 | static int yy_flex_strlen ( const char * );
363 | #endif
364 |
365 | #ifndef YY_NO_INPUT
366 | /* %if-c-only Standard (non-C++) definition */
367 | /* %not-for-header */
368 |
369 | /* %endif */
370 | #endif
371 |
372 | /* %if-c-only */
373 |
374 | /* %endif */
375 |
376 | /* Amount of stuff to slurp up with each read. */
377 | #ifndef YY_READ_BUF_SIZE
378 | #ifdef __ia64__
379 | /* On IA-64, the buffer size is 16k, not 8k */
380 | #define YY_READ_BUF_SIZE 16384
381 | #else
382 | #define YY_READ_BUF_SIZE 8192
383 | #endif /* __ia64__ */
384 | #endif
385 |
386 | /* Number of entries by which start-condition stack grows. */
387 | #ifndef YY_START_STACK_INCR
388 | #define YY_START_STACK_INCR 25
389 | #endif
390 |
391 | /* %if-tables-serialization structures and prototypes */
392 | /* %not-for-header */
393 |
394 | /* %not-for-header */
395 |
396 | /* Default declaration of generated scanner - a define so the user can
397 | * easily add parameters.
398 | */
399 | #ifndef YY_DECL
400 | #define YY_DECL_IS_OURS 1
401 | /* %if-c-only Standard (non-C++) definition */
402 |
403 | extern int yylex (void);
404 |
405 | #define YY_DECL int yylex (void)
406 | /* %endif */
407 | /* %if-c++-only C++ definition */
408 | /* %endif */
409 | #endif /* !YY_DECL */
410 |
411 | /* %not-for-header */
412 |
413 | /* %if-c++-only */
414 | /* %not-for-header */
415 |
416 | /* %endif */
417 |
418 | /* yy_get_previous_state - get the state just before the EOB char was reached */
419 |
420 | /* %if-c-only */
421 | /* %not-for-header */
422 |
423 | #undef YY_NEW_FILE
424 | #undef YY_FLUSH_BUFFER
425 | #undef yy_set_bol
426 | #undef yy_new_buffer
427 | #undef yy_set_interactive
428 | #undef YY_DO_BEFORE_ACTION
429 |
430 | #ifdef YY_DECL_IS_OURS
431 | #undef YY_DECL_IS_OURS
432 | #undef YY_DECL
433 | #endif
434 |
435 | #ifndef yy_create_buffer_ALREADY_DEFINED
436 | #undef yy_create_buffer
437 | #endif
438 | #ifndef yy_delete_buffer_ALREADY_DEFINED
439 | #undef yy_delete_buffer
440 | #endif
441 | #ifndef yy_scan_buffer_ALREADY_DEFINED
442 | #undef yy_scan_buffer
443 | #endif
444 | #ifndef yy_scan_string_ALREADY_DEFINED
445 | #undef yy_scan_string
446 | #endif
447 | #ifndef yy_scan_bytes_ALREADY_DEFINED
448 | #undef yy_scan_bytes
449 | #endif
450 | #ifndef yy_init_buffer_ALREADY_DEFINED
451 | #undef yy_init_buffer
452 | #endif
453 | #ifndef yy_flush_buffer_ALREADY_DEFINED
454 | #undef yy_flush_buffer
455 | #endif
456 | #ifndef yy_load_buffer_state_ALREADY_DEFINED
457 | #undef yy_load_buffer_state
458 | #endif
459 | #ifndef yy_switch_to_buffer_ALREADY_DEFINED
460 | #undef yy_switch_to_buffer
461 | #endif
462 | #ifndef yypush_buffer_state_ALREADY_DEFINED
463 | #undef yypush_buffer_state
464 | #endif
465 | #ifndef yypop_buffer_state_ALREADY_DEFINED
466 | #undef yypop_buffer_state
467 | #endif
468 | #ifndef yyensure_buffer_stack_ALREADY_DEFINED
469 | #undef yyensure_buffer_stack
470 | #endif
471 | #ifndef yylex_ALREADY_DEFINED
472 | #undef yylex
473 | #endif
474 | #ifndef yyrestart_ALREADY_DEFINED
475 | #undef yyrestart
476 | #endif
477 | #ifndef yylex_init_ALREADY_DEFINED
478 | #undef yylex_init
479 | #endif
480 | #ifndef yylex_init_extra_ALREADY_DEFINED
481 | #undef yylex_init_extra
482 | #endif
483 | #ifndef yylex_destroy_ALREADY_DEFINED
484 | #undef yylex_destroy
485 | #endif
486 | #ifndef yyget_debug_ALREADY_DEFINED
487 | #undef yyget_debug
488 | #endif
489 | #ifndef yyset_debug_ALREADY_DEFINED
490 | #undef yyset_debug
491 | #endif
492 | #ifndef yyget_extra_ALREADY_DEFINED
493 | #undef yyget_extra
494 | #endif
495 | #ifndef yyset_extra_ALREADY_DEFINED
496 | #undef yyset_extra
497 | #endif
498 | #ifndef yyget_in_ALREADY_DEFINED
499 | #undef yyget_in
500 | #endif
501 | #ifndef yyset_in_ALREADY_DEFINED
502 | #undef yyset_in
503 | #endif
504 | #ifndef yyget_out_ALREADY_DEFINED
505 | #undef yyget_out
506 | #endif
507 | #ifndef yyset_out_ALREADY_DEFINED
508 | #undef yyset_out
509 | #endif
510 | #ifndef yyget_leng_ALREADY_DEFINED
511 | #undef yyget_leng
512 | #endif
513 | #ifndef yyget_text_ALREADY_DEFINED
514 | #undef yyget_text
515 | #endif
516 | #ifndef yyget_lineno_ALREADY_DEFINED
517 | #undef yyget_lineno
518 | #endif
519 | #ifndef yyset_lineno_ALREADY_DEFINED
520 | #undef yyset_lineno
521 | #endif
522 | #ifndef yyget_column_ALREADY_DEFINED
523 | #undef yyget_column
524 | #endif
525 | #ifndef yyset_column_ALREADY_DEFINED
526 | #undef yyset_column
527 | #endif
528 | #ifndef yywrap_ALREADY_DEFINED
529 | #undef yywrap
530 | #endif
531 | #ifndef yyget_lval_ALREADY_DEFINED
532 | #undef yyget_lval
533 | #endif
534 | #ifndef yyset_lval_ALREADY_DEFINED
535 | #undef yyset_lval
536 | #endif
537 | #ifndef yyget_lloc_ALREADY_DEFINED
538 | #undef yyget_lloc
539 | #endif
540 | #ifndef yyset_lloc_ALREADY_DEFINED
541 | #undef yyset_lloc
542 | #endif
543 | #ifndef yyalloc_ALREADY_DEFINED
544 | #undef yyalloc
545 | #endif
546 | #ifndef yyrealloc_ALREADY_DEFINED
547 | #undef yyrealloc
548 | #endif
549 | #ifndef yyfree_ALREADY_DEFINED
550 | #undef yyfree
551 | #endif
552 | #ifndef yytext_ALREADY_DEFINED
553 | #undef yytext
554 | #endif
555 | #ifndef yyleng_ALREADY_DEFINED
556 | #undef yyleng
557 | #endif
558 | #ifndef yyin_ALREADY_DEFINED
559 | #undef yyin
560 | #endif
561 | #ifndef yyout_ALREADY_DEFINED
562 | #undef yyout
563 | #endif
564 | #ifndef yy_flex_debug_ALREADY_DEFINED
565 | #undef yy_flex_debug
566 | #endif
567 | #ifndef yylineno_ALREADY_DEFINED
568 | #undef yylineno
569 | #endif
570 | #ifndef yytables_fload_ALREADY_DEFINED
571 | #undef yytables_fload
572 | #endif
573 | #ifndef yytables_destroy_ALREADY_DEFINED
574 | #undef yytables_destroy
575 | #endif
576 | #ifndef yyTABLES_NAME_ALREADY_DEFINED
577 | #undef yyTABLES_NAME
578 | #endif
579 |
580 | #line 140 "/home/crystal/compilerPriciple/Lab/src/CmmLexer.l"
581 |
582 |
583 | #line 584 "/home/crystal/compilerPriciple/Lab/include/CmmScanner.tab.h"
584 | #undef yyIN_HEADER
585 | #endif /* yyHEADER_H */
586 |
--------------------------------------------------------------------------------
/include/ErrorReporter.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/20.
3 | //
4 |
5 | #ifndef LAB1_ERRORREPORTER_H
6 | #define LAB1_ERRORREPORTER_H
7 |
8 | #include
9 |
10 | typedef enum ErrorType_e{
11 | LEXICAL_ERROR_BASE = 0,
12 |
13 | UnrecognizedCharacter,
14 | InvalidIdentifier,
15 | InvalidNumber,
16 | InvalidFloat,
17 |
18 | UNDEF_LEXICAL_ERROR = 49,
19 |
20 | SYNTAX_ERROR_BASE = 50,
21 |
22 | UnexpectedStatement,
23 | UnexpectedDeclaration,
24 | MissingSemicolon,
25 | MissingRightBracket,
26 | MissingRightParenthesis,
27 | MissingComma,
28 | MissingSpecifier,
29 | UnterminatedComment,
30 | UnexpectedExpression,
31 |
32 | UNDEF_SYNTAX_ERROR = 99,
33 |
34 | SEMANTIC_ERROR_BASE = 100,
35 |
36 | UndefinedVariable, // Error 1
37 | UndefinedFunctionCalled, // Error 2
38 | VariableNameRedefinition, // Error 3
39 | FunctionRedefinition, // Error 4
40 | AssignmentTypeMismatch, // Error 5
41 | AssignToRvalue, // Error 6
42 | OperatorTypeMismatch, // Error 7
43 | ReturnTypeMismatch, // Error 8
44 | ParameterListMismatch, // Error 9
45 | ArrayAccessOnNonArray, // Error 10
46 | FunctionCalledOnNonFunction,// Error 11
47 | ArrayIndexTypeMismatch, // Error 12
48 | MemberAccessOnNonStruct, // Error 13
49 | UndefinedStructMember, // Error 14
50 | InvalidMemberDefinition, // Error 15
51 | ConflictStructDefinition, // Error 16
52 | UndefinedStruct, // Error 17
53 | UndefinedExternalFunction, // Error 18
54 | ImplicitFunctionDeclaration,// Error 19
55 |
56 | UNDEF_SEMANTIC_ERROR = 149,
57 | }ErrorType;
58 |
59 | /**
60 | * register an error to reporter, content of externalMessage will be malloc copied
61 | * if there's already an error on the same line, the new one will be ignored
62 | * @param line line number of the error
63 | * @param errorType error type
64 | * @param externalMessage error message
65 | */
66 | void reportError(int line, int errorType, char* externalMessage);
67 |
68 | /**
69 | * register an error to reporter, content of externalMessage will be malloc copied and formatted
70 | * if there's already an error on the same line, the new one will be ignored
71 | * @param line line number of the error
72 | * @param errorType error type
73 | * @param format format string
74 | * @param ... format arguments
75 | */
76 | void reportErrorFormat(int line, int errorType, const char* format, ...);
77 |
78 | /**
79 | * print all errors to file
80 | * @param file file to print
81 | */
82 | void printError(FILE* file);
83 |
84 | /**
85 | * reset the error reporter, clear all errors, free all memory used by the reporter
86 | */
87 | void resetErrorReporter();
88 |
89 | /**
90 | * check if there's any error reported
91 | * @return 0 if no error, otherwise return the number of errors
92 | */
93 | int hasError();
94 |
95 | /**
96 | * do not use, just for disabling the default yyerror function
97 | */
98 | void yyerror(const char* msg);
99 |
100 | #endif //LAB1_ERRORREPORTER_H
101 |
--------------------------------------------------------------------------------
/include/InterCodeGenerator.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/31.
3 | //
4 |
5 | /**
6 | * 碎碎念:实际上这一部分按照我的预期应该是嵌入语义分析器的
7 | * (你可以看出来这一部分跟语义分析几乎是同一个设计思路)
8 | * 但是……这样做的话语义分析器那边复杂度估计会爆炸……
9 | * 所以……狠狠摆了!
10 | */
11 |
12 | #ifndef LAB1_INTERCODEGENERATOR_H
13 | #define LAB1_INTERCODEGENERATOR_H
14 |
15 | #include "CmmParserTypes.h"
16 | #include "Structure/SimpleList.h"
17 | #include "Structure/SymbolTable.h"
18 |
19 | #define MAX_INTERCODE_PARAM 3
20 |
21 | struct InterCodeInfo_s;
22 |
23 | /**
24 | * 这是个虚表,我写上只是为了好玩而已,没必要复现这玩意
25 | * 如果对虚表感到好奇可以找一下相关资料
26 | * 顺带着推荐一下我的知乎专栏,有讲虚表相关的东西(,直接去搜我ID就好
27 | */
28 | typedef struct {
29 | void (*generateInterCode) (struct InterCodeInfo_s* interCodeInfo, FILE* file);
30 | }InterCodeInfo_VT;
31 | typedef InterCodeInfo_VT* InterCodeInfo_VT_t;
32 |
33 | typedef enum{
34 | ICT_TEMP_VAR,
35 | ICT_TEMP_LABEL,
36 | ICT_TEMP_PARAM,
37 | }InterCodeTempType;
38 |
39 | typedef enum {
40 | IC_LABEL = 0,
41 | IC_FUNC,
42 | IC_ASSIGN,
43 | IC_ADD,
44 | IC_SUB,
45 | IC_MUL,
46 | IC_DIV,
47 |
48 | IC_ADDR,
49 | IC_ASSIGN_RDEREF,
50 | IC_ASSIGN_LDEREF,
51 |
52 | IC_GOTO,
53 | IC_EQ_GOTO,
54 | IC_NE_GOTO,
55 | IC_GE_GOTO,
56 | IC_GT_GOTO,
57 | IC_LE_GOTO,
58 | IC_LT_GOTO,
59 |
60 | IC_RETURN,
61 |
62 | IC_DEC,
63 | IC_ARG,
64 | IC_CALL,
65 | IC_PARAM,
66 | IC_READ,
67 | IC_WRITE
68 | }InterCodeType;
69 |
70 | typedef enum{
71 | ICP_INT,
72 | ICP_VAR,
73 | ICP_PARAM,
74 | ICP_LABEL,
75 | }InterCodeParam_Type;
76 |
77 | typedef struct {
78 | InterCodeParam_Type type;
79 | union{
80 | int intVal;
81 | int varID;
82 | int paramID;
83 | char* labelName;
84 | };
85 | int scope;
86 | }InterCodeParam;
87 | typedef InterCodeParam* InterCodeParam_t;
88 |
89 | typedef struct InterCodeInfo_s{
90 | InterCodeInfo_VT_t vptr;
91 | InterCodeType type;
92 | InterCodeParam params[MAX_INTERCODE_PARAM];
93 | }InterCodeInfo;
94 | typedef InterCodeInfo* InterCodeInfo_t;
95 |
96 | /*
97 | * The container for intermediate code
98 | * will be constructed by below level and passed to above level
99 | * codes: the intermediate code generated by below level
100 | * returnType: the return type that is truly used by below level as return value
101 | * returnID: the return value's VarID or ParamID
102 | * specialReply: special result from below level used to reply above level's request
103 | */
104 | typedef struct{
105 | SimpleList_t codes;
106 | InterCodeParam_Type returnType; // use return type so that we can handle the situation that the return value is a parameter
107 | int returnID;
108 | int specialReply;
109 | }InterCodeContainer;
110 | typedef InterCodeContainer* InterCodeContainer_t;
111 | typedef InterCodeContainer_t InterCodeHandle;
112 |
113 | #define REP_NO 0
114 | #define REP_IS_ADDRESS 1
115 |
116 | #define INVALID_INTERCODE_HANDLE (NULL)
117 |
118 | /*
119 | * instructions for generate intermediate code
120 | * will be constructed by above level and passed to below level
121 | * trueLabel: the label for true branch expected by above level
122 | * falseLabel: the label for false branch expected by above level
123 | * specialRequest: special instruction from above level
124 | */
125 | typedef struct{
126 | char* trueLabel;
127 | char* falseLabel;
128 | int specialRequest;
129 | }InterCodeInstruction;
130 | typedef InterCodeInstruction* InterCodeInstruction_t;
131 |
132 | #define REQ_NO 0
133 | #define REQ_ADDRESS 1
134 | #define REQ_NORETURN 2
135 |
136 | /**
137 | * Generate intermediate code for the given syntax tree.
138 | * tree must be valid and has no error.
139 | * @param rootNodeIndex the index of the root node of the syntax tree.
140 | * @param file output file of InterCode.
141 | */
142 | InterCodeHandle generateInterCode(ParserNode_I rootNodeIndex, FILE *file, SymbolTable_t inSymbolTable);
143 |
144 | /**
145 | * End the generation of intermediate code.
146 | * Will clear the memory used for generating intermediate code.
147 | */
148 | void generateInterCode_End();
149 |
150 | /**
151 | * Create a new InterCodeInfo.
152 | * @param type the type of the intermediate code.
153 | * @param paramNum the number of parameters.
154 | * @param va_list the parameters' list packed by Handle
155 | * @return the new InterCodeInfo.
156 | */
157 | InterCodeInfo_t InterCodeInfo_create(InterCodeType type, int paramNum, va_list paramList);
158 |
159 | /**
160 | * Print the Param to buffer.
161 | * @param param the param to print
162 | * @param buffer the buffer to print
163 | * @param bufferSize size of the buffer
164 | * @return characters printed to buffer(including the null terminator)
165 | */
166 | int InterCodeParam_printToBuffer(InterCodeParam* param, char* buffer, int bufferSize);
167 |
168 | /**
169 | * Merge two InterCodeHandle.
170 | * Do not use the two InterCodeHandle after merge, it's not safe.
171 | * Will free the handle merged in the process.
172 | * @param handle1
173 | * @param handle2
174 | * @return merged InterCodeHandle
175 | */
176 | InterCodeHandle InterCodeHandle_merge(InterCodeHandle handle1, InterCodeHandle handle2);
177 |
178 | /**
179 | * Create a new InterCodeHandle.
180 | * @return the new InterCodeHandle.
181 | */
182 | InterCodeHandle InterCodeHandle_create();
183 |
184 | /**
185 | * Add a new InterCode to the InterCodeHandle at the end.
186 | * @param handle the handle to add code.
187 | * @param codeType the type of the code.
188 | * @param paramNum the number of parameters.
189 | * @param ... the parameters, format: [InterCodeParam_type, value]
190 | */
191 | void InterCodeHandle_newCode(InterCodeHandle handle, InterCodeType codeType, int paramNum, ...);
192 |
193 | /**
194 | * Destroy the InterCodeHandle and codes in it.
195 | * @param handle the handle to destroy.
196 | */
197 | void InterCodeHandle_destroy(InterCodeHandle handle);
198 |
199 | /**
200 | * Print the InterCodeHandle to the file.
201 | * @param file the file to print.
202 | * @param handle the handle to print.
203 | */
204 | void InterCodeHandle_print(FILE *file, InterCodeHandle handle);
205 |
206 | /**
207 | * @return if param's a struct/array, return 1
208 | */
209 | int InterCodeGenerator_Helper_isParamAddressReferenced(SymbolInfo_Function_t functionInfo, int paramID);
210 |
211 | #define INTERCODEPARAM_GETLABEL(param) ((param)->labelName)
212 | #define INTERCODEPARAM_GETVAR(param) ((param)->varID)
213 | #define INTERCODEPARAM_GETPARAM(param) ((param)->paramID)
214 | #define INTERCODEPARAM_GETINT(param) ((param)->intVal)
215 |
216 | #define IS_VARIABLE_ID_A_PARAM_ID(variableID) ((variableID) < 0)
217 | #define GET_VARIABLE_ID_FROM_PARAM_ID(paramID) (-(paramID))
218 |
219 | #define INTERCODEINFO_CREATE_AND_ADD(container, type, paramNum, ...) \
220 | do{ \
221 | InterCodeInfo_t interCodeInfo = InterCodeInfo_create(type, paramNum, ##__VA_ARGS__); \
222 | container->codes[container->codeNum++] = interCodeInfo; \
223 | }while(0)
224 |
225 | #endif //LAB1_INTERCODEGENERATOR_H
226 |
--------------------------------------------------------------------------------
/include/Lab1.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by CrystalVapor on 2024/3/9.
3 | //
4 |
5 | #ifndef LAB1_LAB1_H
6 | #define LAB1_LAB1_H
7 |
8 | //#define DEBUG_PARSER_TREE
9 |
10 | int main(int argc, char** argv);
11 |
12 | #endif //LAB1_LAB1_H
13 |
--------------------------------------------------------------------------------
/include/Lab2.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/19.
3 | //
4 |
5 | #ifndef LAB1_LAB2_H
6 | #define LAB1_LAB2_H
7 |
8 | #include "CmmParserTypes.h"
9 |
10 | int main(int argc, char** argv);
11 |
12 | #endif //LAB1_LAB2_H
13 |
--------------------------------------------------------------------------------
/include/Lab3.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/31.
3 | //
4 |
5 | #ifndef LAB1_LAB3_H
6 | #define LAB1_LAB3_H
7 |
8 | int main(int argc, char** argv);
9 |
10 | #endif //LAB1_LAB3_H
11 |
--------------------------------------------------------------------------------
/include/SemanticAnalyzer.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/20.
3 | //
4 |
5 | #ifndef LAB1_SEMANTICANALYZER_H
6 | #define LAB1_SEMANTICANALYZER_H
7 |
8 | struct SymbolTable_s;
9 | typedef struct SymbolTable_s* SymbolTable_t;
10 |
11 | /**
12 | * Analyze the semantic of the parser tree.
13 | * @return the number of semantic errors.
14 | */
15 | int semanticAnalyze(ParserNode_I rootNodeIndex, SymbolTable_t inSymbolTable);
16 |
17 | /**
18 | * End the semantic analyze, free the memory used by the semantic analyzer.
19 | */
20 | void semanticAnalyze_End();
21 |
22 | #endif //LAB1_SEMANTICANALYZER_H
23 |
--------------------------------------------------------------------------------
/include/Structure/ParserNodes.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by m1504 on 2024/3/19.
3 | //
4 |
5 | /*
6 | * 碎碎念:
7 | * 这里是一开始编写的地方,当时过于迷恋动态内存管理,所以将ParserNode的管理写得很复杂。
8 | * 实际上这里parsernode应该使用保存在数组中的指针而非保存数组索引(不直接保存数组内指针的原因是因为可能realloc后失效)
9 | * (再注:不过由于没有移除节点的需求,似乎可以使用块状链表以避免不断少量申请内存产生的内存碎片,同样也可以安全地保存指针)
10 | * 另外就算如此,parsernode的子节点也应该使用一个C数组而非动态数组。
11 | * 不过懒得改了,将就着用吧(
12 | */
13 |
14 | #ifndef LAB1_PARSERNODES_H
15 | #define LAB1_PARSERNODES_H
16 |
17 | #include "CmmParserTypes.h"
18 |
19 | #define INVALID_NODE_INDEX (-1)
20 |
21 | #define GET_NODE(nodeIndex) (getParserNode(nodeIndex))
22 | #define GET_CHILD(nodeIndex, i) (getParserNodeChild(nodeIndex, i))
23 | #define GET_CHILD_NODE(nodeIndex, i) (GET_NODE(GET_CHILD(nodeIndex, i)))
24 | #define GET_CHILD_NUM(nodeIndex) (getParserNodeChildNum(nodeIndex))
25 |
26 | //#define DEBUG_PRINT_PARSER_NODE_INDEX
27 |
28 | void setParserTreeRoot(ParserNode_I InRootIndex);
29 |
30 | ParserNode_I getParserTreeRoot();
31 |
32 | /**
33 | * Create a new parser node in the global node container, will return the index of the new node
34 | * @param symbol the symbol of the node
35 | * @param lineNum the line number of the node
36 | * @param childNum the number of children of the node
37 | * @param children the children of the node
38 | * @param fatherNodeIndex the father node of the node
39 | * @return the index of the new node
40 | */
41 | ParserNode_I newParserNode(int symbol, int lineNum, int childNum, ParserNode_I *children, ParserNode_I fatherNodeIndex);
42 |
43 | /**
44 | * Add the parser node to the global node container
45 | * @param node the parser node to be added
46 | * @return the index of the new node
47 | */
48 | int ParserNodeIndexContainer_addNodeIndex(ParserNodeIndexContainer_t container, ParserNode_I index);
49 |
50 | /**
51 | * Get the parser node from the global node container
52 | * @param index the index of the node
53 | * @return the parser node
54 | */
55 | ParserNode_t getParserNode(ParserNode_I index);
56 |
57 | /**
58 | * Get the child's node index of the parser node
59 | * @param index the index of the father node
60 | * @param childIndex the index of the child(in the children array)
61 | * @return the index of the child's node(in the global node container)
62 | */
63 | ParserNode_I getParserNodeChild(ParserNode_I index, int childIndex);
64 |
65 | /**
66 | * Get the child's node of the parser node
67 | * @param index the index of the father node
68 | * @param childIndex the index of the child(in the children array)
69 | * @return the child's node
70 | */
71 | ParserNode_t getParserNodeChildNode(ParserNode_I index, int childIndex);
72 |
73 | /**
74 | * Get the number of children of the parser node
75 | * @param index the index of the node
76 | * @return the number of children
77 | */
78 | int getParserNodeChildNum(ParserNode_I index);
79 |
80 | /**
81 | * Free the global node container
82 | */
83 | void freeParserNodes();
84 |
85 | /**
86 | * Create a new parser node index container
87 | * @return the new parser node index container
88 | */
89 | ParserNodeIndexContainer_t ParserNodeIndexContainer_createContainer();
90 |
91 | /**
92 | * Get the parser node from the container
93 | * @param container the container
94 | * @param index the index of the node
95 | * @return the parser node
96 | */
97 | ParserNode_t ParserNodeIndexContainer_getNode(ParserNodeIndexContainer_t container, int index);
98 |
99 | /**
100 | * Add children to the parser node
101 | * @param nodeIndex the index of the node
102 | * @param childNum the number of children
103 | * @param children the children
104 | */
105 | void addChildrenToNode(ParserNode_I nodeIndex, int childNum, ParserNode_I* children);
106 |
107 | /**
108 | * Add a child to the parser node
109 | * @param nodeIndex the index of the node
110 | * @param childIndex the index of the child
111 | */
112 | void addChildToNode(ParserNode_I nodeIndex, ParserNode_I childIndex);
113 |
114 | /**
115 | * Convert a string(HEX,DEC,OCT) to an integer
116 | * @param str the string to be converted
117 | * @return integer converted from the string
118 | */
119 | int stoi(const char* str);
120 |
121 | /**
122 | * Get the parser node index from the container
123 | * @param container the container
124 | * @param index the index of the node
125 | * @return the parser node index
126 | */
127 | ParserNode_I ParserNodeIndexContainer_getNodeIndex(ParserNodeIndexContainer_t container, int index);
128 |
129 | /**
130 | * Traverse the parser tree in pre-order and print the tree
131 | * @param nodeIndex the index of the root node
132 | * @param depth the depth of the root node(used for printing)
133 | */
134 | void printParserTree_PreOrder(ParserNode_I nodeIndex, int depth);
135 |
136 | /**
137 | * Print all the nodes in the global node container linearly
138 | */
139 | void printAllNodes();
140 |
141 | /**
142 | * Print the parser node
143 | * @param nodeIndex the index of the node
144 | * @param depth the depth of the node(used for printing)
145 | */
146 | void printParserNode(ParserNode_I nodeIndex, int depth);
147 |
148 | /**
149 | * do not use.
150 | */
151 | void yyerror(const char* msg);
152 |
153 | /**
154 | * Check if the children of the node match the rule
155 | * @param nodeIndex the node to be checked
156 | * @param ruleSize the size of rule
157 | * @param ... rule, should be a list of token(Lexical or Syntax)
158 | * @return 1 if match, 0 if not match
159 | */
160 | int isChildrenMatchRule(ParserNode_I nodeIndex, int ruleSize, ...);
161 |
162 | #endif //LAB1_PARSERNODES_H
163 |
--------------------------------------------------------------------------------
/include/Structure/SemanticInfo.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/19.
3 | //
4 |
5 | #ifndef LAB1_SEMANTICINFO_H
6 | #define LAB1_SEMANTICINFO_H
7 |
8 | #include "Structure/SemanticInfo.h"
9 | #include "Structure/SymbolTable.h"
10 | #include "SimpleArray.h"
11 | #include "SymbolTable.h"
12 |
13 | ////////////////////////////////////////
14 | // SemanticInfo
15 | ////////////////////////////////////////
16 |
17 | typedef struct SemanticInfo_s{
18 | // Rvalue members, following members are only valid when isLValue is false
19 | Symbol_Value_Type valueType;
20 | SymbolInfo_t valueTypeMeta;
21 |
22 | // Semantic information
23 | int isLValue;
24 |
25 | // used for intercode generate
26 | int varID;
27 | }SemanticInfo;
28 | typedef SemanticInfo* SemanticInfo_t;
29 |
30 | /**
31 | * Create a new Lvalue SemanticInfo object
32 | * @note IN Cmm, ALL Lvalue should be Variable
33 | * @param valueType the value type of the LValue
34 | * @param valueInfo the value information of the LValue
35 | * @param semanticInfoList the list to collect recently created semanticInfo, used for garbage collection
36 | * @return a new SemanticInfo object
37 | */
38 | SemanticInfo_t
39 | SemanticInfo_createLvalue(Symbol_Value_Type valueType, SymbolInfo_t valueInfo, SimpleArray_t semanticInfoList);
40 |
41 | /**
42 | * Create a new Rvalue SemanticInfo object
43 | * @note IN Cmm, ALL Rvalue act like a variable
44 | * @param valueType the value type of the RValue
45 | * @param valueInfo the valueTypeMeta information of the RValue
46 | * @param semanticInfoList the list to collect recently created semanticInfo, used for garbage collection
47 | * @return a new SemanticInfo object
48 | */
49 | SemanticInfo_t SemanticInfo_createRvalue(Symbol_Value_Type valueType, SymbolInfo_t valueInfo, SimpleArray_t semanticInfoList);
50 |
51 | /**
52 | * Make a semantic variable to a RValue object whether it is a LValue or RValue
53 | * @param lvalue the LValue object
54 | * @param semanticInfoList the list to collect recently created semanticInfo, used for garbage collection
55 | * @return a new RValue object
56 | */
57 | SemanticInfo_t SemanticInfo_makeRvalue(SemanticInfo_t semanticInfo, SimpleArray_t semanticInfoList);
58 |
59 | /**
60 | * Destroy a SemanticInfo object
61 | * @param semanticInfoToDestroy the SemanticInfo object to be destroyed
62 | */
63 | void SemanticInfo_destroy(void* semanticInfoToDestroy);
64 |
65 | /**
66 | * Compare two SemanticInfo objects' types
67 | * int => int, float => float
68 | * for struct, if their members are matched(order and type), they are matched
69 | * for array, if their element type and dimension count are matched, they are matched
70 | * @param a the first SemanticInfo object
71 | * @param b the second SemanticInfo object
72 | * @return 1 if the two objects are matched, 0 otherwise
73 | */
74 | int SemanticInfo_isTypeMatched(SemanticInfo_t a, SemanticInfo_t b);
75 |
76 | /**
77 | * Check if the given two FunctionInfo have the same return type
78 | * @param a the first FunctionInfo
79 | * @param b the second FunctionInfo
80 | * @return 1 if the two FunctionInfo have the same return type, 0 otherwise
81 | */
82 | int SymbolInfo_Function_isReturnTypeMatched(SymbolInfo_Function_t a, SymbolInfo_Function_t b);
83 |
84 | /**
85 | * Check if the given two FunctionInfo have the same parameter list
86 | * @param a the first FunctionInfo
87 | * @param b the second FunctionInfo
88 | * @return 1 if the two FunctionInfo have the same parameter list, 0 otherwise
89 | */
90 | int SymbolInfo_Function_isParameterListMatched(SymbolInfo_Function_t a, SymbolInfo_Function_t b);
91 |
92 | /**
93 | * Check if the given semanticInfo is the same as the given type(whether it is a RValue or LValue)
94 | * @param semanticInfo the semanticInfo to be checked
95 | * @param type the type to be checked
96 | * @return 1 if the semanticInfo is the same as the given type, 0 otherwise
97 | */
98 | int SemanticInfo_checkValueType(SemanticInfo_t semanticInfo, Symbol_Value_Type type);
99 |
100 | /**
101 | * Check if the value of semanticInfo matched the return type of the functionInfo
102 | * @param functionInfo the functionInfo to be checked
103 | * @param semanticInfo the semanticInfo to be checked
104 | * @return 1 if the value of semanticInfo matched the return type of the functionInfo, 0 otherwise
105 | */
106 | int SemanticInfo_checkReturnType(SymbolInfo_Function_t functionInfo, SemanticInfo_t semanticInfo);
107 |
108 | /**
109 | * Check if the parameter list of the functionInfo matched the given semanticInfos
110 | * @param functionInfo the functionInfo to be checked
111 | * @param semanticInfos the semanticInfos to be checked
112 | * @param paramCount the count of the semanticInfos
113 | * @return 1 if the parameter list of the functionInfo matched the given semanticInfos, 0 otherwise
114 | */
115 | int SemanticInfo_checkParameterList(SymbolInfo_Function_t functionInfo, SemanticInfo_t* semanticInfos, int paramCount);
116 |
117 | /**
118 | * Try to get the memberInfo from the given semanticInfo
119 | * @param semanticInfo the semanticInfo to get from
120 | * @param memberName the member name
121 | * @return the memberInfo, NULL if failed
122 | */
123 | SymbolInfo_Member_t SemanticInfo_getMemberInfo(SemanticInfo_t semanticInfo, const char* memberName);
124 |
125 | /**
126 | * Helper Function to check if the two types are matched
127 | * @param aType type of a
128 | * @param aMeta type meta of a
129 | * @param bType type of b
130 | * @param bMeta type meta of b
131 | * @return 1 if matched, 0 otherwise
132 | */
133 | int SymbolInfo_Helper_isTypeMatched(Symbol_Value_Type aType, SymbolInfo_t aMeta, Symbol_Value_Type bType, SymbolInfo_t bMeta);
134 |
135 | #endif //LAB1_SEMANTICINFO_H
136 |
--------------------------------------------------------------------------------
/include/Structure/SimpleArray.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/17.
3 | //
4 |
5 | #ifndef LAB1_SIMPLEARRAY_H
6 | #define LAB1_SIMPLEARRAY_H
7 |
8 | #define DEFAULT_CAPACITY 100
9 |
10 | typedef void (*Destructor)(void*);
11 |
12 | struct SimpleArray_s{
13 | char* data;
14 | int num;
15 | int capacity;
16 | int typeSize;
17 | };
18 | typedef struct SimpleArray_s* SimpleArray_t;
19 | typedef struct SimpleArray_s SimpleArray;
20 |
21 | /**
22 | * Create a new simple array, the typeSize is the size of the type of the element
23 | * @param typeSize size of the type of the element
24 | * @return created simple array
25 | */
26 | SimpleArray_t SimpleArray_create(int typeSize);
27 |
28 | /**
29 | * Create a new simple array with capacity, the typeSize is the size of the type of the element
30 | * @param typeSize size of the type of the element
31 | * @param capacity capacity of the array
32 | * @return created simple array
33 | */
34 | SimpleArray_t SimpleArray_newArrayWithCapacity(int typeSize, int capacity);
35 |
36 | /**
37 | * Add an element to the simple array's tail, will copy the content of the element to the array
38 | * @param array the simple array
39 | * @param element the element to add
40 | * @return the index of the added element
41 | */
42 | int SimpleArray_addElement(SimpleArray_t array, const void* element);
43 |
44 | /**
45 | * Get the element at the index, will check if the index is valid
46 | * do not save the pointer of the element, it may be invalid after the array is modified
47 | * @param array the simple array
48 | * @param index the index of the element
49 | * @return the element at the index
50 | */
51 | void* SimpleArray_at(SimpleArray_t array, int index);
52 |
53 | /** Free the simple array with destructor, will free the memory of the array and the elements
54 | * Destructor: void(void* pointer_to_the_element)
55 | * @param array the simple array
56 | * @param elementDestructor the destructor of the element, if it's NULL, will not call the destructor
57 | */
58 | void SimpleArray_destroy(SimpleArray_t array, Destructor elementDestructor);
59 |
60 | /**
61 | * Reserve the capacity of the simple array, will change the capacity of the array
62 | * @param array the simple array
63 | * @param capacity the new capacity of the array
64 | */
65 | void SimpleArray_reserve(SimpleArray_t array, int capacity);
66 |
67 | /**
68 | * Set the element at the index, will copy the content of the element to the array
69 | * @param array the simple array
70 | * @param index the index of the element
71 | * @param element the element to set
72 | */
73 | void SimpleArray_setElement(SimpleArray_t array, int index, const void* element);
74 |
75 | /**
76 | * Insert an element to the simple array at the index, will move the elements after the index
77 | * @param array the simple array
78 | * @param index the index to insert
79 | * @param element the element to insert
80 | */
81 | void SimpleArray_insertElement(SimpleArray_t array, int index, void* element);
82 |
83 | /** Remove the element at the index with destructor if it's not NULL, will move the elements after the index
84 | * Destructor: void(void* pointer_to_the_element)
85 | * @param array the simple array
86 | * @param index the index to remove
87 | * @param elementDestructor the destructor of the element, if it's NULL, will not call the destructor
88 | */
89 | void SimpleArray_removeElement(SimpleArray_t array, int index, Destructor elementDestructor);
90 |
91 | /**
92 | * Clear the simple array with destructor, will free the memory of the elements
93 | * Destructor: void(void* pointer_to_the_element)
94 | * @param array the simple array
95 | */
96 | void SimpleArray_clear(SimpleArray_t array);
97 |
98 | /** Resize the simple array, will change the capacity and the size of the array
99 | * be aware that the elements between old size and new size will be random
100 | * @param array the simple array
101 | * @param newSize the new size of the array
102 | */
103 | void SimpleArray_resize(SimpleArray_t array, int newSize);
104 |
105 | /**
106 | * Zero fill the simple array, will fill the array with 0
107 | * @param array the simple array
108 | */
109 | void SimpleArray_zeroFilled(SimpleArray_t array);
110 |
111 | /** pop the element at the back of the simple array with destructor if it's not NULL
112 | * Destructor: void(void* pointer_to_the_element)
113 | * @param array the simple array
114 | * @param elementDestructor the destructor of the element, if it's NULL, will not call the destructor
115 | */
116 | void SimpleArray_popBack(SimpleArray_t array, Destructor elementDestructor);
117 |
118 | /** Push an element to the back of the simple array, will copy the content of the element to the array
119 | * Same as addElement, just an alias of it.
120 | * @param array the simple array
121 | * @param element the element to push
122 | * @return the index of the pushed element
123 | */
124 | int SimpleArray_pushBack(SimpleArray_t array, void* element);
125 |
126 | /**
127 | * Get the element at the back of the simple array
128 | * @param array the simple array
129 | * @return the element at the back
130 | */
131 | void* SimpleArray_back(SimpleArray_t array);
132 |
133 | /** Get the size of the simple array
134 | * @param array the simple array
135 | * @return the size of the array
136 | */
137 | int SimpleArray_size(SimpleArray_t array);
138 |
139 | #endif //LAB1_SIMPLEARRAY_H
140 |
--------------------------------------------------------------------------------
/include/Structure/SimpleHashTable.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by m1504 on 2024/3/20.
3 | //
4 |
5 | #ifndef LAB1_SIMPLEHASHTABLE_H
6 | #define LAB1_SIMPLEHASHTABLE_H
7 |
8 | #include "Structure/SimpleHashTable.h"
9 | #include
10 | #include
11 | #include "SimpleArray.h"
12 |
13 | #define THOUSAND_HASH_TABLE_SIZE 1009
14 | #define DEFAULT_HASH_BUCKET_SIZE 10
15 | struct SimpleHashTable_s;
16 | typedef struct SimpleHashTable_s * SimpleHashTable_t;
17 |
18 | /**
19 | * A hash function that takes a key and returns a hash value.
20 | * @param key the key to be hashed
21 | * @param keySize the size of the key
22 | * @param tableSize the size of the hash table
23 | * @return the hash value of the key
24 | */
25 | typedef int (*HashFunc)(const void* key, int keySize, int tableSize);
26 |
27 | /**
28 | * A compare function that takes two keys and returns 0 if they are the same.
29 | * @param keyA the first key
30 | * @param keyB the second key
31 | * @param keySize the size of the key
32 | * @return 0 if the two keys are the same, otherwise return a non-zero value
33 | */
34 | typedef int (*CompareFunc)(const void* keyA, const void* keyB, int keySize);
35 |
36 | /**
37 | * A Traverse function that takes an element and do something with it.
38 | * @param element the element to be traversed
39 | */
40 | typedef void (*TraverseFunc)(const void* element);
41 |
42 | /**
43 | * An advanced traverse function that takes a key, an element and extra parameters and do something with them.
44 | * @param key the key of the element
45 | * @param keySize the size of the key
46 | * @param element the element to be traversed
47 | * @param extraParamCount the number of extra parameters
48 | * @param ... the extra parameters
49 | */
50 | typedef void (*AdvancedTraverseFunc)(const void* key, int keySize, const void* element, int extraParamCount, ...);
51 |
52 | typedef struct SimpleHashTablePair_s {
53 | void* key;
54 | int keySize;
55 | void* element;
56 | }SimpleHashTablePair;
57 | typedef SimpleHashTablePair* SimpleHashTablePair_t;
58 |
59 | typedef struct SimpleHashTable_s{
60 | HashFunc hashFunc;
61 | CompareFunc compareFunc;
62 | SimpleArray_t data;
63 | int elementSize;
64 | int keySize;
65 | int tableSize;
66 | }SimpleHashTable;
67 | typedef SimpleHashTable* SimpleHashTable_t;
68 |
69 | /**
70 | * Create a hash table with the given element size, hash function and compare function, default table size is THOUSAND_HASH_TABLE_SIZE
71 | * @param elementSize the size of the element
72 | * @param hashFunc the hash function, use NULL to use the default hash function(pjw)
73 | * @param compareFunc the compare function, use NULL to use the default compare function(memcmp)
74 | * @return the created hash table
75 | */
76 | SimpleHashTable_t SimpleHashTable_createHashTable(int elementSize, HashFunc hashFunc, CompareFunc compareFunc);
77 |
78 | /**
79 | * Create a hash table with the given element size, hash function, compare function and table size
80 | * @param elementSize the size of the element
81 | * @param keyHashFunc the hash function for the key, use NULL to use the default hash function(pjw)
82 | * @param keyCompareFunc the compare function for the key, use NULL to use the default compare function(memcmp)
83 | * @param tableSize the size of the hash table
84 | * @return the created hash table
85 | */
86 | SimpleHashTable_t SimpleHashTable_createWithSize(int elementSize, HashFunc keyHashFunc, CompareFunc keyCompareFunc, int tableSize);
87 |
88 | /**
89 | * Destroy the hash table, and call the destructor on every element if it is not NULL
90 | * @param hashTable the hash table to be destroyed
91 | * @param destructorForKey the destructor for the key, use NULL if no destructor is needed
92 | * @param destructorForElement the destructor for the element, use NULL if no destructor is needed
93 | */
94 | void SimpleHashTable_destroy(SimpleHashTable_t hashTable, Destructor destructorForKey, Destructor destructorForElement);
95 |
96 | /**
97 | * Force insert the element with the key, and call the destructor if the key already exists and it is not NULL
98 | * @param hashTable table to insert
99 | * @param key key to insert
100 | * @param keySize size of the key
101 | * @param element element to insert
102 | * @param destructorForKey destructor for the key
103 | * @param destructorForElement destructor for the element
104 | */
105 | void SimpleHashTable_forceInsert(SimpleHashTable_t hashTable, const void* key, int keySize, const void* element, Destructor destructorForKey, Destructor destructorForElement);
106 |
107 | /**
108 | * Insert the element with the key, will not insert if the key already exists
109 | * @param hashTable the hash table to insert
110 | * @param key the key to insert
111 | * @param keySize the size of the key
112 | * @param element the element to insert
113 | * @return 0 if the element is inserted successfully, -1 if the key already exists
114 | */
115 | int SimpleHashTable_insert(SimpleHashTable_t hashTable, const void* key, int keySize, const void* element);
116 |
117 | /**
118 | * Find the element with the key
119 | * @param hashTable the hash table to find
120 | * @param key the key to find
121 | * @param keySize the size of the key
122 | * @return the element with the key, NULL if the key does not exist
123 | */
124 | void* SimpleHashTable_find(SimpleHashTable_t hashTable, const void* key, int keySize);
125 |
126 | /**
127 | * Remove the element with the key, and call the destructor if it is not NULL
128 | * @param hashTable the hash table to remove
129 | * @param key the key to remove
130 | * @param keySize the size of the key
131 | * @param destructorForKey the destructor for the key, use NULL if no destructor is needed
132 | * @param destructorForElement the destructor for the element, use NULL if no destructor is needed
133 | */
134 | void SimpleHashTable_remove(SimpleHashTable_t hashTable, const void* key, int keySize, Destructor destructorForKey, Destructor destructorForElement);
135 |
136 | /**
137 | * Traverse the hash table and call the traverse function on every element
138 | * @param hashTable the hash table to traverse
139 | * @param traverseFunc the traverse function
140 | */
141 | void SimpleHashTable_traverse(SimpleHashTable_t hashTable, TraverseFunc traverseFunc);
142 |
143 | /**
144 | * Traverse the hash table and call the advanced traverse function on every element
145 | * @param hashTable the hash table to traverse
146 | * @param traverseFunc the advanced traverse function
147 | * @param extraParamCount the number of extra parameters
148 | * @param ... the extra parameters
149 | */
150 | void SimpleHashTable_advancedTraverse(SimpleHashTable_t hashTable, AdvancedTraverseFunc traverseFunc, int extraParamCount, ...);
151 |
152 | /**
153 | * Default hash function, use PJW hash algorithm
154 | * @param key the key to be hashed
155 | * @param keySize the size of the key
156 | * @param size the size of the hash table
157 | * @return the hash value of the key
158 | */
159 | int pjwHash(const char* key, int keySize, int size);
160 |
161 | #endif //LAB1_SIMPLEHASHTABLE_H
162 |
--------------------------------------------------------------------------------
/include/Structure/SimpleList.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/4/3.
3 | //
4 |
5 | #ifndef LAB1_SIMPLELIST_H
6 | #define LAB1_SIMPLELIST_H
7 |
8 | typedef struct SimpleListNode_s {
9 | struct SimpleListNode_s *next;
10 | struct SimpleListNode_s *prev;
11 | void *data;
12 | }SimpleListNode;
13 | typedef struct SimpleListNode_s* SimpleListNode_t;
14 |
15 | typedef struct SimpleList_s{
16 | SimpleListNode_t head;
17 | SimpleListNode_t tail;
18 | int size;
19 | }SimpleList;
20 | typedef struct SimpleList_s* SimpleList_t;
21 |
22 | /**
23 | * Create an empty list
24 | * @return new list
25 | */
26 | SimpleList_t SimpleList_create();
27 |
28 | /**
29 | * Destroy a list
30 | * @param list list to destroy
31 | * @param destroyData function to destroy data
32 | * @return NULL
33 | */
34 | SimpleList_t SimpleList_destroy(SimpleList_t list, void (*destroyData)(void* data));
35 |
36 | /**
37 | * Push data to the back of the list, will create a new node
38 | * @param list list to push
39 | * @param data data to push
40 | * @return new node
41 | */
42 | SimpleListNode_t SimpleList_push_back(SimpleList_t list, void* data);
43 |
44 | /**
45 | * Push data to the front of the list, will create a new node
46 | * @param list list to push
47 | * @param data data to push
48 | * @return new node
49 | */
50 | SimpleListNode_t SimpleList_push_front(SimpleList_t list, void* data);
51 |
52 | /**
53 | * Pop the last node of the list
54 | * @param list
55 | * @return the data of the last node
56 | */
57 | void* SimpleList_pop_back(SimpleList_t list);
58 |
59 | /**
60 | * Pop the first node of the list
61 | * @param list
62 | * @return the data of the first node
63 | */
64 | void* SimpleList_pop_front(SimpleList_t list);
65 |
66 | /**
67 | * Insert data to the list before the given position
68 | * @param list list to insert
69 | * @param pos position to insert
70 | * @param data data to insert
71 | */
72 | void SimpleList_insertBefore(SimpleList_t list, SimpleListNode_t pos, void* data);
73 |
74 | /**
75 | * Insert data to the list after the given position
76 | * @param list list to insert
77 | * @param pos position to insert
78 | * @param data data to insert
79 | */
80 | void SimpleList_insertAfter(SimpleList_t list, SimpleListNode_t pos, void* data);
81 |
82 | /**
83 | * Append list2 to list1
84 | * do not use list2 or list1 after this operation, it's not safe
85 | * only returned list is considered valid
86 | * @param list1
87 | * @param list2
88 | * @return appended list1
89 | */
90 | SimpleList_t SimpleList_append(SimpleList_t list1, SimpleList_t list2);
91 | #endif //LAB1_SIMPLELIST_H
92 |
--------------------------------------------------------------------------------
/include/Structure/SymbolTable.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/19.
3 | //
4 |
5 | /** 碎碎念:
6 | * 我是个傻逼
7 | * 符号创建流程中设计了一套从raw到baked的转换,也就是从拿到struct名称到拿到struct信息的转换
8 | * 我以为这样能方便struct变量、struct数组、嵌套struct的创建
9 | * 然而tmd到了现在我才发现,这个设计是多余的
10 | * 在创建相关符号的时候一定是先查表拿到了struct信息才能创建的
11 | * 根本不需要脱裤子放屁地先创建一个raw再bake
12 | * 就算是前置声明也肯定是先创建一个空的baked丢进符号表,这个流程里完全没有structname的事
13 | * 艹!这个b流程从设计到编写到debug花了我两天
14 | * 我是个傻逼
15 | * 现在还得回头再搭一套基于全程bakedmeta的流程
16 | * 虽说不改也不是不能用,可以直接从struct那里提一个rawmeta出来,但性能浪费我就不说了
17 | * 还是码吧,但我tm现在已经不想玩了
18 | * 艹
19 | * 我是个傻逼
20 | * Crystal 2024/3/27 11:50
21 | */
22 |
23 | /*
24 | * 为了后续翻找方便,相关弃用方法已移除。
25 | * Crystal 2024/4/6 12:00
26 | */
27 |
28 | #ifndef LAB1_SYMBOLTABLE_H
29 | #define LAB1_SYMBOLTABLE_H
30 |
31 | #include "SimpleArray.h"
32 | #include "SimpleHashTable.h"
33 |
34 | #define INVALID_VAR_ID (-1)
35 | #define INVALID_LABEL_ID (-1)
36 |
37 | ////////////////////////////////////////
38 | // Enums for SymbolRecord
39 | ////////////////////////////////////////
40 |
41 | /**
42 | * The status of the symbol.
43 | */
44 | typedef enum SymbolDefineStatus_e {
45 | SDS_Undefined = -1, // A symbol is not declared
46 | SDS_Declared = 0, // A symbol is declared but not defined
47 | SDS_ExternalDeclared = 1, // A symbol is declared and defined in other nextScopeID
48 | SDS_ExternalDefined = 2, // A symbol is defined and usable in current nextScopeID
49 | SDS_Defined = 3, // A symbol is declared in other nextScopeID
50 | } SymbolDefineStatus;
51 |
52 | /**
53 | * The type of the symbol.
54 | */
55 | typedef enum SymbolType_e {
56 | ST_Variable = 0b00,
57 | ST_Function = 0b01,
58 | ST_Struct = 0b10,
59 | } SymbolType;
60 |
61 | ////////////////////////////////////////
62 | // Types for Symbol's value
63 | ////////////////////////////////////////
64 |
65 | /**
66 | * The type of the symbol value.
67 | */
68 | typedef enum Symbol_Value_Type_e {
69 | SVT_Int = 0b00,
70 | SVT_Float = 0b01,
71 | SVT_Struct = 0b10,
72 | SVT_Array = 0b11,
73 | SVT_Void = 0b100,
74 | } Symbol_Value_Type;
75 |
76 | /**
77 | * The size of the symbol value.
78 | */
79 | int SymbolValue_getSize(Symbol_Value_Type type, void *meta);
80 |
81 | ////////////////////////////////////////
82 | ///SymbolRecord
83 | ////////////////////////////////////////
84 |
85 | typedef void* SymbolInfo_t;
86 |
87 | typedef struct {
88 | SymbolType type;
89 | SymbolInfo_t info;
90 | } SymbolRecord;
91 | typedef SymbolRecord* SymbolRecord_t;
92 |
93 | void SymbolRecord_destroy(void* record);
94 | void SymbolRecord_printDebug(SymbolRecord_t record, char* buffer, int bufferSize);
95 |
96 | ////////////////////////////////////////
97 | /// SymbolTable
98 | ////////////////////////////////////////
99 |
100 | #define INVALID_SCOPE (-1)
101 |
102 | typedef struct SymbolTable_s {
103 | SimpleHashTable_t table; // hash table for symbol records, key is full name of symbol, records stored as flat struct SymbolRecord
104 | int nextScopeID; // next scope ID that will be used
105 | SimpleArray_t scopeStack; // stack of scope IDs
106 | int currentScope; // current scopeID that is being used
107 | int nextVarID; // next variable ID that will be used
108 | int nextLabelID; // next label ID that will be used
109 | } SymbolTable;
110 | typedef SymbolTable* SymbolTable_t;
111 |
112 | /**
113 | * Create a symbol table.
114 | * @return The symbol table.
115 | */
116 | SymbolTable_t SymbolTable_create();
117 |
118 | /**
119 | * Destroy a symbol table.
120 | * @param table The symbol table.
121 | */
122 | void SymbolTable_destroy(void* table);
123 |
124 | /**
125 | * Enter a new scope, will get a new scope ID and update prefix.
126 | * prefix is always same as the top of the scope stack.
127 | * @param table The symbol table.
128 | */
129 | void SymbolTable_enterScope(SymbolTable_t table);
130 |
131 | /**
132 | * Leave current scope, will pop an ID from ID stack and update prefix.
133 | * prefix is always same as the top of the scope stack.
134 | * @param table The symbol table.
135 | */
136 | void SymbolTable_leaveScope(SymbolTable_t table);
137 |
138 | /**
139 | * Get the current scope.
140 | * @param table The symbol table.
141 | * @return The current scope.
142 | */
143 | int SymbolTable_getScope(SymbolTable_t table);
144 |
145 | /**
146 | * Generate a new name with the current nextScopeID prefix in input buffer.
147 | * @param table The symbol table.
148 | * @param name The name.
149 | * @return The name without the nextScopeID prefix(a pointer to the middle of buffer).
150 | */
151 | void SymbolTable_generateName(SymbolTable_t table, char* name, char* buffer, int bufferSize);
152 |
153 | /**
154 | * Lookup a symbol in the symbol table.
155 | * @param table The symbol table.
156 | * @param name The name of the symbol.
157 | * @param outRecord The output record.
158 | * @return The status of the symbol.
159 | */
160 | SymbolDefineStatus SymbolTable_lookupRecord(SymbolTable_t table, char* name, SymbolRecord_t* outRecord);
161 |
162 | /**
163 | * Lookup a symbol in the symbol table.
164 | * @param table The symbol table.
165 | * @param name The name of the symbol.
166 | * @param outRecord The output record.
167 | * @return index of the nextScopeID where the symbol is found, -1 if not found.
168 | */
169 | int SymbolTable_internalLookupRecord(SymbolTable_t table, char* name, SymbolRecord_t* outRecord);
170 |
171 | /**
172 | * Lookup a symbol in the symbol table in the specific scope.
173 | * @param table The symbol table.
174 | * @param name The name of the symbol.
175 | * @param scope The scope to search.
176 | * @param outRecord The output record.
177 | * @return The status of the symbol.
178 | */
179 | SymbolDefineStatus SymbolTable_lookupRecordInScope(SymbolTable_t table, char* name, int scope, SymbolRecord_t* outRecord);
180 |
181 | /**
182 | * Insert a symbol into the symbol table, content will be copied.
183 | * @param table The symbol table.
184 | * @param name The name of the symbol, will be duplicated.
185 | * @param record The record.
186 | * @return 0 if success, -1 if failed.
187 | */
188 | int SymbolTable_insertRecord(SymbolTable_t table, char* name, SymbolRecord_t record);
189 |
190 | /**
191 | * Creates a blank variable record with valid function info, the meta need to be well-baked.
192 | * will also allocate a new variable ID for the variable.
193 | * ID can be accessed by SymbolRecord->info->varID
194 | * @param table The symbol table
195 | * @param outRecord The output record, should be a pointer to valid memory of SymbolRecord
196 | * @param info The meta data of the variable
197 | * @return SE_Success if success, failed otherwise
198 | */
199 | void SymbolTable_createVariableByInfo(SymbolTable_t table, SymbolRecord *outRecord, SymbolInfo_t info);
200 |
201 | /**
202 | * Creates a blank function record with valid function info, the meta need to be well-baked.
203 | * @param table The symbol table
204 | * @param outRecord The output record, should be a pointer to valid memory of SymbolRecord
205 | * @param info The meta data of the function
206 | * @return SE_Success if success, failed otherwise
207 | */
208 | void SymbolTable_createFunctionByInfo(SymbolTable_t table, SymbolRecord *outRecord, SymbolInfo_t info);
209 |
210 | /**
211 | * Creates a blank struct record with valid struct info, the meta need to be well-baked.
212 | * @param table The symbol table
213 | * @param outRecord The output record, should be a pointer to valid memory of SymbolRecord
214 | * @param info The meta data of the struct
215 | * @return SE_Success if success, failed otherwise
216 | */
217 | void SymbolTable_createStructByInfo(SymbolTable_t table, SymbolRecord *outRecord, SymbolInfo_t info);
218 |
219 | /**
220 | * Generate a new variable ID.
221 | * @param table The symbol table.
222 | * @return The new variable ID.
223 | */
224 | int SymbolTable_getNextVarID(SymbolTable_t table);
225 |
226 | /**
227 | * Generate a new label name [ label$[ID]] ]
228 | * @param table The symbol table.
229 | * @param buffer The buffer to store the label name.
230 | * @param bufferSize The size of the buffer.
231 | */
232 | void SymbolTable_generateNextLabelName(SymbolTable_t table, char* buffer, int bufferSize);
233 |
234 | /**
235 | * Generate a new label name with suffix [ label$[ID][suffix] ]
236 | * @param table The symbol table.
237 | * @param buffer The buffer to store the label name.
238 | * @param bufferSize The size of the buffer.
239 | * @param suffix The suffix to append to the label name.
240 | */
241 | void SymbolTable_generateNextLabelNameWithSuffix(SymbolTable_t table, char* buffer, int bufferSize, char* suffix);
242 |
243 | ////////////////////////////////////////
244 | /// SymbolInfo
245 | ////////////////////////////////////////
246 |
247 | typedef struct {
248 | Symbol_Value_Type type;
249 | SymbolInfo_t meta;
250 | int varID;
251 | } SymbolInfo_Variable;
252 | typedef SymbolInfo_Variable* SymbolInfo_Variable_t;
253 | typedef SymbolInfo_Variable* SymbolInfo_Variable_Raw;
254 |
255 | /**
256 | * Create a new baked SymbolInfo_Variable with baked meta info.
257 | * @param type The type of the variable.
258 | * @param meta The baked meta data of the variable.
259 | * @return The baked SymbolInfo_Variable.
260 | */
261 | SymbolInfo_Variable_t SymbolInfo_Variable_createBaked(Symbol_Value_Type type, SymbolInfo_t meta);
262 |
263 | /**
264 | * Destroy the baked SymbolInfo_Variable.
265 | * @param info The baked SymbolInfo_Variable.
266 | */
267 | void SymbolInfo_Variable_destroy(SymbolInfo_Variable_t info);
268 |
269 | typedef struct {
270 | Symbol_Value_Type elementType;
271 | SymbolInfo_t elementMeta;
272 | int dimensionCount;
273 | int dimension;
274 | } SymbolInfo_Array;
275 | typedef SymbolInfo_Array* SymbolInfo_Array_t;
276 | typedef SymbolInfo_Array* SymbolInfo_Array_Raw;
277 |
278 | /**
279 | * Create a new baked SymbolInfo_Array with baked element struct info.
280 | * @param elementType The type of the elements in the array.
281 | * @param elementStructInfo The struct info of the elements in the array.
282 | * @param dimensions The dimensions and its length of the array, -1 if it is not fixed.
283 | * @param dimensionCount The count of the dimensions.
284 | * @return The raw SymbolInfo_Array.
285 | */
286 | SymbolInfo_Array_t SymbolInfo_Array_createBaked(Symbol_Value_Type elementType, SymbolInfo_t elementStructInfo, int dimensions[], int dimensionCount);
287 |
288 | /**
289 | * Destroy the baked SymbolInfo_Array.
290 | * @param info The baked SymbolInfo_Array.
291 | */
292 | void SymbolInfo_Array_destroy(SymbolInfo_Array_t info);
293 |
294 | typedef struct {
295 | Symbol_Value_Type returnType;
296 | SymbolInfo_t returnTypeMeta;
297 | char* functionName;
298 | int parameterCount;
299 | SymbolInfo_t* parameters;
300 | int isDefined;
301 | int firstDeclaredLine;
302 | } SymbolInfo_Function;
303 | typedef SymbolInfo_Function* SymbolInfo_Function_t;
304 | typedef SymbolInfo_Function* SymbolInfo_Function_Raw;
305 |
306 | /**
307 | * Create a new baked SymbolInfo_Function with baked meta info.
308 | * @param returnType The return type of the function, SVT_Void for void.
309 | * @param returnTypeMeta The baked meta data of the return type.
310 | * @param parameterTypes An array of parameter types, length must match the parameterCount.
311 | * @param parameterNames An array of parameter names, length must match the parameterCount, all content will be duplicated.
312 | * @param parametersMeta An array of baked parameter metadata, length must match the parameterCount.
313 | * NULL
if the parameter is not a struct or an array.
314 | * baked SymbolInfo_Struct_t if the parameter is a struct.
315 | * baked SymbolInfo_Array_t if the parameter is an array.
316 | * @param parameterCount
317 | * @return
318 | */
319 | SymbolInfo_Function_t
320 | SymbolInfo_Function_createBaked(Symbol_Value_Type returnType, SymbolInfo_t returnTypeMeta, Symbol_Value_Type parameterTypes[],
321 | char *parameterNames[], void *parametersMeta[], int parameterCount);
322 |
323 | /**
324 | * Destroy the baked SymbolInfo_Function.
325 | * @param info The baked SymbolInfo_Function.
326 | */
327 | void SymbolInfo_Function_destroy(SymbolInfo_Function_t info);
328 |
329 | int SymbolInfo_Function_hasParameterName(SymbolInfo_Function_t functionInfo, char* parameterName);
330 |
331 | void SymbolInfo_Function_addParameter(SymbolInfo_Function_t functionInfo, SymbolInfo_t parameter);
332 | /**
333 | * Get the name of the function.
334 | * @param info The baked SymbolInfo_Function.
335 | * @return The name of the function.
336 | */
337 | char* SymbolInfo_Function_getName(SymbolInfo_Function_t info);
338 |
339 | /**
340 | * Set the name of the function.
341 | * @param info The baked SymbolInfo_Function.
342 | * @param name The name of the function, will be duplicated.
343 | */
344 | void SymbolInfo_Function_setName(SymbolInfo_Function_t info, char* name);
345 |
346 | typedef struct {
347 | Symbol_Value_Type parameterType;
348 | char* parameterName;
349 | SymbolInfo_t parameterMeta;
350 | } SymbolInfo_Parameter;
351 | typedef SymbolInfo_Parameter* SymbolInfo_Parameter_t;
352 | typedef SymbolInfo_Parameter* SymbolInfo_Parameter_Raw;
353 |
354 | /**
355 | * Create a new baked SymbolInfo_Parameter with baked meta info.
356 | * @param type The type of the parameter.
357 | * @param parameterName The name of the parameter, will be duplicated if not NULL.
358 | * @param meta The baked meta data of the parameter.
359 | * NULL
if the parameter is not a struct or an array.
360 | * baked SymbolInfo_Struct_t if the parameter is a struct.
361 | * baked SymbolInfo_Array_t if the parameter is an array.
362 | * @return The baked SymbolInfo_Parameter.
363 | */
364 | SymbolInfo_Parameter_t SymbolInfo_Parameter_createBaked(Symbol_Value_Type type, char* parameterName, SymbolInfo_t meta);
365 |
366 | typedef struct {
367 | #ifdef SYMBOL_TABLE_STRUCT_NAME
368 | char* structName;
369 | #endif
370 | int memberCount;
371 | SymbolInfo_t* members;
372 | int size;
373 | } SymbolInfo_Struct;
374 | typedef SymbolInfo_Struct* SymbolInfo_Struct_t;
375 | typedef SymbolInfo_Struct* SymbolInfo_Struct_Raw;
376 |
377 | /**
378 | * Create a new baked SymbolInfo_Struct with baked meta info.
379 | * @param memberTypes An array of member types, length must match the memberCount.
380 | * @param memberNames An array of member names, length must match the memberCount, all content will be duplicated, memberName cannot be NULL.
381 | * @param memberMeta An array of member metadata.
382 | * NULL
if the member is not a struct or an array.
383 | * baked SymbolInfo_Struct_t if the member is a struct.
384 | * baked SymbolInfo_Array_t if the member is an array.
385 | * @param memberCount The count of the members.
386 | * @return baked SymbolInfo_Struct_t if success, NULL if failed.
387 | */
388 | SymbolInfo_Struct_t
389 | SymbolInfo_Struct_createBaked(Symbol_Value_Type *memberTypes, char **memberNames, void **memberMeta, int memberCount);
390 |
391 | /** Destroy the baked SymbolInfo_Struct.
392 | * @param info The baked SymbolInfo_Struct.
393 | */
394 | void SymbolInfo_Struct_destroy(SymbolInfo_Struct_t info);
395 |
396 | int SymbolInfo_Struct_checkMemberName(SymbolInfo_Struct_t info, char* memberName);
397 |
398 | /**
399 | * Insert a member into the struct.
400 | * @param info The baked SymbolInfo_Struct.
401 | * @param memberInfo The member info.
402 | */
403 | void SymbolInfo_Struct_insertMember(SymbolInfo_Struct_t info, SymbolInfo_t memberInfo);
404 |
405 | #ifdef SYMBOL_TABLE_STRUCT_NAME
406 | /**
407 | * Get the name of the struct.
408 | * @param info The baked SymbolInfo_Struct.
409 | * @return The name of the struct.
410 | */
411 | char* SymbolInfo_Struct_getName(SymbolInfo_Struct_t info);
412 | /**
413 | * Set the name of the struct.
414 | * @param info The baked SymbolInfo_Struct.
415 | * @param name The name of the struct, will be duplicated.
416 | */
417 | void SymbolInfo_Struct_setName(SymbolInfo_Struct_t info, char* name);
418 | #endif
419 |
420 | typedef struct {
421 | Symbol_Value_Type memberType;
422 | SymbolInfo_t memberMeta;
423 | char* memberName;
424 | int offset;
425 | } SymbolInfo_Member;
426 | typedef SymbolInfo_Member* SymbolInfo_Member_t;
427 | typedef SymbolInfo_Member* SymbolInfo_Member_Raw;
428 | /**
429 | * Create a new SymbolInfo_Member.
430 | * @param memberType The type of the member.
431 | * @param memberName The name of the member, will be duplicated.
432 | * @param memberMeta The meta data of the member.
433 | * NULL
if the member is not a struct or an array.
434 | * char[]
if the member is a struct, represent the name of the struct without the nextScopeID prefix.
435 | * SymbolInfo_Array_t
(create by SymbolInfo_Array_create
, **need to be raw**) if the member is an array.
436 | * @return The raw SymbolInfo_Member.
437 | * @see SymbolInfo_Array_create
438 | */
439 | SymbolInfo_Member_Raw SymbolInfo_Member_create(Symbol_Value_Type memberType, char* memberName, void* memberMeta);
440 |
441 | /**
442 | * Create a new baked SymbolInfo_Member with baked meta info.
443 | * @param memberType The type of the member.
444 | * @param memberName The name of the member, will be duplicated.
445 | * @param memberMeta The baked meta data of the member.
446 | * NULL
if the member is not a struct or an array.
447 | * baked SymbolInfo_Struct_t if the member is a struct.
448 | * baked SymbolInfo_Array_t if the member is an array.
449 | * @return
450 | */
451 | SymbolInfo_Member_t SymbolInfo_Member_createBaked(Symbol_Value_Type memberType, char* memberName, SymbolInfo_t memberMeta);
452 |
453 | /**
454 | * Destroy the baked SymbolInfo_Member.
455 | * @param info The baked SymbolInfo_Member.
456 | */
457 | void SymbolInfo_Member_destroy(SymbolInfo_Member_t info);
458 |
459 | /**
460 | * Check if the symbol is defined.
461 | * @param info The symbol info.
462 | * @return 1 if defined, 0 if not defined.
463 | */
464 | int SymbolRecord_isSymbolDefined(SymbolRecord_t record);
465 |
466 |
467 |
468 |
469 | #endif //LAB1_SYMBOLTABLE_H
470 |
--------------------------------------------------------------------------------
/include/Structure/TokenName.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by m1504 on 2024/3/18.
3 | //
4 |
5 | #ifndef LAB1_TOKENNAME_H
6 | #define LAB1_TOKENNAME_H
7 |
8 | const char* getGrammarSymbolName(int grammarSymbol);
9 | const char* getTokenName(int token);
10 |
11 | #endif //LAB1_TOKENNAME_H
12 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # 哈尔滨工业大学-编译原理2024-实验
2 |
3 | ## 版权声明
4 |
5 | 本实验代码由哈尔滨工业大学(本部)相关专业学生编写,仅用于学习交流,未经允许不得用于商业用途。
6 | **由不当使用此项目造成的课业危险由使用者自行承担!!编写者不负任何责任!!**
7 |
8 | ## 模块
9 |
10 | - `src/CmmLexer.l` 词法分析器
11 | - `src/CmmParser.y` 语法分析器
12 | - `src/ErrorReporter.c` 错误报告器,使用散列表实现
13 | - `src/SemanticAnalyzer.c` 语义分析器,在遍历语法树的基础上进行语义检查
14 | - `src/InterCodeGenerator.c` 中间代码生成器,生成三地址码,手动实现了虚表和多态(只是为了好玩)
15 | - `src/Structure/SimpleArray.c` 用于管理树节点,以及为高级数据结构提供基础的的简易动态数组
16 | - `src/Structure/SimpleHashTable.c` 用于管理符号表和错误报告的简易哈希表
17 | - `src/Structure/TokenName.c` 用于从符号枚举值获取符号名
18 | - `src/Structure/SymbolTable.c` 符号表相关实现,支持了一套动态内存管理的符号表
19 | - `src/Structure/ParserNodes.c` 语法树节点,使用动态数组实现
20 | - `src/Structure/SemanticInfo.c` 语义信息,用于在语义节点中提供综合属性
21 | - `Lab1.c` 实验一主程序,包含了词法分析器和语法分析器的调用
22 | - `Lab2.c` 实验二主程序,包含了语义分析器的调用
23 | - `Lab3.c` 实验三主程序,包含了中间代码生成器的调用
24 |
25 | 2024.4.8:项目全部模块编写完成,编写者不再主动更新,如发现问题请及时发issue反馈编写者以修正
26 | *同样也欢迎发issue或邮件探讨项目的设计*
27 |
28 | ## 项目编译
29 |
30 | 首先切换到项目主目录(即CMakeLists.txt所在目录)
31 | 选定一个你喜欢的cmake构建目录名,此处以Cmake为例
32 |
33 | ```bash
34 | mkdir Cmake
35 | cd Cmake
36 | cmake ..
37 | ```
38 |
39 | cmake将创建所有所需make文件,如果你需要对项目进行debug,在cmake生成make文件时需要指定debug参数:
40 |
41 | ```bash
42 | cmake -DCMAKE_BUILD_TYPE=Debug ..
43 | ```
44 |
45 | 在执行cmake指令后,你就可以在Cmake文件夹下使用make指令构建项目目标,使用指令
46 |
47 | ```bash
48 | make all
49 | ```
50 |
51 | 以一次性构建Lab1-3的文件
52 | 你也可以指定性的构建Lab1-3中的任意一个,只需要将`all`替换成`Lab1`, `Lab2`, `Lab3`中的任意一个即可
53 |
54 | 项目的执行文件将生成在 `./crystal` 目录下。
55 |
56 | ## 项目测试
57 |
58 | 项目已在`./crystal`目录下提供测试脚本,可执行`LabXBatchTest.sh`测试实验X,相关样例在`testLabX`目录下
59 |
60 | 当执行脚本时:
61 |
62 | 实验一的树节点输出会被重定向到`testLab1/output/[caseName].pst`
63 | 报错信息将打印到屏幕中。
64 |
65 | 实验三的中间代码生成输出会被重定向到`testLab3/output/[caseName].ir`
66 |
67 | 也可以单独执行`./LabX [filename]`进行测试
68 |
69 | ## 项目测试环境
70 |
71 | IDE: CLion 2023.3.4
72 |
73 | *Thanks to JetBrains for providing the Education License!*
74 |
75 | AI Assistant: GitHub Copilot
76 |
77 | *Thanks to GitHub for providing the Education License!*
78 |
79 | - Ubuntu 22.04.2 LTS
80 | - gcc 11.4.0
81 | - flex 2.6.4
82 | - bison 3.8.2
83 | - cmake 3.26.4
84 | - make 4.3
85 |
86 | *Required_min_version:*
87 |
88 | - cmake 3.22
89 | - flex 2.5.35
90 | - bison 2.5.0
91 |
--------------------------------------------------------------------------------
/src/CmmLexer.l:
--------------------------------------------------------------------------------
1 | %{
2 | #define NOINCLUDE_CMM_SCANNER_TAB_H
3 | #include "CmmParserTypes.h"
4 | #include "Structure/ParserNodes.h"
5 | #include "ErrorReporter.h"
6 | #undef NOINCLUDE_CMM_SCANNER_TAB_H
7 |
8 | %}
9 |
10 | %option yylineno
11 |
12 | COMMENTSINGLE "//"
13 | COMMENTMULTI "/*"
14 |
15 | SEMI ;
16 | COMMA ,
17 | ASSIGNOP =
18 | PLUS \+
19 | MINUS \-
20 | STAR \*
21 | DIV \/
22 | AND &&
23 | OR \|\|
24 | DOT \.
25 | NOT !
26 |
27 | EQ ==
28 | NEQ !=
29 | LE <=
30 | LT <
31 | GE >=
32 | GT >
33 |
34 | LP \(
35 | RP \)
36 | LB \[
37 | RB \]
38 | LC \{
39 | RC \}
40 |
41 | TYPE int|float
42 | STRUCT struct
43 | RETURN return
44 | IF if
45 | ELSE else
46 | WHILE while
47 |
48 | INTOCT 0[1-7][0-7]*
49 | INTHEX 0[xX][0-9a-fA-F]+
50 | INTDEC (0|[1-9][0-9]*)
51 | INT {INTDEC}|{INTOCT}|{INTHEX}
52 | FLOAT ({INTDEC}\.[0-9]+)|(([0-9]+\.[0-9]*|[0-9]*\.[0-9]*)[Ee][+-]?[0-9]+)
53 | ID [a-zA-Z_][a-zA-Z0-9_]*
54 |
55 | SPACE [ \t\n\r]+
56 |
57 | ID_ERROR [0-9][a-zA-Z0-9_]*
58 | INTOCT_ERROR 0[0-7]*[89][0-9]*
59 | INTHEX_ERROR 0[xX][0-9a-fA-F]*[g-zG-Z]*[0-9a-zA-Z]*
60 | INTDEC_ERROR [1-9][0-9]*[a-zA-Z]*
61 | FLOAT_ERROR ({INTDEC}\.[0-9]*[a-zA-Z]+)|(([0-9]*\.[0-9]*|[0-9]*\.[0-9]*)[Ee][+-]?[0-9]*[a-zA-Z]+)
62 | INT_ERROR {INTDEC_ERROR}|{INTOCT_ERROR}|{INTHEX_ERROR}
63 |
64 | ERROR .
65 |
66 | %%
67 | {COMMENTSINGLE} { while (input() != '\n'); }
68 | {COMMENTMULTI} {
69 | int c;
70 | // note that when input meets EOF, it will return 0, not EOF.(issue #2, CmmScanner.c, line 1751)
71 | const int lexerEOF = 0;
72 | int startLine = yylineno;
73 | while ((c = input()) != lexerEOF) {
74 | if (c == '*') {
75 | if ((c = input()) == '/') {
76 | break;
77 | }
78 | else if(c == lexerEOF)
79 | {
80 | goto error_UC;
81 | }
82 | else {
83 | unput(c);
84 | }
85 | }
86 | }
87 | error_UC:
88 | if (c == lexerEOF) {
89 | reportError(startLine, UnterminatedComment, "unterminated comment detected.");
90 | break;
91 | }
92 | }
93 |
94 | {INT} { yylval.nodeIndex = newParserNode(INT, yylineno, 0, NULL, INVALID_NODE_INDEX); return INT; }
95 | {FLOAT} { yylval.nodeIndex = newParserNode(FLOAT, yylineno, 0, NULL, INVALID_NODE_INDEX); return FLOAT; }
96 |
97 | {SEMI} { yylval.nodeIndex = newParserNode(SEMI, yylineno, 0, NULL, INVALID_NODE_INDEX); return SEMI; }
98 | {COMMA} { yylval.nodeIndex = newParserNode(COMMA, yylineno, 0, NULL, INVALID_NODE_INDEX); return COMMA; }
99 | {ASSIGNOP} { yylval.nodeIndex = newParserNode(ASSIGNOP, yylineno, 0, NULL, INVALID_NODE_INDEX); return ASSIGNOP; }
100 | {PLUS} { yylval.nodeIndex = newParserNode(PLUS, yylineno, 0, NULL, INVALID_NODE_INDEX); return PLUS; }
101 | {MINUS} { yylval.nodeIndex = newParserNode(MINUS, yylineno, 0, NULL, INVALID_NODE_INDEX); return MINUS; }
102 | {STAR} { yylval.nodeIndex = newParserNode(STAR, yylineno, 0, NULL, INVALID_NODE_INDEX); return STAR; }
103 | {DIV} { yylval.nodeIndex = newParserNode(DIV, yylineno, 0, NULL, INVALID_NODE_INDEX); return DIV; }
104 | {AND} { yylval.nodeIndex = newParserNode(AND, yylineno, 0, NULL, INVALID_NODE_INDEX); return AND; }
105 | {OR} { yylval.nodeIndex = newParserNode(OR, yylineno, 0, NULL, INVALID_NODE_INDEX); return OR; }
106 | {DOT} { yylval.nodeIndex = newParserNode(DOT, yylineno, 0, NULL, INVALID_NODE_INDEX); return DOT; }
107 | {NOT} { yylval.nodeIndex = newParserNode(NOT, yylineno, 0, NULL, INVALID_NODE_INDEX); return NOT; }
108 | {TYPE} { yylval.nodeIndex = newParserNode(TYPE, yylineno, 0, NULL, INVALID_NODE_INDEX); return TYPE; }
109 |
110 | {EQ} { yylval.nodeIndex = newParserNode(EQ, yylineno, 0, NULL, INVALID_NODE_INDEX); return EQ; }
111 | {NEQ} { yylval.nodeIndex = newParserNode(NEQ, yylineno, 0, NULL, INVALID_NODE_INDEX); return NEQ; }
112 | {LE} { yylval.nodeIndex = newParserNode(LE, yylineno, 0, NULL, INVALID_NODE_INDEX); return LE; }
113 | {LT} { yylval.nodeIndex = newParserNode(LT, yylineno, 0, NULL, INVALID_NODE_INDEX); return LT; }
114 | {GE} { yylval.nodeIndex = newParserNode(GE, yylineno, 0, NULL, INVALID_NODE_INDEX); return GE; }
115 | {GT} { yylval.nodeIndex = newParserNode(GT, yylineno, 0, NULL, INVALID_NODE_INDEX); return GT; }
116 |
117 | {LP} { yylval.nodeIndex = newParserNode(LP, yylineno, 0, NULL, INVALID_NODE_INDEX); return LP; }
118 | {RP} { yylval.nodeIndex = newParserNode(RP, yylineno, 0, NULL, INVALID_NODE_INDEX); return RP; }
119 | {LB} { yylval.nodeIndex = newParserNode(LB, yylineno, 0, NULL, INVALID_NODE_INDEX); return LB; }
120 | {RB} { yylval.nodeIndex = newParserNode(RB, yylineno, 0, NULL, INVALID_NODE_INDEX); return RB; }
121 | {LC} { yylval.nodeIndex = newParserNode(LC, yylineno, 0, NULL, INVALID_NODE_INDEX); return LC; }
122 | {RC} { yylval.nodeIndex = newParserNode(RC, yylineno, 0, NULL, INVALID_NODE_INDEX); return RC; }
123 |
124 | {STRUCT} { yylval.nodeIndex = newParserNode(STRUCT, yylineno, 0, NULL, INVALID_NODE_INDEX); return STRUCT; }
125 | {RETURN} { yylval.nodeIndex = newParserNode(RETURN, yylineno, 0, NULL, INVALID_NODE_INDEX); return RETURN; }
126 | {IF} { yylval.nodeIndex = newParserNode(IF, yylineno, 0, NULL, INVALID_NODE_INDEX); return IF; }
127 | {ELSE} { yylval.nodeIndex = newParserNode(ELSE, yylineno, 0, NULL, INVALID_NODE_INDEX); return ELSE; }
128 | {WHILE} { yylval.nodeIndex = newParserNode(WHILE, yylineno, 0, NULL, INVALID_NODE_INDEX); return WHILE; }
129 |
130 | {ID} { yylval.nodeIndex = newParserNode(ID, yylineno, 0, NULL, INVALID_NODE_INDEX); return ID; }
131 |
132 | {SPACE} ;
133 |
134 | {INT_ERROR} { reportErrorFormat(yylineno, InvalidNumber,"Invalid number \"%s\" ", yytext); return YYerror;}
135 | {FLOAT_ERROR} { reportErrorFormat(yylineno, InvalidFloat, "Invalid float \"%s\" ", yytext); return YYerror;}
136 | {ID_ERROR} { reportErrorFormat(yylineno, InvalidIdentifier, "Invalid identifier \"%s\" ", yytext); return YYerror;}
137 |
138 |
139 | {ERROR} { reportErrorFormat(yylineno, UnrecognizedCharacter, "Unrecognized character \"%s\" ", yytext); return YYerror;}
140 | %%
141 |
--------------------------------------------------------------------------------
/src/CmmParser.y:
--------------------------------------------------------------------------------
1 | %{
2 | #define NOINCLUDE_CMM_SCANNER_TAB_H
3 | #include
4 | #include "CmmParserTypes.h"
5 | #include "Structure/ParserNodes.h"
6 | #include "ErrorReporter.h"
7 | #undef NOINCLUDE_CMM_SCANNER_TAB_H
8 |
9 | extern int yylineno;
10 | extern int yylex();
11 | %}
12 |
13 | %union {
14 | ParserNode_I nodeIndex;
15 | }
16 |
17 |
18 | %token INT // A sequence of digits without spaces
19 | %token FLOAT // A real number consisting of digits and a decimal point, point must be surrounded by digits
20 | %token ID // A sequence of letters, digits, and underscores, starting with a letter or underscore, at most 52 characters
21 | %token SEMI // ;
22 | %token COMMA // ,
23 | %token ASSIGNOP // =
24 | %token EQ NEQ LE LT GE GT // ==, !=, <=, <, >=, >
25 | %token PLUS // +
26 | %token MINUS // -
27 | %token STAR // *
28 | %token DIV // /
29 | %token AND // &&
30 | %token OR // ||
31 | %token DOT // .
32 | %token NOT // !
33 | %token TYPE // int, float
34 | %token LP // (
35 | %token RP // )
36 | %token LB // [
37 | %token RB // ]
38 | %token LC // {
39 | %token RC // }
40 | %token STRUCT // struct
41 | %token RETURN // return
42 | %token IF // if
43 | %token ELSE // else
44 | %token WHILE // while
45 |
46 | %type Program ExtDefList ExtDef ExtDecList
47 | %type Specifier StructSpecifier OptTag Tag
48 | %type VarDec FunDec VarList ParamDec
49 | %type CompStm StmtList Stmt
50 | %type DefList Def DecList Dec
51 | %type Exp Args
52 |
53 | // Define the precedence and associativity of the operators
54 | %right ASSIGNOP
55 | %left OR
56 | %left AND
57 | %left EQ NEQ LE LT GE GT
58 | %left PLUS MINUS
59 | %left STAR DIV
60 | %right NOT
61 | %left DOT LP RP LB RB LC RC
62 |
63 | %nonassoc LELSE
64 | %nonassoc ELSE
65 |
66 | %nonassoc pri3
67 | %nonassoc pri2
68 | %nonassoc pri1
69 | %nonassoc pri0
70 |
71 | %%
72 | // HIGH LEVEL GRAMMAR
73 | Program:
74 | ExtDefList {ParserNode_I children[1] = {$1}; $$ = newParserNode(PROGRAM, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX); setParserTreeRoot($$);}
75 | ;
76 |
77 | ExtDefList:
78 | ExtDef ExtDefList {ParserNode_I children[2] = {$1, $2}; $$ = newParserNode(EXT_DEF_LIST, NO_LINE_NUMBER, 2, children, INVALID_NODE_INDEX);}
79 | | /* empty */ {$$ = newParserNode(EXT_DEF_LIST, NO_LINE_NUMBER, 0, NULL, INVALID_NODE_INDEX);}
80 | ;
81 |
82 | ExtDef:
83 | Specifier ExtDecList SEMI %prec pri0 {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXT_DEF, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
84 | |Specifier SEMI %prec pri0 {ParserNode_I children[2] = {$1, $2}; $$ = newParserNode(EXT_DEF, NO_LINE_NUMBER, 2, children, INVALID_NODE_INDEX);}
85 | |Specifier FunDec CompStm {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXT_DEF, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
86 | |Specifier FunDec SEMI %prec pri0 {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXT_DEF, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
87 |
88 | |Specifier ExtDecList %prec pri1 {reportError(getParserNode($1)->lineNum, MissingSemicolon, "Missing \";\"");}
89 | |Specifier %prec pri1 {reportError(getParserNode($1)->lineNum, MissingSemicolon, "Missing \";\"");}
90 | |Specifier FunDec %prec pri1 {reportError(getParserNode($2)->lineNum, MissingSemicolon, "Missing \";\"");}
91 | |error SEMI %prec pri2 {yyerrok; reportError(yylineno, UnexpectedDeclaration, "Unexpected Declaration");}
92 | ;
93 |
94 | ExtDecList:
95 | VarDec {ParserNode_I children[1] = {$1}; $$ = newParserNode(EXT_DEC_LIST, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
96 | |VarDec COMMA ExtDecList {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXT_DEC_LIST, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
97 |
98 | |VarDec ExtDecList {reportError(getParserNode($2)->lineNum, MissingComma, "Missing \",\"");}
99 | ;
100 |
101 | //SPECIFIER
102 | Specifier:
103 | TYPE {ParserNode_I children[1] = {$1}; $$ = newParserNode(SPECIFIER, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
104 | |StructSpecifier {ParserNode_I children[1] = {$1}; $$ = newParserNode(SPECIFIER, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
105 | ;
106 |
107 | StructSpecifier:
108 | STRUCT OptTag LC DefList RC {ParserNode_I children[5] = {$1, $2, $3, $4, $5}; $$ = newParserNode(STRUCT_SPECIFIER, NO_LINE_NUMBER, 5, children, INVALID_NODE_INDEX);}
109 | |STRUCT Tag {ParserNode_I children[2] = {$1, $2}; $$ = newParserNode(STRUCT_SPECIFIER, NO_LINE_NUMBER, 2, children, INVALID_NODE_INDEX);}
110 | ;
111 |
112 | OptTag:
113 | ID {ParserNode_I children[1] = {$1}; $$ = newParserNode(OPT_TAG, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
114 | |/* empty */ {$$ = newParserNode(OPT_TAG, NO_LINE_NUMBER, 0, NULL, INVALID_NODE_INDEX);}
115 | ;
116 |
117 | Tag:
118 | ID {ParserNode_I children[1] = {$1}; $$ = newParserNode(TAG, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
119 | ;
120 |
121 | //DECLARATION
122 | VarDec:
123 | ID {ParserNode_I children[1] = {$1}; $$ = newParserNode(VAR_DEC, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
124 | |VarDec LB INT RB %prec pri0 {ParserNode_I children[4] = {$1, $2, $3, $4}; $$ = newParserNode(VAR_DEC, NO_LINE_NUMBER, 4, children, INVALID_NODE_INDEX);}
125 |
126 | |VarDec LB INT %prec pri1 {reportError(getParserNode($2)->lineNum, MissingRightBracket, "Missing \"]\"");}
127 | ;
128 |
129 | FunDec:
130 | ID LP VarList RP %prec pri0 {ParserNode_I children[4] = {$1, $2, $3, $4}; $$ = newParserNode(FUN_DEC, NO_LINE_NUMBER, 4, children, INVALID_NODE_INDEX);}
131 | |ID LP RP %prec pri0 {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(FUN_DEC, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
132 |
133 | |ID LP VarList %prec pri1 {reportError(getParserNode($2)->lineNum, MissingRightParenthesis, "Missing \")\"");}
134 | ;
135 |
136 | VarList:
137 | ParamDec COMMA VarList %prec pri0 {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(VAR_LIST, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
138 | |ParamDec {ParserNode_I children[1] = {$1}; $$ = newParserNode(VAR_LIST, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
139 | ;
140 |
141 | ParamDec:
142 | Specifier VarDec {ParserNode_I children[2] = {$1, $2}; $$ = newParserNode(PARAM_DEC, NO_LINE_NUMBER, 2, children, INVALID_NODE_INDEX);}
143 |
144 | |VarDec {reportError(getParserNode($1)->lineNum, MissingSpecifier, "Missing Specifier");}
145 | ;
146 |
147 | //STATEMENT
148 | CompStm:
149 | LC DefList StmtList RC {ParserNode_I children[4] = {$1, $2, $3, $4}; $$ = newParserNode(COMP_STM, NO_LINE_NUMBER, 4, children, INVALID_NODE_INDEX);}
150 | ;
151 |
152 | StmtList:
153 | Stmt StmtList {ParserNode_I children[2] = {$1, $2}; $$ = newParserNode(STMT_LIST, NO_LINE_NUMBER, 2, children, INVALID_NODE_INDEX);}
154 | |/* empty */ {$$ = newParserNode(STMT_LIST, NO_LINE_NUMBER, 0, NULL, INVALID_NODE_INDEX);}
155 | ;
156 |
157 | Stmt:
158 | Exp SEMI %prec pri2 {ParserNode_I children[2] = {$1, $2}; $$ = newParserNode(STMT, NO_LINE_NUMBER, 2, children, INVALID_NODE_INDEX);}
159 | |CompStm {ParserNode_I children[1] = {$1}; $$ = newParserNode(STMT, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
160 | |RETURN Exp SEMI %prec pri2 {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(STMT, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
161 | |IF LP Exp RP Stmt %prec LELSE {ParserNode_I children[5] = {$1, $2, $3, $4, $5}; $$ = newParserNode(STMT, NO_LINE_NUMBER, 5, children, INVALID_NODE_INDEX);}
162 | |IF LP Exp RP Stmt ELSE Stmt {ParserNode_I children[7] = {$1, $2, $3, $4, $5, $6, $7}; $$ = newParserNode(STMT, NO_LINE_NUMBER, 7, children, INVALID_NODE_INDEX);}
163 | |WHILE LP Exp RP Stmt {ParserNode_I children[5] = {$1, $2, $3, $4, $5}; $$ = newParserNode(STMT, NO_LINE_NUMBER, 5, children, INVALID_NODE_INDEX);}
164 |
165 | |error SEMI %prec pri3 {yyerrok; reportError(yylineno, UnexpectedStatement, "Unexpected Statement");}
166 | ;
167 |
168 |
169 | //LOCAL DEFINITION
170 | DefList:
171 | Def DefList {ParserNode_I children[2] = {$1, $2}; $$ = newParserNode(DEF_LIST, NO_LINE_NUMBER, 2, children, INVALID_NODE_INDEX);}
172 | |/* empty */ {$$ = newParserNode(DEF_LIST, NO_LINE_NUMBER, 0, NULL, INVALID_NODE_INDEX);}
173 | ;
174 |
175 | Def:
176 | Specifier DecList SEMI {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(DEF, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
177 | ;
178 |
179 | DecList:
180 | Dec {ParserNode_I children[1] = {$1}; $$ = newParserNode(DEC_LIST, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
181 | |Dec COMMA DecList {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(DEC_LIST, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
182 | ;
183 |
184 | Dec:
185 | VarDec {ParserNode_I children[1] = {$1}; $$ = newParserNode(DEC, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
186 | |VarDec ASSIGNOP Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(DEC, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
187 | ;
188 |
189 | //EXPRESSION
190 |
191 | Exp:
192 | Exp ASSIGNOP Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
193 | |Exp AND Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
194 | |Exp OR Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
195 | |Exp EQ Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
196 | |Exp NEQ Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
197 | |Exp LT Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
198 | |Exp LE Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
199 | |Exp GT Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
200 | |Exp GE Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
201 | |Exp PLUS Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
202 | |Exp MINUS Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
203 | |Exp STAR Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
204 | |Exp DIV Exp {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
205 | |LP Exp RP {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
206 | |MINUS Exp {ParserNode_I children[2] = {$1, $2}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 2, children, INVALID_NODE_INDEX);}
207 | |NOT Exp {ParserNode_I children[2] = {$1, $2}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 2, children, INVALID_NODE_INDEX);}
208 | |ID LP Args RP {ParserNode_I children[4] = {$1, $2, $3, $4}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 4, children, INVALID_NODE_INDEX);}
209 | |ID LP RP {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
210 | |Exp LB Exp RB {ParserNode_I children[4] = {$1, $2, $3, $4}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 4, children, INVALID_NODE_INDEX);}
211 | |Exp DOT ID {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
212 | |ID %prec pri0 {ParserNode_I children[1] = {$1}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
213 | |INT %prec pri0 {ParserNode_I children[1] = {$1}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
214 | |FLOAT %prec pri0 {ParserNode_I children[1] = {$1}; $$ = newParserNode(EXP, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
215 |
216 | |error Exp %prec pri1 {yyerrok; reportError(yylineno, UnexpectedExpression, "Unexpected Expression");}
217 | ;
218 |
219 | Args:
220 | Exp COMMA Args {ParserNode_I children[3] = {$1, $2, $3}; $$ = newParserNode(ARGS, NO_LINE_NUMBER, 3, children, INVALID_NODE_INDEX);}
221 | |Exp {ParserNode_I children[1] = {$1}; $$ = newParserNode(ARGS, NO_LINE_NUMBER, 1, children, INVALID_NODE_INDEX);}
222 | ;
223 |
224 | %%
--------------------------------------------------------------------------------
/src/ErrorReporter.c:
--------------------------------------------------------------------------------
1 | //
2 | // Created by m1504 on 2024/3/20.
3 | //
4 |
5 | #include "Structure/SimpleHashTable.h"
6 | #include
7 | #include
8 | #include
9 |
10 | #include "ErrorReporter.h"
11 |
12 | #define IS_LEXICAL_ERROR(errorType) (errorType >= LEXICAL_ERROR_BASE && errorType <= UNDEF_LEXICAL_ERROR)
13 | #define IS_SYNTAX_ERROR(errorType) (errorType >= SYNTAX_ERROR_BASE && errorType <= UNDEF_SYNTAX_ERROR)
14 | #define IS_SEMANTIC_ERROR(errorType) (errorType >= SEMANTIC_ERROR_BASE && errorType <= UNDEF_SEMANTIC_ERROR)
15 |
16 | //#define ERROR_REPORTER_DEBUG
17 |
18 | typedef struct ErrorInfo_s {
19 | int errorType;
20 | int lineNumber;
21 | char* externalMessage;
22 | } ErrorInfo;
23 | typedef ErrorInfo* ErrorInfo_t;
24 |
25 | char semanticErrorTypeNames[][10] = {
26 | "UNDEF",
27 | "1",
28 | "2",
29 | "3",
30 | "4",
31 | "5",
32 | "6",
33 | "7",
34 | "8",
35 | "9",
36 | "10",
37 | "11",
38 | "12",
39 | "13",
40 | "14",
41 | "15",
42 | "16",
43 | "17",
44 | "18",
45 | "19",
46 | "20"
47 | };
48 |
49 | SimpleHashTable_t errorTable = NULL;
50 |
51 | FILE* errorFile = NULL;
52 |
53 | int cmpErrorPriority(int errorType1, int errorType2);
54 |
55 | ErrorInfo createErrorInfo(int lineNumber, int errorType, char* externalMessage) {
56 | ErrorInfo errorInfo;
57 | errorInfo.lineNumber = lineNumber;
58 | errorInfo.errorType = errorType;
59 | errorInfo.externalMessage = strdup(externalMessage);
60 | return errorInfo;
61 | }
62 |
63 | void freeErrorInfo(void* inErrorInfo) {
64 | ErrorInfo_t errorInfo = (ErrorInfo_t)inErrorInfo;
65 | if (errorInfo->externalMessage != NULL) {
66 | free(errorInfo->externalMessage);
67 | }
68 | }
69 |
70 | const char* getErrorTypeName(int errorType){
71 | if(IS_LEXICAL_ERROR(errorType))
72 | {
73 | return "A";
74 | }
75 | else if(IS_SYNTAX_ERROR(errorType))
76 | {
77 | return "B";
78 | }
79 | else if(IS_SEMANTIC_ERROR(errorType))
80 | {
81 | if(errorType != UNDEF_SEMANTIC_ERROR) {
82 | return semanticErrorTypeNames[errorType - SEMANTIC_ERROR_BASE];
83 | }
84 | }
85 | return "UNDEF";
86 | }
87 |
88 | void printErrorInfo(const void* inErrorInfo) {
89 | fprintf(errorFile, "Error type %s at line %d: %s\n"
90 | , getErrorTypeName(((ErrorInfo_t)inErrorInfo)->errorType)
91 | , ((ErrorInfo_t)inErrorInfo)->lineNumber
92 | , ((ErrorInfo_t)inErrorInfo)->externalMessage);
93 | }
94 |
95 | void reportError(int line, int errorType, char* externalMessage) {
96 | if (errorTable == NULL) {
97 | errorTable = SimpleHashTable_createHashTable(sizeof(ErrorInfo), NULL, NULL);
98 | }
99 |
100 | #ifdef ERROR_REPORTER_DEBUG
101 | printf("DEBUG: Error type %s at line %d: %s\n\n"
102 | , getErrorTypeName(errorType)
103 | , line
104 | , externalMessage);
105 | #endif
106 |
107 | ErrorInfo_t existedErrorInfo = (ErrorInfo_t)SimpleHashTable_find(errorTable, &line, sizeof(int));
108 | if (existedErrorInfo == NULL || cmpErrorPriority(existedErrorInfo->errorType, errorType) < 0) {
109 | ErrorInfo errorInfo = createErrorInfo(line, errorType, externalMessage);
110 |
111 | #ifdef ERROR_REPORTER_DEBUG
112 | printf("DEBUG: Error type %s in *ErrorInfo* at line %d: %s\n\n"
113 | , getErrorTypeName(errorInfo.errorType)
114 | , errorInfo.lineNumber
115 | , errorInfo.externalMessage);
116 | #endif
117 |
118 | SimpleHashTable_forceInsert(errorTable, (char *) &line, sizeof(int), &errorInfo, NULL, freeErrorInfo);
119 |
120 | #ifdef ERROR_REPORTER_DEBUG
121 | printf("DEBUG: Error type %s in *ErrorTable* at line %d: %s\n\n"
122 | , getErrorTypeName(((ErrorInfo_t)SimpleHashTable_find(errorTable, &line, sizeof(int)))->errorType)
123 | , ((ErrorInfo_t)SimpleHashTable_find(errorTable, &line, sizeof(int)))->lineNumber
124 | , ((ErrorInfo_t)SimpleHashTable_find(errorTable, &line, sizeof(int)))->externalMessage);
125 | #endif
126 |
127 | }
128 | }
129 |
130 | void reportErrorFormat(int line, int errorType, const char* format, ...)
131 | {
132 | char buffer[1024];
133 | va_list args;
134 | va_start(args, format);
135 | vsprintf(buffer, format, args);
136 | va_end(args);
137 | reportError(line, errorType, buffer);
138 | }
139 |
140 | void printError(FILE *file) {
141 | if(errorTable == NULL || file == NULL)
142 | {
143 | return;
144 | }
145 | errorFile = file;
146 | SimpleHashTable_traverse(errorTable, printErrorInfo);
147 | }
148 |
149 | void resetErrorReporter() {
150 | if (errorTable != NULL) {
151 | SimpleHashTable_destroy(errorTable, NULL, freeErrorInfo);
152 | }
153 | errorTable = NULL;
154 | errorFile = NULL;
155 | }
156 |
157 | int hasError()
158 | {
159 | return errorTable == NULL ? 0 : 1;
160 | }
161 |
162 |
163 | int cmpErrorPriority(int errorType1, int errorType2) {
164 | if (errorType1 == errorType2) {
165 | return 0;
166 | }
167 | if(IS_LEXICAL_ERROR(errorType1))
168 | {
169 | if(IS_LEXICAL_ERROR(errorType2))
170 | {
171 | return errorType1 - errorType2;
172 | }
173 | }
174 | if(IS_SYNTAX_ERROR(errorType1))
175 | {
176 | if(IS_SYNTAX_ERROR(errorType2))
177 | {
178 | return errorType1 - errorType2;
179 | }
180 | else if(IS_LEXICAL_ERROR(errorType2))
181 | {
182 | return -1;
183 | }
184 | }
185 | if(IS_SEMANTIC_ERROR(errorType1))
186 | {
187 | if(IS_SEMANTIC_ERROR(errorType2))
188 | {
189 | return 0;
190 | }
191 | if(IS_LEXICAL_ERROR(errorType2))
192 | {
193 | return -1;
194 | }
195 | if(IS_SYNTAX_ERROR(errorType2))
196 | {
197 | return -1;
198 | }
199 | }
200 | return 1;
201 | }
202 |
--------------------------------------------------------------------------------
/src/Lab1.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Lab1.h"
3 | #include "CmmParserTypes.h"
4 | #include "Structure/ParserNodes.h"
5 | #include "ErrorReporter.h"
6 |
7 | //#define ALWAYS_TRY_PRINT_PARSER_TREE
8 |
9 | extern void yyrestart(FILE* input_file);
10 |
11 | int main(int argc, char** argv){
12 | if(argc<2)
13 | {
14 | fprintf(stderr, "Usage: %s \n", argv[0]);
15 | return 1;
16 | }
17 | FILE* file = fopen(argv[1], "r");
18 | if(file == NULL)
19 | {
20 | fprintf(stderr, "Error: Cannot open file %s\n", argv[1]);
21 | return 1;
22 | }
23 |
24 | yyset_debug(0);
25 | yyrestart(file);
26 | yyparse();
27 | int ret = hasError();
28 | #ifndef ALWAYS_TRY_PRINT_PARSER_TREE
29 | if(!ret)
30 | #else
31 | if(1)
32 | #endif
33 | {
34 | printParserTree_PreOrder(getParserTreeRoot(), 0);
35 | }
36 | #ifndef ALWAYS_TRY_PRINT_PARSER_TREE
37 | if(ret)
38 | #else
39 | if(1)
40 | #endif
41 | {
42 | printError(stderr);
43 | resetErrorReporter();
44 | }
45 |
46 | #ifdef DEBUG_PARSER_TREE
47 | printf("DEBUG_PARSER_NODES:\n");
48 | printAllNodes();
49 | #endif
50 |
51 | freeParserNodes();
52 | return ret;
53 | }
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/src/Lab2.c:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/19.
3 | //
4 |
5 | #include "Structure/SymbolTable.h"
6 | #include "ErrorReporter.h"
7 | #include "Structure/ParserNodes.h"
8 | #include "SemanticAnalyzer.h"
9 |
10 | #include "Lab2.h"
11 |
12 | int main(int argc, char** argv) {
13 | if(argc<2)
14 | {
15 | fprintf(stderr, "Usage: %s \n", argv[0]);
16 | return 1;
17 | }
18 | FILE* file = fopen(argv[1], "r");
19 | if(file == NULL)
20 | {
21 | fprintf(stderr, "Error: Cannot open file %s\n", argv[1]);
22 | return 1;
23 | }
24 |
25 | yyset_debug(0);
26 | yyrestart(file);
27 | yyparse();
28 | int ret = hasError();
29 |
30 | #ifdef DEBUG_PARSER_TREE
31 | printf("DEBUG_PARSER_NODES:\n");
32 | printAllNodes();
33 | #endif
34 |
35 | if(ret)
36 | {
37 | printError(stderr);
38 | fprintf(stderr, "Lexical or syntax error detected, aborted before semantic analyzing.\n");
39 | freeParserNodes();
40 | return ret;
41 | }
42 |
43 | SymbolTable_t symbolTable = SymbolTable_create();
44 |
45 | semanticAnalyze(getParserTreeRoot(), symbolTable);
46 |
47 | ret = hasError();
48 | if(ret) {
49 | printError(stderr);
50 | resetErrorReporter();
51 | }
52 |
53 | semanticAnalyze_End();
54 | SymbolTable_destroy(symbolTable);
55 | freeParserNodes();
56 |
57 | return ret;
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/src/Lab3.c:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/31.
3 | //
4 |
5 | #include "CmmParserTypes.h"
6 | #include "Structure/ParserNodes.h"
7 | #include "SemanticAnalyzer.h"
8 | #include "ErrorReporter.h"
9 | #include "InterCodeGenerator.h"
10 |
11 | #include "Lab3.h"
12 | #include "Structure/SymbolTable.h"
13 |
14 |
15 | void registerPredefinedFunctions(SymbolTable_t symbolTable);
16 |
17 | int main(int argc, char** argv){
18 | if(argc<2)
19 | {
20 | fprintf(stderr, "Usage: %s \n", argv[0]);
21 | return 1;
22 | }
23 | FILE* file = fopen(argv[1], "r");
24 | if(file == NULL)
25 | {
26 | fprintf(stderr, "Error: Cannot open file %s\n", argv[1]);
27 | return 1;
28 | }
29 |
30 | yyset_debug(0);
31 | yyrestart(file);
32 | yyparse();
33 | int ret = hasError();
34 |
35 | #ifdef DEBUG_PARSER_TREE
36 | printf("DEBUG_PARSER_NODES:\n");
37 | printAllNodes();
38 | #endif
39 |
40 | if(ret)
41 | {
42 | printError(stderr);
43 | fprintf(stderr, "Lexical or syntax error detected, aborted before semantic analyzing.\n");
44 | resetErrorReporter();
45 | freeParserNodes();
46 | return ret;
47 | }
48 |
49 | SymbolTable_t symbolTable = SymbolTable_create();
50 |
51 | registerPredefinedFunctions(symbolTable);
52 |
53 | semanticAnalyze(getParserTreeRoot(), symbolTable);
54 |
55 | ret = hasError();
56 | if(ret) {
57 | printError(stderr);
58 | fprintf(stderr, "Semantic error detected.\n");
59 | resetErrorReporter();
60 | semanticAnalyze_End();
61 | freeParserNodes();
62 | return ret;
63 | }
64 |
65 |
66 |
67 | InterCodeHandle codeHandle = generateInterCode(getParserTreeRoot(), stdout, symbolTable);
68 |
69 | generateInterCode_End();
70 |
71 |
72 | semanticAnalyze_End();
73 | SymbolTable_destroy(symbolTable);
74 | freeParserNodes();
75 |
76 | return ret;
77 | }
78 |
79 | void registerPredefinedFunctions(SymbolTable_t symbolTable) {
80 | SymbolInfo_Function_t readFunc = SymbolInfo_Function_createBaked(SVT_Int,
81 | NULL,
82 | NULL,
83 | NULL,
84 | NULL,
85 | 0);
86 | Symbol_Value_Type writeFuncParamType[1] = {SVT_Int};
87 | char* writeFuncParamName[1] = {"value"};
88 | SymbolInfo_t writeFuncParamInfo[1] = {NULL};
89 | SymbolInfo_Function_t writeFunc = SymbolInfo_Function_createBaked(SVT_Int,
90 | NULL,
91 | writeFuncParamType,
92 | writeFuncParamName,
93 | writeFuncParamInfo,
94 | 1);
95 | readFunc->isDefined = 1;
96 | writeFunc->isDefined = 1;
97 | SymbolRecord record;
98 | SymbolTable_createFunctionByInfo(symbolTable, &record, readFunc);
99 | SymbolTable_insertRecord(symbolTable, "read", &record);
100 | SymbolTable_createFunctionByInfo(symbolTable, &record, writeFunc);
101 | SymbolTable_insertRecord(symbolTable, "write", &record);
102 | }
103 |
--------------------------------------------------------------------------------
/src/Structure/ParserNodes.c:
--------------------------------------------------------------------------------
1 | //
2 | // Created by m1504 on 2024/3/19.
3 | //
4 |
5 | #include "Lab1.h"
6 | #include
7 | #include
8 | #include "stdlib.h"
9 | #include "string.h"
10 | #include "Structure/SimpleArray.h"
11 | #include "CmmParserTypes.h"
12 |
13 | #include "Structure/ParserNodes.h"
14 |
15 | SimpleArray_t parserNodes = NULL;
16 | ParserNode_I rootIndex = INVALID_NODE_INDEX;
17 | extern char* yytext;
18 |
19 | void setParserTreeRoot(ParserNode_I InRootIndex){
20 | rootIndex = InRootIndex;
21 | }
22 |
23 | ParserNode_I newParserNode(int symbol, int lineNum, int childNum, ParserNode_I *children, ParserNode_I fatherNodeIndex) {
24 | if(parserNodes == NULL)
25 | {
26 | parserNodes = SimpleArray_create(sizeof(ParserNode));
27 | }
28 | ParserNode node;
29 | node.token = symbol;
30 | node.lineNum = lineNum;
31 | node.children = NULL;
32 | node.semanticInfo = NULL;
33 | switch (symbol) {
34 | case ID:
35 | case TYPE:
36 | node.ID = strdup(yytext);
37 | break;
38 | case INT:
39 | node.intVal = stoi(yytext);
40 | break;
41 | case FLOAT:
42 | node.floatVal = strtof(yytext, NULL);
43 | break;
44 | default:
45 | break;
46 | }
47 | int nodeIndex = SimpleArray_addElement(parserNodes, &node);
48 |
49 | addChildrenToNode(nodeIndex, childNum, children);
50 | if(fatherNodeIndex != INVALID_NODE_INDEX)
51 | {
52 | addChildToNode(fatherNodeIndex, nodeIndex);
53 | }
54 |
55 | return nodeIndex;
56 | }
57 |
58 | ParserNode_t getParserNode(ParserNode_I index){
59 | return (ParserNode_t) SimpleArray_at(parserNodes, index);
60 | }
61 |
62 | void freeParserNode(void *nodeToFree) {
63 | ParserNode_t node = (ParserNode_t)nodeToFree;
64 | if(node->children != NULL)
65 | {
66 | SimpleArray_destroy(node->children, NULL);
67 | }
68 | if(node->token == ID || node->token == TYPE)
69 | {
70 | free(node->ID);
71 | }
72 | }
73 |
74 | void freeParserNodes(){
75 | SimpleArray_destroy(parserNodes, freeParserNode);
76 | }
77 |
78 | int ParserNodeIndexContainer_addNodeIndex(ParserNodeIndexContainer_t container, ParserNode_I index){
79 | return SimpleArray_addElement(container, &index);
80 | }
81 |
82 | ParserNodeIndexContainer_t ParserNodeIndexContainer_createContainer(){
83 | return SimpleArray_newArrayWithCapacity(sizeof(ParserNode_I), 10);
84 | }
85 |
86 | ParserNode_t ParserNodeIndexContainer_getNode(ParserNodeIndexContainer_t container, int index){
87 | ParserNode_I* indexPtr = (ParserNode_I*) SimpleArray_at(container, index);
88 | return getParserNode(*indexPtr);
89 | }
90 |
91 | void addChildrenToNode(ParserNode_I nodeIndex, int childNum, ParserNode_I* children) {
92 | if(childNum == 0)
93 | {
94 | return;
95 | }
96 | ParserNode_t node = getParserNode(nodeIndex);
97 | if(node->children == NULL) {
98 | node->children = ParserNodeIndexContainer_createContainer();
99 | node->lineNum = getParserNode(children[0])->lineNum;
100 | }
101 | for(int i = 0; i < childNum; i++) {
102 | ParserNodeIndexContainer_addNodeIndex(node->children, children[i]);
103 | }
104 | }
105 |
106 | void addChildToNode(ParserNode_I nodeIndex, ParserNode_I childIndex){
107 | ParserNode_t node = getParserNode(nodeIndex);
108 | if(node->children == NULL)
109 | {
110 | node->children = ParserNodeIndexContainer_createContainer();
111 | node->lineNum = getParserNode(childIndex)->lineNum;
112 | }
113 | ParserNodeIndexContainer_addNodeIndex(node->children, childIndex);
114 | }
115 |
116 | int stoi(const char* str){
117 | int base = 10;
118 | int result = 0;
119 | int sign = 1;
120 | //处理符号和基数
121 | entry:
122 | switch(str[0]) {
123 | case '-':
124 | sign = -1;
125 | ++str;
126 | goto entry;
127 | case '+':
128 | ++str;
129 | goto entry;
130 | case '0':
131 | switch (str[1]) {
132 | case 'x':
133 | case 'X':
134 | base = 16;
135 | str+=2;
136 | break;
137 | case '\0':
138 | return 0;
139 | default:
140 | base = 8;
141 | ++str;
142 | break;
143 | }
144 | default:
145 | break;
146 | }
147 | //此处已确保str指向真正的数字串
148 | //不关心无符号溢出,不可能炸,这里强转避免编译警告
149 | int len = (int)strlen(str);
150 | for(int i =0;i='0' && str[i]<='9')
154 | {
155 | digit = str[i] - '0';
156 | }
157 | else if(str[i]>='a' && str[i]<='z')
158 | {
159 | digit = str[i] - 'a' + 10;
160 | }
161 | else if(str[i]>='A' && str[i]<='Z')
162 | {
163 | digit = str[i] - 'A' + 10;
164 | }
165 | result = result * base + digit;
166 | }
167 | return result * sign;
168 | }
169 |
170 | ParserNode_I ParserNodeIndexContainer_getNodeIndex(ParserNodeIndexContainer_t container, int index) {
171 | return *((ParserNode_I *) SimpleArray_at(container, index));
172 | }
173 |
174 | ParserNode_I getParserTreeRoot() {
175 | return rootIndex;
176 | }
177 |
178 | #pragma clang diagnostic push
179 | #pragma ide diagnostic ignored "misc-no-recursion"
180 | void printParserTree_PreOrder(ParserNode_I nodeIndex, int depth) {
181 | if(nodeIndex == INVALID_NODE_INDEX)
182 | {
183 | return;
184 | }
185 | printParserNode(nodeIndex, depth);
186 | ParserNode_t node = getParserNode(nodeIndex);
187 | if(node->children == NULL)
188 | {
189 | return;
190 | }
191 | for(int i = 0; i < node->children->num; i++)
192 | {
193 | printParserTree_PreOrder(ParserNodeIndexContainer_getNodeIndex(node->children, i), depth + 1);
194 | }
195 | }
196 | #pragma clang diagnostic pop
197 |
198 | void printAllNodes() {
199 | for(int i = 0;inum;i++)
200 | {
201 | printParserNode(i, 0);
202 | }
203 | }
204 |
205 | void printParserNode(ParserNode_I nodeIndex, int depth) {
206 | if(nodeIndex == INVALID_NODE_INDEX)
207 | {
208 | return;
209 | }
210 | #ifdef DEBUG_PRINT_PARSER_NODE_INDEX
211 | printf("%d\t", nodeIndex);
212 | #endif
213 | ParserNode_t node = getParserNode(nodeIndex);
214 | if(IS_SYNTAX_TOKEN(node->token))
215 | {
216 | if(node->children!=NULL)
217 | {
218 | for(int i = 0; i < depth; i++)
219 | {
220 | printf(" ");
221 | }
222 | printf("%s (%d)\n", getGrammarSymbolName(node->token), node->lineNum);
223 | }
224 |
225 | }
226 | else if(IS_TERMINAL_TOKEN(node->token))
227 | {
228 | for(int i = 0; i < depth; i++)
229 | {
230 | printf(" ");
231 | }
232 | switch(node->token)
233 | {
234 | case ID:
235 | printf("ID: %s\n", node->ID);
236 | break;
237 | case TYPE:
238 | printf("TYPE: %s\n", node->ID);
239 | break;
240 | case INT:
241 | printf("INT: %d\n", node->intVal);
242 | break;
243 | case FLOAT:
244 | printf("FLOAT: %f\n", node->floatVal);
245 | break;
246 | case EQ:
247 | case NEQ:
248 | case LT:
249 | case GT:
250 | case LE:
251 | case GE:
252 | printf("RELOP\n" );
253 | break;
254 | default:
255 | printf("%s\n", getTokenName(node->token));
256 | break;
257 | }
258 | }
259 | }
260 |
261 | void yyerror(const char *msg) {
262 |
263 | }
264 |
265 | ParserNode_t getParserNodeChildNode(ParserNode_I index, int childIndex) {
266 | return getParserNode(getParserNodeChild(index, childIndex));
267 | }
268 |
269 | ParserNode_I getParserNodeChild(ParserNode_I index, int childIndex) {
270 | ParserNodeIndexContainer_t children = getParserNode(index)->children;
271 | return ParserNodeIndexContainer_getNodeIndex(children, childIndex);
272 | }
273 |
274 | int getParserNodeChildNum(ParserNode_I index) {
275 | ParserNodeIndexContainer_t children = getParserNode(index)->children;
276 | return children->num;
277 | }
278 |
279 | int isChildrenMatchRule(ParserNode_I nodeIndex, int ruleSize, ...) {
280 | if (GET_NODE(nodeIndex)->children == NULL)
281 | {
282 | if(ruleSize == 0)
283 | return 1;
284 | else
285 | return 0;
286 | }
287 | if (GET_CHILD_NUM(nodeIndex) != ruleSize) {
288 | return 0;
289 | }
290 | va_list params;
291 | va_start(params, ruleSize);
292 | for (int i = 0; i < ruleSize; i++) {
293 | if (GET_CHILD_NODE(nodeIndex, i)->token != va_arg(params, int)) {
294 | va_end(params);
295 | return 0;
296 | }
297 | }
298 | va_end(params);
299 | return 1;
300 | }
301 |
--------------------------------------------------------------------------------
/src/Structure/SemanticInfo.c:
--------------------------------------------------------------------------------
1 | #pragma clang diagnostic push
2 | #pragma ide diagnostic ignored "misc-no-recursion"
3 | //
4 | // Created by Crystal on 2024/3/19.
5 | //
6 |
7 | #include "Structure/SymbolTable.h"
8 |
9 | #include "Structure/SemanticInfo.h"
10 |
11 | int SymbolInfo_isStructTypeMatched(SymbolInfo_Struct_t a, SymbolInfo_Struct_t b);
12 | int SymbolInfo_isArrayTypeMatched(SymbolInfo_Array_t a, SymbolInfo_Array_t b);
13 |
14 | SemanticInfo_t
15 | SemanticInfo_createLvalue(Symbol_Value_Type valueType, SymbolInfo_t valueInfo, SimpleArray_t semanticInfoList) {
16 | SemanticInfo_t semanticInfo = (SemanticInfo_t)malloc(sizeof(SemanticInfo));
17 | semanticInfo->isLValue = 1;
18 | semanticInfo->valueType = valueType;
19 | semanticInfo->valueTypeMeta = valueInfo;
20 | SimpleArray_pushBack(semanticInfoList, &semanticInfo);
21 | return semanticInfo;
22 | }
23 |
24 | SemanticInfo_t SemanticInfo_createRvalue(Symbol_Value_Type valueType, SymbolInfo_t valueInfo, SimpleArray_t semanticInfoList) {
25 | SemanticInfo_t semanticInfo = (SemanticInfo_t)malloc(sizeof(SemanticInfo));
26 | semanticInfo->isLValue = 0;
27 | semanticInfo->valueType = valueType;
28 | semanticInfo->valueTypeMeta = valueInfo;
29 | SimpleArray_pushBack(semanticInfoList, &semanticInfo);
30 | return semanticInfo;
31 | }
32 |
33 | SemanticInfo_t SemanticInfo_makeRvalue(SemanticInfo_t semanticInfo, SimpleArray_t semanticInfoList){
34 | if(semanticInfo->isLValue)
35 | {
36 | return SemanticInfo_createRvalue(semanticInfo->valueType, semanticInfo->valueTypeMeta, semanticInfoList);
37 | }
38 | return semanticInfo;
39 | }
40 |
41 | void SemanticInfo_destroy(void *semanticInfoToDestroy) {
42 | SemanticInfo_t* semanticInfo = (SemanticInfo_t*)semanticInfoToDestroy;
43 | free(*semanticInfo);
44 | }
45 |
46 | int SemanticInfo_isTypeMatched(SemanticInfo_t a, SemanticInfo_t b) {
47 | if(a==NULL || b==NULL)
48 | {
49 | return 0;
50 | }
51 | return SymbolInfo_Helper_isTypeMatched(a->valueType, a->valueTypeMeta, b->valueType, b->valueTypeMeta);
52 | }
53 |
54 | int SymbolInfo_Function_isReturnTypeMatched(SymbolInfo_Function_t a, SymbolInfo_Function_t b){
55 | return SymbolInfo_Helper_isTypeMatched(a->returnType, a->returnTypeMeta, b->returnType, b->returnTypeMeta);
56 | }
57 |
58 | int SymbolInfo_Function_isParameterListMatched(SymbolInfo_Function_t a, SymbolInfo_Function_t b){
59 | if(a->parameterCount != b->parameterCount)
60 | {
61 | return 0;
62 | }
63 | for(int i = 0; i < a->parameterCount; i++)
64 | {
65 | SymbolInfo_Parameter_t aParameter = a->parameters[i];
66 | SymbolInfo_Parameter_t bParameter = b->parameters[i];
67 | if(!SymbolInfo_Helper_isTypeMatched(aParameter->parameterType,
68 | aParameter->parameterMeta,
69 | bParameter->parameterType,
70 | bParameter->parameterMeta))
71 | {
72 | return 0;
73 | }
74 | }
75 | return 1;
76 | }
77 |
78 |
79 | int SemanticInfo_checkValueType(SemanticInfo_t semanticInfo, Symbol_Value_Type type){
80 | return semanticInfo->valueType == type;
81 | }
82 |
83 | int SemanticInfo_checkReturnType(SymbolInfo_Function_t functionInfo, SemanticInfo_t semanticInfo){
84 | return SymbolInfo_Helper_isTypeMatched(semanticInfo->valueType, semanticInfo->valueTypeMeta,
85 | functionInfo->returnType, functionInfo->returnTypeMeta);
86 | }
87 |
88 | int SemanticInfo_checkParameterList(SymbolInfo_Function_t functionInfo, SemanticInfo_t* semanticInfos, int paramCount){
89 | if(functionInfo->parameterCount != paramCount)
90 | {
91 | return 0;
92 | }
93 | for(int i = 0; i < paramCount; i++)
94 | {
95 | SymbolInfo_Parameter_t parameter = functionInfo->parameters[i];
96 | if(!SymbolInfo_Helper_isTypeMatched(parameter->parameterType, parameter->parameterMeta,
97 | semanticInfos[i]->valueType, semanticInfos[i]->valueTypeMeta))
98 | {
99 | return 0;
100 | }
101 | }
102 | return 1;
103 | }
104 |
105 |
106 | SymbolInfo_Member_t SemanticInfo_getMemberInfo(SemanticInfo_t semanticInfo, const char *memberName) {
107 | if(!SemanticInfo_checkValueType(semanticInfo, SVT_Struct)) {
108 | return NULL;
109 | }
110 | SymbolInfo_Struct_t structInfo = (SymbolInfo_Struct_t)semanticInfo->valueTypeMeta;
111 | for(int i = 0; i < structInfo->memberCount; i++) {
112 | SymbolInfo_Member_t member = structInfo->members[i];
113 | if(strcmp(member->memberName, memberName) == 0) {
114 | return member;
115 | }
116 | }
117 | return NULL;
118 | }
119 |
120 | int SymbolInfo_isStructTypeMatched(SymbolInfo_Struct_t a, SymbolInfo_Struct_t b){
121 | if(a->memberCount == b->memberCount)
122 | {
123 | for(int i = 0; i < a->memberCount; i++)
124 | {
125 | SymbolInfo_Member_t aMember = a->members[i];
126 | SymbolInfo_Member_t bMember = b->members[i];
127 | if(!SymbolInfo_Helper_isTypeMatched(aMember->memberType,
128 | aMember->memberMeta,
129 | bMember->memberType,
130 | bMember->memberMeta))
131 | {
132 | return 0;
133 | }
134 | }
135 | return 1;
136 | }
137 | return 0;
138 | }
139 |
140 | int SymbolInfo_isArrayTypeMatched(SymbolInfo_Array_t a, SymbolInfo_Array_t b) {
141 | return a->dimensionCount == b->dimensionCount
142 | && SymbolInfo_Helper_isTypeMatched(a->elementType, a->elementMeta,
143 | b->elementType, b->elementMeta);
144 | }
145 |
146 | int SymbolInfo_Helper_isTypeMatched(Symbol_Value_Type aType, SymbolInfo_t aMeta, Symbol_Value_Type bType,
147 | SymbolInfo_t bMeta) {
148 | if(aType == bType)
149 | {
150 | switch (aType) {
151 | case SVT_Int:
152 | case SVT_Float:
153 | case SVT_Void:
154 | return 1;
155 | case SVT_Struct:
156 | return SymbolInfo_isStructTypeMatched((SymbolInfo_Struct_t)aMeta, (SymbolInfo_Struct_t)bMeta);
157 | case SVT_Array:
158 | return SymbolInfo_isArrayTypeMatched((SymbolInfo_Array_t)aMeta, (SymbolInfo_Array_t)bMeta);
159 | default:
160 | return 0;
161 | }
162 | }
163 | return 0;
164 | }
165 |
166 | #pragma clang diagnostic pop
--------------------------------------------------------------------------------
/src/Structure/SimpleArray.c:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/17.
3 | //
4 |
5 | #include
6 | #include
7 | #include "Structure/SimpleArray.h"
8 |
9 | // Free the simple array, will free the memory of the array and the elements, used private
10 | void SimpleArray_internalDestroyArray(SimpleArray_t array);
11 |
12 | // Remove the element at the index, will move the elements after the index, used private
13 | void SimpleArray_internalRemoveElement(SimpleArray_t array, int index);
14 |
15 | SimpleArray_t SimpleArray_create(int typeSize){
16 | SimpleArray_t array = (SimpleArray_t)malloc(sizeof(SimpleArray));
17 | array->data = (char*)malloc(DEFAULT_CAPACITY * typeSize);
18 | array->num = 0;
19 | array->typeSize = typeSize;
20 | array->capacity = DEFAULT_CAPACITY;
21 | return array;
22 | }
23 |
24 | int SimpleArray_addElement(SimpleArray_t array, const void* element){
25 | if(array->num >= array->capacity / 2){
26 | SimpleArray_reserve(array, array->capacity * 2);
27 | }
28 | memcpy(array->data + array->num * array->typeSize, element, array->typeSize);
29 | array->num++;
30 | return array->num - 1;
31 | }
32 |
33 | void* SimpleArray_at(SimpleArray_t array, int index){
34 | if(index < 0 || index >= array->num){
35 | return NULL;
36 | }
37 | return array->data + index * array->typeSize;
38 | }
39 |
40 | void SimpleArray_internalDestroyArray(SimpleArray_t array){
41 | free(array->data);
42 | free(array);
43 | }
44 |
45 | void SimpleArray_reserve(SimpleArray_t array, int capacity){
46 | char* newData = (char*)malloc(capacity * array->typeSize);
47 | memcpy(newData, array->data, array->num * array->typeSize);
48 | free(array->data);
49 | array->data = newData;
50 | array->capacity = capacity;
51 | }
52 |
53 | void SimpleArray_insertElement(SimpleArray_t array, int index, void *element) {
54 | if(array->num >= array->capacity / 2){
55 | SimpleArray_reserve(array, array->capacity * 2);
56 | }
57 | memmove(array->data + (index + 1) * array->typeSize, array->data + index * array->typeSize, (array->num - index) * array->typeSize);
58 | memcpy(array->data + index * array->typeSize, element, array->typeSize);
59 | array->num++;
60 | }
61 |
62 | void SimpleArray_internalRemoveElement(SimpleArray_t array, int index) {
63 | memmove(array->data + index * array->typeSize, array->data + (index + 1) * array->typeSize, (array->num - index - 1) * array->typeSize);
64 | array->num--;
65 | }
66 |
67 | void SimpleArray_clear(SimpleArray_t array) {
68 | array->num = 0;
69 | }
70 |
71 | SimpleArray_t SimpleArray_newArrayWithCapacity(int typeSize, int capacity) {
72 | SimpleArray_t array = (SimpleArray_t)malloc(sizeof(SimpleArray));
73 | array->data = (char*)malloc(capacity * typeSize);
74 | array->num = 0;
75 | array->typeSize = typeSize;
76 | array->capacity = capacity;
77 | return array;
78 | }
79 |
80 | void SimpleArray_resize(SimpleArray_t array, int newSize) {
81 | if(newSize * 2 > array->capacity) {
82 | SimpleArray_reserve(array, newSize * 2);
83 | }
84 | array->num = newSize;
85 | }
86 |
87 | void SimpleArray_zeroFilled(SimpleArray_t array) {
88 | memset(array->data, 0, array->num * array->typeSize);
89 | }
90 |
91 | void SimpleArray_popBack(SimpleArray_t array, Destructor elementDestructor) {
92 | SimpleArray_removeElement(array, array->num - 1, elementDestructor);
93 | }
94 |
95 | int SimpleArray_pushBack(SimpleArray_t array, void *element) {
96 | return SimpleArray_addElement(array, element);
97 | }
98 |
99 | void * SimpleArray_back(SimpleArray_t array) {
100 | return SimpleArray_at(array, array->num - 1);
101 | }
102 |
103 | int SimpleArray_size(SimpleArray_t array) {
104 | return array->num;
105 | }
106 |
107 | void SimpleArray_destroy(SimpleArray_t array, Destructor elementDestructor) {
108 | if(array == NULL)
109 | return;
110 | if(elementDestructor != NULL)
111 | {
112 | for (int i = 0; i < array->num; i++) {
113 | elementDestructor(array->data + i * array->typeSize);
114 | }
115 | }
116 | SimpleArray_internalDestroyArray(array);
117 | }
118 |
119 | void SimpleArray_removeElement(SimpleArray_t array, int index, Destructor elementDestructor) {
120 | if(elementDestructor != NULL)
121 | {
122 | elementDestructor(array->data + index * array->typeSize);
123 | }
124 | SimpleArray_internalRemoveElement(array, index);
125 | }
126 |
127 | void SimpleArray_setElement(SimpleArray_t array, int index, const void *element) {
128 | memcpy(array->data + index * array->typeSize, element, array->typeSize);
129 | }
130 |
--------------------------------------------------------------------------------
/src/Structure/SimpleHashTable.c:
--------------------------------------------------------------------------------
1 | //
2 | // Created by m1504 on 2024/3/20.
3 | //
4 |
5 |
6 | #include
7 | #include
8 | #include
9 | #include "Structure/SimpleHashTable.h"
10 |
11 | void SimpleHashTablePair_setPair(SimpleHashTablePair_t pair, const void* key, int keySize, const void* element, int elementSize)
12 | {
13 | pair->keySize = keySize;
14 | pair->key = malloc(keySize);
15 | pair->element = malloc(elementSize);
16 | memcpy(pair->key, key, keySize);
17 | memcpy(pair->element, element, elementSize);
18 | }
19 |
20 | void SimpleHashTablePair_destroy(SimpleHashTablePair_t pair, Destructor destructorForKey, Destructor destructorForElement)
21 | {
22 | if(destructorForKey != NULL)
23 | {
24 | destructorForKey(pair->key);
25 | }
26 | else
27 | {
28 | free(pair->key);
29 | }
30 | if(destructorForElement != NULL)
31 | {
32 | destructorForElement(pair->element);
33 | }
34 | else
35 | {
36 | free(pair->element);
37 | }
38 |
39 | }
40 |
41 | int pjwHash(const char* key, int keySize, int tableSize) {
42 | const int BitsInUnsignedInt = (int)(sizeof(int) * 8);
43 | const int ThreeQuarters = (int)((BitsInUnsignedInt * 3) / 4);
44 | const int OneEighth = (int)(BitsInUnsignedInt / 8);
45 | const int HighBits = (int)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);
46 | int hash = 0;
47 | int test = 0;
48 |
49 | for (int i = 0; i < keySize; i++) {
50 | hash = (hash << OneEighth) + key[i];
51 |
52 | if ((test = hash & HighBits) != 0) {
53 | hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits));
54 | }
55 | }
56 |
57 | return hash % tableSize;
58 | }
59 |
60 | int defaultCompare(const void* a, const void* b, int keySize) {
61 | return memcmp(a, b, keySize);
62 | }
63 |
64 | int defaultHash(const void* key, int keySize, int tableSize) {
65 | return pjwHash((const char*)key, keySize, tableSize);
66 | }
67 |
68 | SimpleHashTable_t SimpleHashTable_createHashTable(int elementSize, HashFunc hashFunc, CompareFunc compareFunc) {
69 | return SimpleHashTable_createWithSize(elementSize, hashFunc, compareFunc, THOUSAND_HASH_TABLE_SIZE);
70 | }
71 |
72 | SimpleHashTable_t SimpleHashTable_createWithSize(int elementSize, HashFunc keyHashFunc, CompareFunc keyCompareFunc, int tableSize) {
73 | SimpleHashTable_t hashTable = (SimpleHashTable_t)malloc(sizeof(SimpleHashTable));
74 | hashTable->hashFunc = keyHashFunc == NULL ? defaultHash : keyHashFunc;
75 | hashTable->compareFunc = keyCompareFunc == NULL ? defaultCompare : keyCompareFunc;
76 | hashTable->elementSize = elementSize;
77 | hashTable->data = SimpleArray_create(sizeof(SimpleArray_t));
78 | hashTable->tableSize = tableSize;
79 | SimpleArray_resize(hashTable->data, tableSize);
80 | SimpleArray_zeroFilled(hashTable->data);
81 | return hashTable;
82 | }
83 |
84 | void SimpleHashTable_destroy(SimpleHashTable_t hashTable, Destructor destructorForKey, Destructor destructorForElement){
85 | if(hashTable == NULL)
86 | return;
87 | for (int i = 0; i < THOUSAND_HASH_TABLE_SIZE; i++) {
88 | SimpleArray_t list = *((SimpleArray_t*) SimpleArray_at(hashTable->data, i));
89 | if (list != NULL) {
90 | for(int j = 0; j < list->num; j++)
91 | {
92 | SimpleHashTablePair_t pair = (SimpleHashTablePair_t) SimpleArray_at(list, j);
93 | SimpleHashTablePair_destroy(pair, destructorForKey, destructorForElement);
94 | }
95 | SimpleArray_destroy(list, NULL);
96 | }
97 | }
98 | SimpleArray_destroy(hashTable->data, NULL);
99 | free(hashTable);
100 | }
101 |
102 | int SimpleHashTable_insert(SimpleHashTable_t hashTable, const void* key, int keySize, const void* element) {
103 | int index = hashTable->hashFunc(key, keySize, hashTable->tableSize);
104 | SimpleArray_t list = *((SimpleArray_t*) SimpleArray_at(hashTable->data, index));
105 | if (list == NULL) {
106 | list = SimpleArray_newArrayWithCapacity(sizeof(SimpleHashTablePair), DEFAULT_HASH_BUCKET_SIZE);
107 | SimpleArray_setElement(hashTable->data, index, &list);
108 | }
109 | for(int i = 0; i < list->num; i++)
110 | {
111 | SimpleHashTablePair_t pair = (SimpleHashTablePair_t) SimpleArray_at(list, i);
112 | if(pair->keySize == keySize && hashTable->compareFunc(pair->key, key, keySize) == 0)
113 | {
114 | return -1;
115 | }
116 | }
117 | SimpleHashTablePair newPair;
118 | SimpleHashTablePair_setPair(&newPair, key, keySize, element, hashTable->elementSize);
119 | SimpleArray_addElement(list, &newPair);
120 | return 0;
121 | }
122 |
123 | void* SimpleHashTable_find(SimpleHashTable_t hashTable, const void* key, int keySize) {
124 | int index = hashTable->hashFunc(key, keySize, hashTable->tableSize);
125 | SimpleArray_t list = *((SimpleArray_t*) SimpleArray_at(hashTable->data, index));
126 | if (list == NULL)
127 | {
128 | return NULL;
129 | }
130 | for (int i = 0; i < list->num; i++) {
131 | SimpleHashTablePair_t pair = (SimpleHashTablePair_t) SimpleArray_at(list, i);
132 | if(pair->keySize == keySize && hashTable->compareFunc(pair->key, key, keySize) == 0)
133 | {
134 | return pair->element;
135 | }
136 | }
137 | return NULL;
138 | }
139 |
140 | void SimpleHashTable_remove(SimpleHashTable_t hashTable, const void* key, int keySize, Destructor destructorForKey, Destructor destructorForElement) {
141 | int index = hashTable->hashFunc(key, keySize, hashTable->tableSize);
142 | SimpleArray_t list = *((SimpleArray_t*) SimpleArray_at(hashTable->data, index));
143 | if (list == NULL)
144 | {
145 | return;
146 | }
147 | for (int i = 0; i < list->num; i++) {
148 | SimpleHashTablePair_t pair = (SimpleHashTablePair_t) SimpleArray_at(list, i);
149 | if(pair->keySize == keySize && hashTable->compareFunc(pair->key, key, keySize) == 0)
150 | {
151 | SimpleHashTablePair_destroy(pair, destructorForKey, destructorForElement);
152 | SimpleArray_removeElement(list, i, NULL);
153 | return;
154 | }
155 | }
156 | }
157 |
158 | void SimpleHashTable_traverse(SimpleHashTable_t hashTable, TraverseFunc traverseFunc) {
159 | if(traverseFunc == NULL)
160 | return;
161 | for (int i = 0; i < hashTable->tableSize; i++) {
162 | SimpleArray_t list = *((SimpleArray_t*) SimpleArray_at(hashTable->data, i));
163 | if (list != NULL) {
164 | for (int j = 0; j < list->num; j++) {
165 | SimpleHashTablePair_t pair = (SimpleHashTablePair_t) SimpleArray_at(list, j);
166 | traverseFunc(pair->element);
167 | }
168 | }
169 | }
170 | }
171 |
172 | void SimpleHashTable_forceInsert(SimpleHashTable_t hashTable, const void *key, int keySize, const void *element,
173 | Destructor destructorForKey, Destructor destructorForElement) {
174 | int index = hashTable->hashFunc(key, keySize, hashTable->tableSize);
175 | SimpleArray_t list = *((SimpleArray_t*) SimpleArray_at(hashTable->data, index));
176 | if (list == NULL) {
177 | list = SimpleArray_newArrayWithCapacity(sizeof(SimpleHashTablePair), DEFAULT_HASH_BUCKET_SIZE);
178 | SimpleArray_setElement(hashTable->data, index, &list);
179 | }
180 | for(int i = 0; i < list->num; i++)
181 | {
182 | SimpleHashTablePair_t pair = (SimpleHashTablePair_t) SimpleArray_at(list, i);
183 | if(pair->keySize == keySize && hashTable->compareFunc(pair->key, key, keySize) == 0)
184 | {
185 | SimpleHashTablePair_destroy(pair, destructorForKey, destructorForElement);
186 | SimpleHashTablePair_setPair(pair, key, keySize, element, hashTable->elementSize);
187 | return;
188 | }
189 | }
190 | SimpleHashTablePair newPair;
191 | SimpleHashTablePair_setPair(&newPair, key, keySize, element, hashTable->elementSize);
192 | SimpleArray_addElement(list, &newPair);
193 | }
194 |
195 | void
196 | SimpleHashTable_advancedTraverse(SimpleHashTable_t hashTable, AdvancedTraverseFunc traverseFunc, int extraParamCount,
197 | ...) {
198 | if(traverseFunc == NULL)
199 | return;
200 | va_list args;
201 | va_start(args, extraParamCount);
202 | for (int i = 0; i < hashTable->tableSize; i++) {
203 | SimpleArray_t list = *((SimpleArray_t*) SimpleArray_at(hashTable->data, i));
204 | if (list != NULL) {
205 | for (int j = 0; j < list->num; j++) {
206 | SimpleHashTablePair_t pair = (SimpleHashTablePair_t) SimpleArray_at(list, j);
207 | traverseFunc(pair->key, pair->keySize, pair->element, extraParamCount, args);
208 | }
209 | }
210 | }
211 | va_end(args);
212 | }
213 |
214 |
--------------------------------------------------------------------------------
/src/Structure/SimpleList.c:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/4/3.
3 | //
4 |
5 | #include
6 |
7 | #include "Structure/SimpleList.h"
8 |
9 | SimpleList_t SimpleList_create() {
10 | SimpleList_t newList = malloc(sizeof(SimpleList));
11 | newList->head = NULL;
12 | newList->tail = NULL;
13 | newList->size = 0;
14 | return newList;
15 | }
16 |
17 | SimpleListNode_t SimpleList_push_back(SimpleList_t list, void *data) {
18 | SimpleListNode_t newNode = malloc(sizeof(SimpleListNode));
19 | newNode->data = data;
20 | newNode->next = NULL;
21 | newNode->prev = list->tail;
22 | if (list->tail != NULL) {
23 | list->tail->next = newNode;
24 | }
25 | list->tail = newNode;
26 | if (list->head == NULL) {
27 | list->head = newNode;
28 | }
29 | list->size++;
30 | return newNode;
31 | }
32 |
33 | SimpleListNode_t SimpleList_push_front(SimpleList_t list, void *data) {
34 | SimpleListNode_t newNode = malloc(sizeof(SimpleListNode));
35 | newNode->data = data;
36 | newNode->next = list->head;
37 | newNode->prev = NULL;
38 | if (list->head != NULL) {
39 | list->head->prev = newNode;
40 | }
41 | list->head = newNode;
42 | if (list->tail == NULL) {
43 | list->tail = newNode;
44 | }
45 | list->size++;
46 | return newNode;
47 | }
48 |
49 | void *SimpleList_pop_back(SimpleList_t list) {
50 | SimpleListNode_t lastNode = list->tail;
51 | if (lastNode == NULL) {
52 | return NULL;
53 | }
54 | void *data = lastNode->data;
55 | list->tail = lastNode->prev;
56 | if (list->tail != NULL) {
57 | list->tail->next = NULL;
58 | } else {
59 | list->head = NULL;
60 | }
61 | free(lastNode);
62 | list->size--;
63 | return data;
64 | }
65 |
66 | void *SimpleList_pop_front(SimpleList_t list) {
67 | SimpleListNode_t firstNode = list->head;
68 | if (firstNode == NULL) {
69 | return NULL;
70 | }
71 | void *data = firstNode->data;
72 | list->head = firstNode->next;
73 | if (list->head != NULL) {
74 | list->head->prev = NULL;
75 | } else {
76 | list->tail = NULL;
77 | }
78 | free(firstNode);
79 | list->size--;
80 | return data;
81 | }
82 |
83 | void SimpleList_insertBefore(SimpleList_t list, SimpleListNode_t pos, void *data) {
84 | if (pos == NULL) {
85 | SimpleList_push_back(list, data);
86 | return;
87 | }
88 | SimpleListNode_t newNode = malloc(sizeof(SimpleListNode));
89 | newNode->data = data;
90 | newNode->next = pos;
91 | newNode->prev = pos->prev;
92 | if (pos->prev != NULL) {
93 | pos->prev->next = newNode;
94 | } else {
95 | list->head = newNode;
96 | }
97 | pos->prev = newNode;
98 | list->size++;
99 | }
100 |
101 | void SimpleList_insertAfter(SimpleList_t list, SimpleListNode_t pos, void *data) {
102 | if (pos == NULL) {
103 | SimpleList_push_front(list, data);
104 | return;
105 | }
106 | SimpleListNode_t newNode = malloc(sizeof(SimpleListNode));
107 | newNode->data = data;
108 | newNode->next = pos->next;
109 | newNode->prev = pos;
110 | if (pos->next != NULL) {
111 | pos->next->prev = newNode;
112 | } else {
113 | list->tail = newNode;
114 | }
115 | pos->next = newNode;
116 | list->size++;
117 | }
118 |
119 | SimpleList_t SimpleList_append(SimpleList_t list1, SimpleList_t list2) {
120 | if (list1 == NULL) {
121 | return list2;
122 | }
123 | if (list2 == NULL) {
124 | return list1;
125 | }
126 | if(list1->size == 0)
127 | {
128 | free(list1);
129 | return list2;
130 | }
131 | if(list2->size == 0)
132 | {
133 | free(list2);
134 | return list1;
135 | }
136 | list1->tail->next = list2->head;
137 | list2->head->prev = list1->tail;
138 | list1->tail = list2->tail;
139 | list1->size += list2->size;
140 | free(list2);
141 | return list1;
142 | }
143 |
144 | SimpleList_t SimpleList_destroy(SimpleList_t list, void (*destroyData)(void *)) {
145 | SimpleListNode_t node = list->head;
146 | while (node != NULL) {
147 | SimpleListNode_t next = node->next;
148 | if (destroyData != NULL) {
149 | destroyData(node->data);
150 | }
151 | free(node);
152 | node = next;
153 | }
154 | free(list);
155 | return NULL;
156 | }
157 |
--------------------------------------------------------------------------------
/src/Structure/SymbolTable.c:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/19.
3 | //
4 |
5 | #include
6 | #include
7 |
8 | #include "Structure/SymbolTable.h"
9 |
10 | #define SYMBOL_TABLE_HASH_TABLE_SIZE 10007
11 |
12 | ////////////////////////////////////////
13 | /// debug
14 | ////////////////////////////////////////
15 |
16 | void SymbolInfo_Struct_printDebug(SymbolInfo_t structInfo, char *buffer, int size);
17 |
18 | void SymbolInfo_Function_printDebug(SymbolInfo_t functionInfo, char *buffer, int size);
19 |
20 | void SymbolInfo_Variable_printDebug(SymbolInfo_t variableInfo, char *buffer, int size);
21 |
22 | void SymbolInfo_DebugHelper_getTypeString(Symbol_Value_Type e, void* meta, char buffer[], int bufferSize);
23 |
24 | ////////////////////////////////////////
25 | /// SymbolValue
26 | ////////////////////////////////////////
27 |
28 | int SymbolValue_getSize(Symbol_Value_Type type, SymbolInfo_t meta) {
29 | switch (type) {
30 | case SVT_Int:
31 | case SVT_Float:
32 | return 4;
33 | case SVT_Struct:
34 | return ((SymbolInfo_Struct_t)meta)->size;
35 | case SVT_Array:
36 | return ((SymbolInfo_Array_t)meta)->dimension * SymbolValue_getSize(((SymbolInfo_Array_t)meta)->elementType,
37 | ((SymbolInfo_Array_t)meta)->elementMeta);
38 | default:
39 | return 0;
40 | }
41 | return 0;
42 | }
43 |
44 | ////////////////////////////////////////
45 | /// SymbolTable
46 | ////////////////////////////////////////
47 |
48 | SymbolTable_t SymbolTable_create() {
49 | SymbolTable_t table = (SymbolTable_t)malloc(sizeof(SymbolTable));
50 | table->table = SimpleHashTable_createWithSize(sizeof(SymbolRecord), NULL, NULL, SYMBOL_TABLE_HASH_TABLE_SIZE);
51 | table->nextScopeID = 0;
52 | table->scopeStack = SimpleArray_create(sizeof(int));
53 | table->currentScope = 0;
54 | table->nextVarID = 0;
55 | table->nextLabelID = 0;
56 | SymbolTable_enterScope(table);
57 | return table;
58 | }
59 |
60 | void SymbolTable_destroy(void* tableToDestroy){
61 | SymbolTable_t table = (SymbolTable_t)tableToDestroy;
62 | SimpleHashTable_destroy(table->table, NULL, SymbolRecord_destroy);
63 | SimpleArray_destroy(table->scopeStack, NULL);
64 | free(table);
65 | }
66 |
67 | void SymbolTable_enterScope(SymbolTable_t table) {
68 | table->currentScope = table->nextScopeID;
69 | SimpleArray_pushBack(table->scopeStack, &table->nextScopeID);
70 | table->nextScopeID++;
71 | }
72 |
73 | void SymbolTable_leaveScope(SymbolTable_t table) {
74 | assert(table->scopeStack->num > 0);
75 | SimpleArray_popBack(table->scopeStack, NULL);
76 | table->currentScope = *(int *) SimpleArray_back(table->scopeStack);
77 | }
78 |
79 | int SymbolTable_getScope(SymbolTable_t table) {
80 | return *(int *) SimpleArray_back(table->scopeStack);
81 | }
82 |
83 | void SymbolTable_generateName(SymbolTable_t table, char *name, char *buffer, int bufferSize) {
84 | snprintf(buffer, bufferSize, "+%d_%s", table->currentScope, name);
85 | }
86 |
87 | SymbolDefineStatus SymbolTable_lookupRecord(SymbolTable_t table, char *name, SymbolRecord_t *outRecord) {
88 | int scopeIndex = SymbolTable_internalLookupRecord(table, name, outRecord);
89 | if(scopeIndex == -1)
90 | {
91 | return SDS_Undefined;
92 | }
93 | if(scopeIndex==table->scopeStack->num-1)
94 | {
95 | if(SymbolRecord_isSymbolDefined(*outRecord))
96 | return SDS_Defined;
97 | else
98 | return SDS_Declared;
99 | }
100 | else
101 | {
102 | if(SymbolRecord_isSymbolDefined(*outRecord))
103 | return SDS_ExternalDefined;
104 | else
105 | return SDS_ExternalDeclared;
106 | }
107 | }
108 |
109 | int SymbolTable_internalLookupRecord(SymbolTable_t table, char *name, SymbolRecord_t *outRecord) {
110 | for(int i = table->scopeStack->num - 1; i >= 0; i--){
111 | int scope = *(int*) SimpleArray_at(table->scopeStack, i);
112 | char buffer[256];
113 | snprintf(buffer, sizeof(buffer), "+%d_%s", scope, name);
114 | #ifdef SYMBOL_TABLE_DEBUG
115 | printf("Looking up \"%s\"\n", buffer);
116 | #endif
117 | SymbolRecord_t record = SimpleHashTable_find(table->table, buffer, (int)strlen(buffer)+1);
118 | if(record != NULL){
119 | *outRecord = record;
120 | return i;
121 | }
122 | }
123 | #ifdef SYMBOL_TABLE_DEBUG
124 | printf("Failed to find \"%s\"\n", name);
125 | #endif
126 | *outRecord = NULL;
127 | return -1;
128 | }
129 |
130 |
131 | SymbolDefineStatus
132 | SymbolTable_lookupRecordInScope(SymbolTable_t table, char *name, int scope, SymbolRecord_t *outRecord) {
133 | char buffer[256];
134 | snprintf(buffer, sizeof(buffer), "+%d_%s", scope, name);
135 | SymbolRecord_t record = SimpleHashTable_find(table->table, buffer, (int)strlen(buffer)+1);
136 | if(record == NULL) {
137 | *outRecord = NULL;
138 | return SDS_Undefined;
139 | }
140 | *outRecord = record;
141 | if(SymbolRecord_isSymbolDefined(record))
142 | return SDS_Defined;
143 | else
144 | return SDS_Declared;
145 | }
146 |
147 | int SymbolTable_insertRecord(SymbolTable_t table, char *name, SymbolRecord_t record) {
148 | char fullNameBuffer[256];
149 | SymbolTable_generateName(table, name, fullNameBuffer, sizeof(fullNameBuffer));
150 | #ifdef SYMBOL_TABLE_STRUCT_NAME
151 | if(record->type == ST_Struct){
152 | SymbolInfo_Struct_setName(record->info, name);
153 | }
154 | #endif
155 | if(record->type == ST_Function){
156 | SymbolInfo_Function_setName(record->info, name);
157 | }
158 | #ifndef SYMBOL_TABLE_DEBUG
159 | return SimpleHashTable_insert(table->table, fullNameBuffer, (int)strlen(fullNameBuffer)+1, record);
160 | #else
161 | char debugBuffer[1024];
162 | int result = SimpleHashTable_insert(table->table, fullNameBuffer, (int)strlen(fullNameBuffer) + 1, record);
163 | if(result == 0){
164 | SymbolRecord_printDebug(record, debugBuffer, 1024);
165 | printf("Inserted record \"%s\": %s\n", fullNameBuffer, debugBuffer);
166 | }
167 | else
168 | {
169 | printf("Failed to insert record \"%s\": %s\n", fullNameBuffer, debugBuffer);
170 | }
171 | return result;
172 | #endif
173 | }
174 |
175 | void SymbolTable_createVariableByInfo(SymbolTable_t table, SymbolRecord *outRecord, SymbolInfo_t info)
176 | {
177 | outRecord->type = ST_Variable;
178 | outRecord->info = info;
179 | }
180 |
181 | void SymbolTable_createFunctionByInfo(SymbolTable_t table, SymbolRecord *outRecord, SymbolInfo_t info) {
182 | outRecord->type = ST_Function;
183 | outRecord->info = info;
184 | }
185 |
186 | void SymbolTable_createStructByInfo(SymbolTable_t table, SymbolRecord *outRecord, SymbolInfo_t info) {
187 | outRecord->type = ST_Struct;
188 | outRecord->info = info;
189 | }
190 |
191 | ////////////////////////////////////////
192 | /// SymbolRecord
193 | ////////////////////////////////////////
194 |
195 | void SymbolRecord_destroy(void* recordToDestroy){
196 | SymbolRecord_t record = (SymbolRecord_t)recordToDestroy;
197 | switch(record->type)
198 | {
199 | case ST_Variable:
200 | SymbolInfo_Variable_destroy(record->info);
201 | break;
202 | case ST_Function:
203 | SymbolInfo_Function_destroy(record->info);
204 | break;
205 | case ST_Struct:
206 | SymbolInfo_Struct_destroy(record->info);
207 | break;
208 | default:
209 | break;
210 | }
211 | free(record);
212 | }
213 |
214 | ////////////////////////////////////////
215 | /// SymbolInfo
216 | ////////////////////////////////////////
217 |
218 |
219 | SymbolInfo_Variable_t SymbolInfo_Variable_createBaked(Symbol_Value_Type type, SymbolInfo_t meta){
220 | SymbolInfo_Variable_Raw info = NULL;
221 | switch(type){
222 | case SVT_Int:
223 | info = (SymbolInfo_Variable_Raw)malloc(sizeof(SymbolInfo_Variable));
224 | ((SymbolInfo_Variable_Raw)info)->type = SVT_Int;
225 | ((SymbolInfo_Variable_Raw)info)->meta = NULL;
226 | ((SymbolInfo_Variable_Raw)info)->varID = 0;
227 | return info;
228 | case SVT_Float:
229 | info = (SymbolInfo_Variable_Raw)malloc(sizeof(SymbolInfo_Variable));
230 | ((SymbolInfo_Variable_Raw)info)->type = SVT_Float;
231 | ((SymbolInfo_Variable_Raw)info)->meta = NULL;
232 | ((SymbolInfo_Variable_Raw)info)->varID = 0;
233 | return info;
234 | case SVT_Struct:
235 | info = (SymbolInfo_Variable_Raw)malloc(sizeof(SymbolInfo_Variable));
236 | ((SymbolInfo_Variable_Raw)info)->type = SVT_Struct;
237 | ((SymbolInfo_Variable_Raw)info)->meta = meta;
238 | ((SymbolInfo_Variable_Raw)info)->varID = 0;
239 | return info;
240 | case SVT_Array:
241 | info = (SymbolInfo_Variable_Raw)malloc(sizeof(SymbolInfo_Variable));
242 | ((SymbolInfo_Variable_Raw)info)->type = SVT_Array;
243 | ((SymbolInfo_Variable_Raw)info)->meta = meta;
244 | ((SymbolInfo_Variable_Raw)info)->varID = 0;
245 | return info;
246 | default:
247 | return NULL;
248 | }
249 | }
250 |
251 | void SymbolInfo_Variable_destroy(SymbolInfo_Variable_t info) {
252 | if(info == NULL)
253 | return;
254 | else if(info->type == SVT_Array){
255 | SymbolInfo_Array_destroy(info->meta);
256 | }
257 | free(info);
258 | }
259 |
260 | SymbolInfo_Array_t SymbolInfo_Array_createBaked(Symbol_Value_Type elementType, SymbolInfo_t elementStructInfo, int dimensions[], int dimensionCount){
261 | SymbolInfo_Array_Raw info = (SymbolInfo_Array_Raw)malloc(sizeof(SymbolInfo_Array));
262 | info->dimensionCount = dimensionCount;
263 | info->dimension = dimensions[0];
264 | if(dimensionCount > 1){
265 | info->elementType = SVT_Array;
266 | info->elementMeta = SymbolInfo_Array_createBaked(elementType, elementStructInfo, dimensions+1, dimensionCount-1);
267 | }else{
268 | info->elementType = elementType;
269 | info->elementMeta = elementStructInfo;
270 | }
271 | return info;
272 | }
273 |
274 | void SymbolInfo_Array_destroy(SymbolInfo_Array_t info) {
275 | if(info == NULL)
276 | return;
277 | if(info->elementType == SVT_Array){
278 | SymbolInfo_Array_destroy(info->elementMeta);
279 | }
280 | free(info);
281 | }
282 |
283 | SymbolInfo_Function_t
284 | SymbolInfo_Function_createBaked(Symbol_Value_Type returnType, SymbolInfo_t returnTypeMeta, Symbol_Value_Type parameterTypes[],
285 | char *parameterNames[], void *parametersMeta[], int parameterCount){
286 | SymbolInfo_Function_Raw rawInfo = (SymbolInfo_Function_Raw)malloc(sizeof(SymbolInfo_Function));
287 | rawInfo->returnType = returnType;
288 | rawInfo->returnTypeMeta = returnTypeMeta;
289 | rawInfo->parameterCount = parameterCount;
290 | // cast to void* to make clang-tidy happy
291 | rawInfo->parameters = (void*)(SymbolInfo_Parameter_Raw*)malloc(sizeof(SymbolInfo_Parameter_Raw) * parameterCount);
292 | for(int i = 0; i < parameterCount; i++){
293 | rawInfo->parameters[i] = SymbolInfo_Parameter_createBaked(parameterTypes[i], parameterNames[i], parametersMeta[i]);
294 | }
295 | rawInfo->isDefined = 0;
296 | return rawInfo;
297 | }
298 |
299 | void SymbolInfo_Function_destroy(SymbolInfo_Function_t info) {
300 | if(info == NULL)
301 | return;
302 | if(info->functionName != NULL)
303 | free(info->functionName);
304 | if(info->returnType == SVT_Array){
305 | SymbolInfo_Array_destroy(info->returnTypeMeta);
306 | }
307 | for(int i = 0; i < info->parameterCount; i++){
308 | SymbolInfo_Parameter_t parameter = info->parameters[i];
309 | if(parameter->parameterName != NULL)
310 | free(parameter->parameterName);
311 | if(parameter->parameterType == SVT_Array){
312 | SymbolInfo_Array_destroy(parameter->parameterMeta);
313 | }
314 | free(parameter);
315 | }
316 | free(info->parameters);
317 | free(info);
318 | }
319 |
320 | int SymbolInfo_Function_hasParameterName(SymbolInfo_Function_t functionInfo, char* parameterName){
321 | if(parameterName == NULL)
322 | {
323 | return 0;
324 | }
325 | for(int i = 0; i < functionInfo->parameterCount; i++)
326 | {
327 | SymbolInfo_Parameter_t parameter = functionInfo->parameters[i];
328 | if(parameter->parameterName != NULL && strcmp(parameter->parameterName, parameterName) == 0)
329 | {
330 | return 1;
331 | }
332 | }
333 | return 0;
334 | }
335 |
336 | void SymbolInfo_Function_addParameter(SymbolInfo_Function_t functionInfo, SymbolInfo_t parameter){
337 | functionInfo->parameters[functionInfo->parameterCount] = parameter;
338 | functionInfo->parameterCount++;
339 | }
340 |
341 | /**
342 | * Get the name of the function.
343 | * @param info The baked SymbolInfo_Function.
344 | * @return The name of the function.
345 | */
346 | char* SymbolInfo_Function_getName(SymbolInfo_Function_t info){
347 | return info->functionName;
348 | }
349 |
350 | /**
351 | * Set the name of the function.
352 | * @param info The baked SymbolInfo_Function.
353 | * @param name The name of the function, will be duplicated.
354 | */
355 | void SymbolInfo_Function_setName(SymbolInfo_Function_t info, char* name){
356 | info->functionName = name == NULL ? NULL : strdup(name);
357 | }
358 |
359 | SymbolInfo_Parameter_t SymbolInfo_Parameter_createBaked(Symbol_Value_Type type, char* parameterName, SymbolInfo_t meta){
360 | SymbolInfo_Parameter_Raw info = (SymbolInfo_Parameter_Raw)malloc(sizeof(SymbolInfo_Parameter));
361 | info->parameterType = type;
362 | info->parameterName = parameterName == NULL ? NULL : strdup(parameterName);
363 | info->parameterMeta = meta;
364 | return info;
365 | }
366 |
367 | SymbolInfo_Struct_t
368 | SymbolInfo_Struct_createBaked(Symbol_Value_Type *memberTypes, char **memberNames, void **memberMeta, int memberCount) {
369 | SymbolInfo_Struct_Raw info = (SymbolInfo_Struct_Raw)malloc(sizeof(SymbolInfo_Struct));
370 | info->memberCount = memberCount;
371 | // cast to void* to make clang-tidy happy
372 | info->members = (void*)(SymbolInfo_Member_Raw*)malloc(sizeof(SymbolInfo_Member_Raw) * memberCount);
373 | for(int i = 0; i < memberCount; i++){
374 | info->members[i] = SymbolInfo_Member_create(memberTypes[i], memberNames[i], memberMeta[i]);
375 | }
376 | return info;
377 | }
378 |
379 |
380 | void SymbolInfo_Struct_destroy(SymbolInfo_Struct_t info) {
381 | if(info == NULL)
382 | return;
383 | #ifdef SYMBOL_TABLE_STRUCT_NAME
384 | if(info->structName != NULL)
385 | free(info->structName);
386 | #endif
387 | if(info->memberCount == 0)
388 | return;
389 | for(int i = 0; i < info->memberCount; i++){
390 | SymbolInfo_Member_t member = info->members[i];
391 | SymbolInfo_Member_destroy(member);
392 | }
393 | free(info->members);
394 | free(info);
395 | }
396 |
397 | int SymbolInfo_Struct_checkMemberName(SymbolInfo_Struct_t info, char* memberName){
398 | for(int i = 0; i < info->memberCount; i++){
399 | SymbolInfo_Member_t member = info->members[i];
400 | if(strcmp(member->memberName, memberName) == 0){
401 | return 1;
402 | }
403 | }
404 | return 0;
405 | }
406 |
407 |
408 | void SymbolInfo_Struct_insertMember(SymbolInfo_Struct_t info, SymbolInfo_t memberInfo){
409 | info->members[info->memberCount] = memberInfo;
410 | info->memberCount++;
411 | ((SymbolInfo_Member_t) memberInfo)->offset = info->size;
412 | info->size += SymbolValue_getSize(((SymbolInfo_Member_t) memberInfo)->memberType, ((SymbolInfo_Member_t) memberInfo)->memberMeta);
413 | }
414 |
415 |
416 | #ifdef SYMBOL_TABLE_STRUCT_NAME
417 | char* SymbolInfo_Struct_getName(SymbolInfo_Struct_t info)
418 | {
419 | if(info == NULL)
420 | return NULL;
421 | return info->structName;
422 | }
423 |
424 | void SymbolInfo_Struct_setName(SymbolInfo_Struct_t info, char* name)
425 | {
426 | info->structName = name == NULL ? NULL : strdup(name);
427 | }
428 | #endif
429 |
430 | SymbolInfo_Member_Raw SymbolInfo_Member_create(Symbol_Value_Type memberType, char* memberName, void *memberMeta) {
431 | SymbolInfo_Member_Raw rawInfo = (SymbolInfo_Member_Raw)malloc(sizeof(SymbolInfo_Member));
432 | rawInfo->memberType = memberType;
433 | rawInfo->memberName = memberName == NULL ? NULL : strdup(memberName);
434 | rawInfo->memberMeta = memberMeta;
435 | return rawInfo;
436 | }
437 |
438 | SymbolInfo_Member_t SymbolInfo_Member_createBaked(Symbol_Value_Type memberType, char* memberName, SymbolInfo_t memberMeta){
439 | SymbolInfo_Member_Raw info = (SymbolInfo_Member_Raw)malloc(sizeof(SymbolInfo_Member));
440 | info->memberType = memberType;
441 | info->memberName = memberName == NULL ? NULL : strdup(memberName);
442 | info->memberMeta = memberMeta;
443 | return info;
444 | }
445 |
446 | void SymbolInfo_Member_destroy(SymbolInfo_Member_t info) {
447 | if(info == NULL)
448 | return;
449 | SymbolInfo_Member_t member = info;
450 | if(member->memberName != NULL)
451 | free(member->memberName);
452 | if(member->memberType == SVT_Array){
453 | SymbolInfo_Array_destroy(member->memberMeta);
454 | }
455 | free(member);
456 | }
457 |
458 | void SymbolRecord_printDebug(SymbolRecord_t record, char *buffer, int bufferSize) {
459 | if(record == NULL){
460 | snprintf(buffer, bufferSize, "NULL SymbolRecord");
461 | return;
462 | }
463 | switch (record->type) {
464 | case ST_Variable:
465 | SymbolInfo_Variable_printDebug(record->info, buffer, bufferSize);
466 | break;
467 | case ST_Function:
468 | SymbolInfo_Function_printDebug(record->info, buffer, bufferSize);
469 | break;
470 | case ST_Struct:
471 | SymbolInfo_Struct_printDebug(record->info, buffer, bufferSize);
472 | break;
473 | default:
474 | snprintf(buffer, bufferSize, "Unknown SymbolRecord type");
475 | break;
476 |
477 | }
478 | }
479 |
480 |
481 | int SymbolRecord_isSymbolDefined(SymbolRecord_t record) {
482 | switch(record->type){
483 | case ST_Variable:
484 | return 1;
485 | case ST_Function: {
486 | SymbolInfo_Function_t functionInfo = (SymbolInfo_Function_t) record->info;
487 | return functionInfo->isDefined;
488 | }
489 | case ST_Struct:
490 | return 1;
491 | default:
492 | return 0;
493 | }
494 | }
495 |
496 | int SymbolTable_getNextVarID(SymbolTable_t table) {
497 | return table->nextVarID++;
498 | }
499 |
500 | void SymbolTable_generateNextLabelName(SymbolTable_t table, char* buffer, int bufferSize){
501 | SymbolTable_generateNextLabelNameWithSuffix(table, buffer, bufferSize, "");
502 | }
503 |
504 | void SymbolTable_generateNextLabelNameWithSuffix(SymbolTable_t table, char* buffer, int bufferSize, char* suffix){
505 | snprintf(buffer, bufferSize, "label$%d%s", table->nextLabelID++, suffix);
506 | }
507 |
508 | void SymbolInfo_Variable_printDebug(SymbolInfo_t variableInfo, char *buffer, int size) {
509 | SymbolInfo_Variable_t info = (SymbolInfo_Variable_t)variableInfo;
510 | SymbolInfo_DebugHelper_getTypeString(info->type, info->meta, buffer, size);
511 | if(info->type == SVT_Struct){
512 | char structDefBuffer[256];
513 | SymbolInfo_Struct_printDebug(info->meta, structDefBuffer, sizeof(structDefBuffer));
514 | snprintf(buffer+strlen(buffer), size-strlen(buffer), "\n\tVariable %s", structDefBuffer);
515 | }
516 | if(info->type == SVT_Array)
517 | {
518 | SymbolInfo_Array_t arrayInfo = info->meta;
519 | if(arrayInfo->elementType == SVT_Struct){
520 | char structDefBuffer[256];
521 | SymbolInfo_Struct_printDebug(arrayInfo->elementMeta, structDefBuffer, sizeof(structDefBuffer));
522 | snprintf(buffer+strlen(buffer), size-strlen(buffer), "\n\tArray %s", structDefBuffer);
523 | }
524 | }
525 | }
526 |
527 | void SymbolInfo_Function_printDebug(SymbolInfo_t functionInfo, char *buffer, int size) {
528 | SymbolInfo_Function_t info = (SymbolInfo_Function_t)functionInfo;
529 | char returnTypeBuffer[256];
530 | SymbolInfo_DebugHelper_getTypeString(info->returnType, info->returnTypeMeta, returnTypeBuffer, sizeof(returnTypeBuffer));
531 | #ifndef SYMBOL_TABLE_FUNCTION_NAME
532 | snprintf(buffer, size, "Function: %s(", returnTypeBuffer);
533 | #else
534 | snprintf(buffer, size, "Function: %s %s(", returnTypeBuffer, info->functionName == NULL ? "NULL" : info->functionName);
535 | #endif
536 | int offset = (int)strlen(buffer);
537 | for(int i = 0; i < info->parameterCount; i++){
538 | char parameterTypeBuffer[256];
539 | SymbolInfo_Parameter_t paraInfo = info->parameters[i];
540 | SymbolInfo_DebugHelper_getTypeString(paraInfo->parameterType, paraInfo->parameterMeta, parameterTypeBuffer, sizeof(parameterTypeBuffer));
541 | offset += snprintf(buffer+offset, size-offset, "%s %s", parameterTypeBuffer, paraInfo->parameterName == NULL ? "NULL" : paraInfo->parameterName);
542 | if(i != info->parameterCount - 1){
543 | offset += snprintf(buffer+offset, size-offset, ", ");
544 | }
545 | }
546 | snprintf(buffer+offset, size-offset, ")");
547 | if(info->returnType== SVT_Struct){
548 | char structDefBuffer[256];
549 | SymbolInfo_Struct_printDebug(info->returnTypeMeta, structDefBuffer, sizeof(structDefBuffer));
550 | snprintf(buffer+strlen(buffer), size-strlen(buffer), "\n\tReturn %s", structDefBuffer);
551 | }
552 | for(int i = 0; i < info->parameterCount; i++) {
553 | SymbolInfo_Parameter_t param = info->parameters[i];
554 | if(param->parameterType == SVT_Struct){
555 | char structDefBuffer[256];
556 | SymbolInfo_Struct_printDebug(param->parameterMeta, structDefBuffer, sizeof(structDefBuffer));
557 | snprintf(buffer+strlen(buffer), size-strlen(buffer), "\n\tParam [%d] %s", i, structDefBuffer);
558 | }
559 | }
560 | }
561 |
562 | void SymbolInfo_Struct_printDebug(SymbolInfo_t structInfo, char *buffer, int size) {
563 | SymbolInfo_Struct_t info = (SymbolInfo_Struct_t)structInfo;
564 | #ifndef SYMBOL_TABLE_STRUCT_NAME
565 | snprintf(buffer, size, "Struct: {");
566 | #else
567 | snprintf(buffer, size, "Struct \"%s\": {", info->structName == NULL ? "NULL" : info->structName);
568 | #endif
569 | int offset = (int)strlen(buffer);
570 | for(int i = 0; i < info->memberCount; i++){
571 | char memberTypeBuffer[256];
572 | SymbolInfo_Member_t memberInfo = info->members[i];
573 | SymbolInfo_DebugHelper_getTypeString(memberInfo->memberType, memberInfo->memberMeta, memberTypeBuffer, sizeof(memberTypeBuffer));
574 | offset += snprintf(buffer+offset, size-offset, "%s %s", memberTypeBuffer, memberInfo->memberName == NULL ? "NULL" : memberInfo->memberName);
575 | if(i != info->memberCount - 1){
576 | offset += snprintf(buffer+offset, size-offset, ", ");
577 | }
578 | }
579 | snprintf(buffer+offset, size-offset, "}");
580 | for(int i = 0; i < info->memberCount; i++) {
581 | SymbolInfo_Member_t member = info->members[i];
582 | if(member->memberType == SVT_Struct){
583 | char structDefBuffer[256];
584 | SymbolInfo_Struct_printDebug(member->memberMeta, structDefBuffer, sizeof(structDefBuffer));
585 | snprintf(buffer+strlen(buffer), size-strlen(buffer), "\n\tMember [%s] %s", member->memberName, structDefBuffer);
586 | }
587 | }
588 | }
589 |
590 | void SymbolInfo_DebugHelper_getTypeString(Symbol_Value_Type e, void* meta, char *buffer, int bufferSize) {
591 | switch (e) {
592 | case SVT_Int:
593 | snprintf(buffer, bufferSize, "int");
594 | break;
595 | case SVT_Float:
596 | snprintf(buffer, bufferSize, "float");
597 | break;
598 | case SVT_Struct:
599 | #ifndef SYMBOL_TABLE_STRUCT_NAME
600 | snprintf(buffer, bufferSize, "struct");
601 | #else
602 | snprintf(buffer, bufferSize, "struct \"%s\"", SymbolInfo_Struct_getName((SymbolInfo_Struct_t)meta));
603 | #endif
604 | break;
605 | case SVT_Array: {
606 | SymbolInfo_Array_t arrayInfo = (SymbolInfo_Array_t) meta;
607 | char dimBuffer[256];
608 | char dimListBuffer[256];
609 | snprintf(dimBuffer, sizeof(dimBuffer), "[%d]", arrayInfo->dimension);
610 | while(arrayInfo->dimensionCount > 1){
611 | arrayInfo = arrayInfo->elementMeta;
612 | snprintf(dimBuffer, sizeof(dimBuffer), "[%d]", arrayInfo->dimension);
613 | snprintf(dimListBuffer+strlen(dimListBuffer), sizeof(dimListBuffer)-strlen(dimListBuffer), "%s", dimBuffer);
614 | }
615 | char elementTypeBuffer[256];
616 | SymbolInfo_DebugHelper_getTypeString(arrayInfo->elementType, arrayInfo->elementMeta, elementTypeBuffer, sizeof(elementTypeBuffer));
617 | snprintf(buffer, bufferSize, "%s %s", elementTypeBuffer , dimBuffer);
618 | break;
619 | }
620 | case SVT_Void:
621 | snprintf(buffer, bufferSize, "void");
622 | break;
623 | default:
624 | snprintf(buffer, bufferSize, "Unknown_Type");
625 | break;
626 | }
627 | }
628 |
629 |
630 |
--------------------------------------------------------------------------------
/src/Structure/TokenName.c:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Crystal on 2024/3/18.
3 | //
4 | #include "CmmParserTypes.h"
5 | #include "Structure/TokenName.h"
6 |
7 | char GrammarSymbolNames[ARGS - PROGRAM + 1][20] = {
8 | "Program",
9 | "ExtDefList",
10 | "ExtDef",
11 | "ExtDecList",
12 | "Specifier",
13 | "StructSpecifier",
14 | "OptTag",
15 | "Tag",
16 | "VarDec",
17 | "FunDec",
18 | "VarList",
19 | "ParamDec",
20 | "CompSt",
21 | "StmtList",
22 | "Stmt",
23 | "DefList",
24 | "Def",
25 | "DecList",
26 | "Dec",
27 | "Exp",
28 | "Args"
29 | };
30 |
31 | char TokenNames[WHILE - INT + 1][20] = {
32 | "INT",
33 | "FLOAT",
34 | "ID",
35 | "SEMI",
36 | "COMMA",
37 | "ASSIGNOP",
38 | "RELOP",
39 | "RELOP",
40 | "RELOP",
41 | "RELOP",
42 | "RELOP",
43 | "RELOP",
44 | "PLUS",
45 | "MINUS",
46 | "STAR",
47 | "DIV",
48 | "AND",
49 | "OR",
50 | "DOT",
51 | "NOT",
52 | "TYPE",
53 | "LP",
54 | "RP",
55 | "LB",
56 | "RB",
57 | "LC",
58 | "RC",
59 | "STRUCT",
60 | "RETURN",
61 | "IF",
62 | "ELSE",
63 | "WHILE"
64 | };
65 |
66 | const char *getGrammarSymbolName(int grammarSymbol) {
67 | return GrammarSymbolNames[grammarSymbol - PROGRAM];
68 | }
69 |
70 | const char* getTokenName(int token)
71 | {
72 | return TokenNames[token - INT];
73 | }
74 |
--------------------------------------------------------------------------------