词法分析把源代码转换成单词流。
词法部分与正则文法相对应,读取前缀几个字符就可以区分是什么单词。
特别设计时会让词法分析变得简单。如:变量名不能是数字开头的,这样读到数字,就知道后面是number常量,而不是变量名。
经过设计后,手写词法分析会很简单。lua的词法分析部分伪代码
function Lex()
local _char = CurrentChar()
if IsDigit(_char) then
return [读取数字常量]
elseif IsLetter(_char) or _char == '_' then
local name = [读取标识符]
if IsReserveKey(name) then
return [确定是什么类型的保留字,一般用个hash表存起来]
else
return [name是变量名]
elseif _char == '\"' or _char == '\'' then
return [读取字符串常量]
elseif _char == '>' then
// 这里需要看两个字符才能确定后面是什么单词
_char = NextChar()
if _char == '=' then
return [大于等于]
else
return [大于]
[elseif ...]
elseif [_char是单字符运算符,如+*%] then
return [单字符token]
elseif [_char是空白符] then
NextChar() // 跳过
return Lex()
end
end
php的词法分析的特殊处理
词法分析一般是无状态的,没有上下文依赖。读去下一个单词,不需要知道上一个单词是什么。
但是php的字符串比较特殊。
php支持很方便的字符串连接语法,使用起来和字符串替换类似。如$name = "我"; echo "i am $name"
。
这里的"i am $name"
是两个单词,在读到$name
时就需要知道当前是不是在处理字符串连接。这个状态是需要词法分析区分保存。