Skip to content

Commit b637b2f

Browse files
committed
完成了while语句,并添加了测试文件夹
1 parent 7a7a37c commit b637b2f

16 files changed

+184
-85
lines changed

AST.h

+34-22
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,6 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
174174

175175
const std::string &getName() const { return Name; }
176176

177-
/*
178-
* 待重构:VSL 中不需要 PrototypeAST
179-
* VSL 中的函数声明必须要带函数体,所以没有必要将 Prototype 分离出来
180-
*/
181177
Function * codegen() {
182178
//不允许函数重定义
183179
Function *TheFunction = TheModule->getFunction(Name);
@@ -411,9 +407,6 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
411407
std::unique_ptr<StatAST> Body)
412408
: Proto(std::move(Proto)), Body(std::move(Body)) {}
413409

414-
/*
415-
* 待重构:如上
416-
*/
417410
Function * codegen() {
418411
//可在当前模块中获取任何先前声明的函数的函数声明
419412
auto &P = *Proto;
@@ -500,12 +493,45 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
500493
:funcs(std::move(funcs)) {}
501494
};
502495

496+
class WhileStatAST:public StatAST{
497+
std::unique_ptr<StatAST> Expr, Stat;
498+
public:
499+
WhileStatAST(std::unique_ptr<StatAST> Expr, std::unique_ptr<StatAST> Stat):
500+
Expr(std::move(Expr)), Stat(std::move(Stat)){}
501+
502+
Value *codegen()
503+
{
504+
Function *TheFunction = Builder.GetInsertBlock()->getParent();
505+
BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction);
506+
BasicBlock *AfterBB = BasicBlock::Create(TheContext, "afterLoop", TheFunction);
507+
508+
Value *EndCond = Expr->codegen();
509+
if(!EndCond)
510+
return nullptr;
511+
EndCond = Builder.CreateICmpNE(EndCond, Builder.getInt32(0),
512+
"loopCondIn");
513+
Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
514+
515+
Builder.SetInsertPoint(LoopBB);
516+
Value *inLoopVal = Stat->codegen();
517+
if(!inLoopVal)
518+
return nullptr;
519+
EndCond = Builder.CreateICmpNE(Expr->codegen(),
520+
Builder.getInt32(0), "loopCondOut");
521+
Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
522+
523+
Builder.SetInsertPoint(AfterBB);
524+
525+
return Builder.getInt32(0);
526+
}
527+
};
528+
503529

504530
//创建和初始化模块和传递管理器
505531
static void InitializeModuleAndPassManager() {
506532

507533
// Open a new module.
508-
TheModule = llvm::make_unique<Module>("my cool jit", TheContext);
534+
TheModule = llvm::make_unique<Module>("VSL jit", TheContext);
509535
TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
510536

511537
// Create a new pass manager attached to it.
@@ -547,18 +573,4 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
547573
#else
548574
#define DLLEXPORT
549575
#endif
550-
551-
// putchard - putchar that takes a double and returns 0.
552-
extern "C" DLLEXPORT double putchard(double X) {
553-
fputc((char)X, stderr);
554-
return 0;
555-
}
556-
557-
// printd - printf that takes a double prints it as "%f\n", returning 0.
558-
extern "C" DLLEXPORT double printd(double X) {
559-
fprintf(stderr, "%f\n", X);
560-
return 0;
561-
}
562-
563-
564576
#endif
162 Bytes
Binary file not shown.

Lexer.h

+21-20
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ enum Token
3434

3535
static std::string IdentifierStr;
3636
static int NumberVal;
37+
static FILE *inputFile;
3738

3839
/*
3940
*返回输入单词类型
@@ -44,14 +45,14 @@ static int gettok()
4445

4546
//过滤空格
4647
while(isspace(LastChar))
47-
LastChar = getchar();
48+
LastChar = fgetc(inputFile);
4849

4950
//解析标识符:{lc_letter}({lc_letter}|{digit})*
5051
if(isalpha(LastChar))
5152
{
5253
IdentifierStr = "";
5354
IdentifierStr += LastChar;
54-
while(isalnum((LastChar = getchar())))
55+
while (isalnum((LastChar = fgetc(inputFile))))
5556
IdentifierStr += LastChar;
5657

5758
if(IdentifierStr == "FUNC")
@@ -88,7 +89,7 @@ static int gettok()
8889
std::string NumStr;
8990
do{
9091
NumStr += LastChar;
91-
LastChar = getchar();
92+
LastChar = fgetc(inputFile);
9293
}while(isdigit(LastChar));
9394

9495
NumberVal = atoi(NumStr.c_str());
@@ -98,11 +99,11 @@ static int gettok()
9899

99100
//解析注释:"//".*
100101
if(LastChar == '/')
101-
if((LastChar = getchar()) == '/')
102-
{
102+
if ((LastChar = fgetc(inputFile)) == '/')
103+
{
103104
do
104-
LastChar = getchar();
105-
while(LastChar != EOF && LastChar != '\n' && LastChar != '\r');
105+
LastChar = fgetc(inputFile);
106+
while(LastChar != EOF && LastChar != '\n' && LastChar != '\r');
106107

107108
//若未到达结尾,返回下一个输入类型
108109
if(LastChar != EOF)
@@ -112,23 +113,23 @@ static int gettok()
112113
}
113114

114115
//赋值符号
115-
if(LastChar == ':' && (LastChar = getchar()) == '=')
116+
if (LastChar == ':' && (LastChar = fgetc(inputFile)) == '=')
116117
{
117-
LastChar = getchar(); //获取下一个字符
118+
LastChar = fgetc(inputFile); //获取下一个字符
118119
return ASSIGN_SYMBOL;
119120
}
120121

121122
//TEXT
122123
if(LastChar == '\"')
123124
{
124125
IdentifierStr = "";
125-
LastChar = getchar();
126-
do
126+
LastChar = fgetc(inputFile);
127+
do
127128
{
128129
if(LastChar == '\\')
129130
{
130-
LastChar = getchar();
131-
if(LastChar == 'n')
131+
LastChar = fgetc(inputFile);
132+
if(LastChar == 'n')
132133
LastChar = '\n';
133134
else if(LastChar == 't')
134135
LastChar = '\t';
@@ -138,27 +139,27 @@ static int gettok()
138139
IdentifierStr += '\\';
139140
}
140141
IdentifierStr += LastChar;
141-
LastChar = getchar();
142+
LastChar = fgetc(inputFile);
142143
}while(LastChar != '\"');
143-
LastChar = getchar();
144+
LastChar = fgetc(inputFile);
144145
return TEXT;
145146
}
146147

147148
if(LastChar == '\\')
148149
{
149150
int tmp;
150-
LastChar = getchar();
151-
if(LastChar == 'n')
151+
LastChar = fgetc(inputFile);
152+
if(LastChar == 'n')
152153
tmp = '\n';
153154
else if(LastChar == 't')
154155
tmp = '\t';
155156
else if(LastChar == 'r')
156157
tmp = '\r';
157158
else
158159
return '\\';
159-
LastChar = getchar();
160+
LastChar = fgetc(inputFile);
160161

161-
return tmp;
162+
return tmp;
162163
}
163164

164165
//文档结束标志
@@ -167,7 +168,7 @@ static int gettok()
167168

168169
//以上情况均不满足,直接返回当前字符
169170
int tmpChar = LastChar;
170-
LastChar = getchar();
171+
LastChar = fgetc(inputFile);
171172

172173
return tmpChar;
173174
}

Parser.h

+33-23
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() {
209209
return llvm::make_unique<PrototypeAST>(FnName, std::move(ArgNames));
210210
}
211211

212-
//function ::= FUNC prototype '{' statement '}'
212+
//function ::= FUNC VARIABLE '(' parameter_lst ')' statement
213213
static std::unique_ptr<FunctionAST> ParseFunc()
214214
{
215215
getNextToken(); // eat FUNC.
@@ -337,7 +337,32 @@ static std::unique_ptr<StatAST> ParseAssStat() {
337337
return llvm::make_unique<AssStatAST>(std::move(NameV), std::move(Expression));
338338
}
339339

340-
static std::unique_ptr<StatAST> ParseStatement() {
340+
//解析while语句
341+
static std::unique_ptr<StatAST> ParseWhileStat()
342+
{
343+
getNextToken();//eat WHILE
344+
345+
auto E = ParseExpression();
346+
if(!E)
347+
return nullptr;
348+
349+
if(CurTok != DO)
350+
return LogErrorS("expect DO in WHILE statement");
351+
getNextToken();//eat DO
352+
353+
auto S = ParseStatement();
354+
if(!S)
355+
return nullptr;
356+
357+
if(CurTok != DONE)
358+
return LogErrorS("expect DONE in WHILE statement");
359+
getNextToken();//eat DONE
360+
361+
return llvm::make_unique<WhileStatAST>(std::move(E), std::move(S));
362+
}
363+
364+
static std::unique_ptr<StatAST> ParseStatement()
365+
{
341366
switch (CurTok) {
342367
case IF:
343368
return ParseIfStat();
@@ -349,6 +374,9 @@ static std::unique_ptr<StatAST> ParseStatement() {
349374
case VAR:
350375
return ParseDec();
351376
break;
377+
case WHILE:
378+
return ParseWhileStat();
379+
break;
352380
default:
353381
auto E = ParseAssStat();
354382
return E;
@@ -440,27 +468,9 @@ static void HandleTopLevelExpression() {
440468
}
441469
}
442470

443-
//program ::= definition | expression
471+
//program ::= function_list
444472
static void MainLoop() {
445-
446-
while (true) {
447-
fprintf(stderr, "ready> ");
448-
switch (CurTok) {
449-
case ';': // ignore top-level semicolons.
450-
getNextToken();
451-
break;
452-
case TOK_EOF:
453-
return;
454-
case FUNC:
455-
HandleFuncDefinition();
456-
break;
457-
case VAR:
458-
459-
default:
460-
HandleTopLevelExpression();
461-
break;
462-
}
463-
}
464-
473+
while(CurTok != TOK_EOF)
474+
HandleFuncDefinition();
465475
}
466476
#endif

main.cpp

+33-20
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include <cstdio>
2+
#include <cstdlib>
13
#include "Lexer.h"
24
#include "AST.h"
35
#include "Parser.h"
@@ -9,32 +11,43 @@
911
#include "../include/KaleidoscopeJIT.h"
1012
#endif
1113

14+
void usage()
15+
{
16+
printf("usage:./VSL file\n");
1217

13-
int main() {
14-
InitializeNativeTarget();
15-
InitializeNativeTargetAsmPrinter();
16-
InitializeNativeTargetAsmParser();
18+
exit(EXIT_FAILURE);
19+
}
20+
21+
int main(int argc, char *argv[]) {
22+
if(argc != 2)
23+
usage();
24+
inputFile = fopen(argv[1], "r");
25+
if(!inputFile){
26+
printf("%s open error!\n", argv[0]);
27+
exit(EXIT_FAILURE);
28+
}
1729

18-
BinopPrecedence['+'] = 10;
19-
BinopPrecedence['-'] = 10;
20-
BinopPrecedence['*'] = 40;
21-
BinopPrecedence['/'] = 40;
30+
InitializeNativeTarget();
31+
InitializeNativeTargetAsmPrinter();
32+
InitializeNativeTargetAsmParser();
2233

23-
// Prime the first token.
24-
fprintf(stderr, "ready> ");
25-
getNextToken();
34+
BinopPrecedence['+'] = 10;
35+
BinopPrecedence['-'] = 10;
36+
BinopPrecedence['*'] = 40;
37+
BinopPrecedence['/'] = 40;
2638

27-
// Make the module, which holds all the code.
28-
//TheModule = new Module("my cool jit", TheContext);
39+
// Make the module, which holds all the code.
40+
//TheModule = new Module("my cool jit", TheContext);
2941

30-
TheJIT = llvm::make_unique<KaleidoscopeJIT>();
31-
InitializeModuleAndPassManager();
42+
TheJIT = llvm::make_unique<KaleidoscopeJIT>();
43+
InitializeModuleAndPassManager();
3244

33-
// Run the main "interpreter loop" now.
34-
MainLoop();
45+
// Run the main "interpreter loop" now.
46+
getNextToken();
47+
MainLoop();
3548

36-
// Print out all of the generated code.
37-
TheModule->print(errs(), nullptr);
49+
// Print out all of the generated code.
50+
//TheModule->print(errs(), nullptr);
3851

39-
return 0;
52+
return 0;
4053
}

tests/VSL

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/home/mt/作业/解释器构造实践/VSL/bin/Debug/VSL

tests/t_assign.VSL

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
FUNC a(x)
2+
x := 2

tests/t_block.VSL

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FUNC a()
2+
{
3+
VAR a
4+
a := 2
5+
6+
RETURN a
7+
}

0 commit comments

Comments
 (0)