词法分析器或者叫扫描器主要用来分析字符串的文本,然后把文本里组成的单词分析出来,,识别为某一类型的属性。对于编写编译器或者解析器的第一步工作就是做这样的事情:词法分析。以前有很多种使用字符串搜索的办法,这里使用正则表达式来实现这个目的。
例子:
print("词法分析器")import collectionsimport reToken = collections.namedtuple(‘Token’, [‘typ’, ‘value’, ‘line’, ‘column’])def tokenize(code):keywords = {‘IF’, ‘THEN’, ‘ENDIF’, ‘FOR’, ‘NEXT’, ‘GOSUB’, ‘RETURN’}token_specification = [(‘NUMBER’, r’\d+(\.\d*)?’), # Integer or decimal number(‘ASSIGN’, r’:=’),# Assignment operator(‘END’,r’;’),# Statement terminator(‘ID’,r'[A-Za-z]+’), # Identifiers(‘OP’,r'[+\-*/]’),# Arithmetic operators(‘NEWLINE’, r’\n’),# Line endings(‘SKIP’, r'[ \t]+’),# Skip over spaces and tabs(‘MISMATCH’,r’.’),# Any other character]tok_regex = ‘|’.join(‘(?P<%s>%s)’ % pair for pair in token_specification)line_num = 1line_start = 0for mo in re.finditer(tok_regex, code):kind = mo.lastgroupvalue = mo.group(kind)if kind == ‘NEWLINE’:line_start = mo.end()line_num += 1elif kind == ‘SKIP’:passelif kind == ‘MISMATCH’:raise RuntimeError(‘%r unexpected on line %d’ % (value, line_num))else:if kind == ‘ID’ and value in keywords:kind = valuecolumn = mo.start() – line_startyield Token(kind, value, line_num, column)statements = ”’IF quantity THENtotal := total + price * quantity;tax := price * 0.05;ENDIF;”’for token in tokenize(statements):print(token)
结果输出如下:
词法分析器
Token(typ=’IF’,value=’IF’,line=2,column=4)
Token(typ=’ID’,value=’quantity’,line=2,column=7)
Token(typ=’THEN’,value=’THEN’,line=2,column=16)
Token(typ=’ID’,value=’total’,line=3,column=8)
Token(typ=’ASSIGN’,value=’:=’,line=3,column=14)
Token(typ=’ID’,value=’total’,line=3,column=17)
Token(typ=’OP’,value=’+’,line=3,column=23)
Token(typ=’ID’,value=’price’,line=3,column=25)
Token(typ=’OP’,value=’*’,line=3,column=31)
Token(typ=’ID’,value=’quantity’,line=3,column=33)
Token(typ=’END’,value=’;’,line=3,column=41)
Token(typ=’ID’,value=’tax’,line=4,column=8)
Token(typ=’ASSIGN’,value=’:=’,line=4,column=12)
Token(typ=’ID’,value=’price’,line=4,column=15)
Token(typ=’OP’,value=’*’,line=4,column=21)
Token(typ=’NUMBER’,value=’0.05′,line=4,column=23)
Token(typ=’END’,value=’;’,line=4,column=27)
Token(typ=’ENDIF’,value=’ENDIF’,line=5,column=4)
Token(typ=’END’,value=’;’,line=5,column=9)
在这个例子里,先从库
接着定义一个函数
(?P<NUMBER>\d+(\.\d*)?)|(?P<ASSIGN>:=)|(?P<END>;)|(?P<ID>[A-Za-z]+)|(?P<OP>[+\-*/])|(?P<NEWLINE>\n)|(?P<SKIP>[\t]+)|(?P<MISMATCH>.)
通过上面正则表达式,就可匹配所有规则,只要匹配成功,就保存在最后一个分组里,因而使用了
通过语句
值得注意的是,由于分析的文本长度不限,有可能达到
蔡军生 微信号:shenzhencai 深圳
版权声明:本文为博主原创文章,未经博主允许不得转载。
接受失败也等于给了自己从零开始的机会,接受失败更是一种智者的宣言和呐喊;