Kaleidoscope: Tutorial Introduction and the Lexer
Basic Language
Kaleidoscope
使用Kaleidoscope作爲玩具語言,我們可以定義函數,使用條件,數學等.
唯一的數據類型是64位浮點類型(C語言中稱爲"double"),並且不需要類型聲明,語法簡單.
以計算Fibonacci數爲例:
def fib(x)
if x < 3 then
1
else
fib(x-1) + fib(x-2)
Kaleidoscope可以調用標準庫函數,可以使用"extern"來定義函數,如:
extern sin(arg)
extern cos(arg)
extern atan2(arg1 arg2)
atan2(sin(.4), cos(42))
The Lexer 詞法分析器
在實現一種語言時,首先需要處理文本文件並識別它所說內容.使用詞法分析器將輸入分解爲"tokens", 詞法分析器返回的token包括一個標記代碼和可能的一些元數據.首先,我們定義了可能的值:
//如果是未知字符, 詞法分析器返回標記[0-255], 否則的話以下值之一會被返回
enum Token{
tok_eof = -1,
//commands
tok_def = -2,
tok_extern = -3,
//primary
tok_identifier = -4,
tok_number = -5,
};
static std::string IdentifierStr; //如果是tok_identifer, 填寫
static double NumVal; //如果是tok_number, 填寫
詞法分析器返回的token是Token枚舉值之一,或者,‘未知’字符的話, 如’+’,將返回ASCII值. 如果當前token是標識符, 則IdentifierStr全局變量保存其名稱. 如果是一個數值字符,如(1.0), 則NumVal保存其值.
詞法分析器實際實現爲gettok函數,當從標準輸入返回下一個標記時, gettok被調用. 它的定義爲:
static int gettok(){
static int LastChar = ' ';
//跳過空格
while (isspace(LastChar))
LastChar = getchar();
}
接下來, gettok需要做的是識別標識符和關鍵字,如’def’. IdenfitifierStr設置爲全局,使用下面循環實現:
if (isalpha(LastChar)){ // identifer: [a-zA-Z][a-zA-Z0-9]*
IdentiferStr = LastChar;
while (isalnum((LastChar = getchar())))
IdentifierStr += LastChar;
if (IdentifierStr == "def")
return tol_def;
if (IdentiferStr == "extern")
return tok_extern;
return tok_identifier;
}
對於數值的處理類似:
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); //strtod將字符串轉換爲浮點數值
return tok_number;
}
其中, c_str()函數返回一個指向正規C字符串的指針, 內容與本string串相同.這是爲了與c語言兼容,在c語言中沒有string類型,故必須通過string類對象的成員函數c_str()把string 對象轉換成c中的字符串樣式其中,.
接下來我們處理註釋, 通過調到行尾來處理,然後返回下一個token.:
if (LastChar == '#') {
//處理到行尾的註釋
do
LastChar = getchar();
while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); //\r是回車
if (LastChar != EOF)
return gettok();
}
最後,如果輸入與上述情況之一不匹配,則它是像’+'這樣的運算符或者文件結尾,可以使用以下代碼處理:
// 檢查是否文件結尾,保留EOF
if (LastChar == EOF)
return tok_eof;
// 否則,直接返回其ascii值
int ThisChar = LastChar;
LastChar = getchar();
return ThisChar;
到此,一個基本的Kaleidoscope語言的完整詞法分析器就完成了.