3.2.5.9 写一个词法分析器

词法分析器或者叫扫描器主要用来分析字符串的文本,然后把文本里组成的单词分析出来,,识别为某一类型的属性。对于编写编译器或者解析器的第一步工作就是做这样的事情:词法分析。以前有很多种使用字符串搜索的办法,这里使用正则表达式来实现这个目的。

例子:

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 深圳

版权声明:本文为博主原创文章,未经博主允许不得转载。

接受失败也等于给了自己从零开始的机会,接受失败更是一种智者的宣言和呐喊;

3.2.5.9 写一个词法分析器

相关文章:

你感兴趣的文章:

标签云: