llvm tutorial
llvm是一种由Chris Lattner提出的编译器的架构,由C++编写,可以作为任意语言的编译器后端。Kaleidoscope Tutorial向开发者展示了如何完整实现一门简单的编程语言。接下来是该手册的各个章节
Chapter 1
为了实现一门编程语言,首先要做的事情就是扫描、分析该语言的源文件。因此,lexer(或叫scanner),即词法分析器是必需的。lexer将源文件分解成一个个的token,这些token包括元数据(metadata)和关键字(token code)。例如下面的代码:
// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
// of these for known things.
enum Token {
tok_eof = -1,
// commands
tok_def = -2,
tok_extern = -3,
// primary
tok_identifier = -4,
tok_number = -5,
};
static std::string IdentifierStr; // Filled in if tok_identifier
static double NumVal; // Filled in if tok_number
全局变量IdentifierStr存放关键字,而全局变量NumVal(这里假定该语言的数据类型有且仅有double类型)存放常量数值。
lexer的核心功能是从输入中读取token。函数gettok形式如下:
/// gettok - Return the next token from standard input.
static int gettok() {
static int LastChar = ' ';
// Skip any whitespace.
while (isspace(LastChar))
LastChar = getchar();
gettok需要跳过源文件中的空格,并且将最后读取的字符存储下来,然后,还需要识别关键字(例如def,extern等)。
if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
IdentifierStr = LastChar;
while (isalnum((LastChar = getchar())))
IdentifierStr += LastChar;
if (IdentifierStr == "def")
return tok_def;
if (IdentifierStr == "extern")
return tok_extern;
return tok_identifier;
}
数字等常量采用如下方式读取,注意这里采用strtod完成字符串到数字的转换
if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+
std::string NumStr;
do {
NumStr += LastChar;
LastChar = getchar();
} while (isdigit(LastChar) || LastChar == '.');
NumVal = strtod(NumStr.c_str(), 0);
return tok_number;
}
另外,我们还需要处理注释部分(注释以#开头):
if (LastChar == '#') {
// Comment until end of line.
do
LastChar = getchar();
while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
if (LastChar != EOF)
return gettok();
}
完整的lexer部分代码参见 http://llvm.org/docs/tutorial/LangImpl02.html#full-code-listing