Kaleidoscope: Tutrial Introduction and the Lexer

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语言的完整词法分析器就完成了.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值