# 实现一个简单的解释器（2）

2019/04/10 10:10

“如果你只学习方法，那么你将被束缚在方法上。 但是，如果你学习了原理，就可以设计自己的方法。”

1、在输入字符串中的处理任何地方的空格 2、处理输入中的多位数整数 3、减去两个整数（当前只能加整数） 这是可以执行上述所有操作的新版本计算器的源代码：

# Token types
# EOF (end-of-file) token is used to indicate that
# there is no more input left for lexical analysis
INTEGER, PLUS, MINUS, EOF = 'INTEGER', 'PLUS', 'MINUS', 'EOF'

class Token(object):
def __init__(self, type, value):
# token type: INTEGER, PLUS, MINUS, or EOF
self.type = type
# token value: non-negative integer value, '+', '-', or None
self.value = value

def __str__(self):
"""String representation of the class instance.

Examples:
Token(INTEGER, 3)
Token(PLUS '+')
"""
return 'Token({type}, {value})'.format(
type=self.type,
value=repr(self.value)
)

def __repr__(self):
return self.__str__()

class Interpreter(object):
def __init__(self, text):
# client string input, e.g. "3 + 5", "12 - 5", etc
self.text = text
# self.pos is an index into self.text
self.pos = 0
# current token instance
self.current_token = None
self.current_char = self.text[self.pos]

def error(self):
raise Exception('Error parsing input')

"""Advance the 'pos' pointer and set the 'current_char' variable."""
self.pos += 1
if self.pos > len(self.text) - 1:
self.current_char = None  # Indicates end of input
else:
self.current_char = self.text[self.pos]

def skip_whitespace(self):
while self.current_char is not None and self.current_char.isspace():

def integer(self):
"""Return a (multidigit) integer consumed from the input."""
result = ''
while self.current_char is not None and self.current_char.isdigit():
result += self.current_char
return int(result)

def get_next_token(self):
"""Lexical analyzer (also known as scanner or tokenizer)

This method is responsible for breaking a sentence
apart into tokens.
"""
while self.current_char is not None:

if self.current_char.isspace():
self.skip_whitespace()
continue

if self.current_char.isdigit():

if self.current_char == '+':

if self.current_char == '-':

self.error()

def eat(self, token_type):
# compare the current token type with the passed token
# type and if they match then "eat" the current token
# and assign the next token to the self.current_token,
# otherwise raise an exception.
if self.current_token.type == token_type:
self.current_token = self.get_next_token()
else:
self.error()

def expr(self):
"""Parser / Interpreter

expr -> INTEGER PLUS INTEGER
expr -> INTEGER MINUS INTEGER
"""
# set current token to the first token taken from the input
self.current_token = self.get_next_token()

# we expect the current token to be an integer
left = self.current_token
self.eat(INTEGER)

# we expect the current token to be either a '+' or '-'
op = self.current_token
if op.type == PLUS:
self.eat(PLUS)
else:
self.eat(MINUS)

# we expect the current token to be an integer
right = self.current_token
self.eat(INTEGER)
# after the above call the self.current_token is set to
# EOF token

# at this point either the INTEGER PLUS INTEGER or
# the INTEGER MINUS INTEGER sequence of tokens
# has been successfully found and the method can just
# return the result of adding or subtracting two integers,
# thus effectively interpreting client input
if op.type == PLUS:
result = left.value + right.value
else:
result = left.value - right.value
return result

def main():
while True:
try:
# To run under Python3 replace 'raw_input' call
# with 'input'
text = raw_input('calc> ')
except EOFError:
break
if not text:
continue
interpreter = Interpreter(text)
result = interpreter.expr()
print(result)

if __name__ == '__main__':
main()


\$ python calc2.py
calc> 27 + 3
30
calc> 27 - 7
20
calc>


1、get_next_token函数被重构了一部分，递增pos指针的逻辑单独放入函数advance中。 2、添加了两个函数：skip_whitespace忽略空白字符，integer处理输入中的多位数整数。 3、修改了expr函数，以识别INTEGER-> MINUS-> INTEGER短语，以及INTEGER-> PLUS-> INTEGER短语。现在，函数可以在成功识别(recognize)相应短语之后来解释加法和减法运算。

1、扩展计算器以处理两个整数的乘法 2、扩展计算器以处理两个整数的除法 3、修改代码以解释包含任意数量的加法和减法的表达式，例如" 9-5 + 3 + 11"

1、什么是词素？ 2、在Token流中找到结构的过程称为什么，或者换句话说，识别该Token流中的特定短语的过程叫什么？ 3、解释器（编译器）中负责解析(parsing)的部分叫什么？

0
0 收藏

0 评论
0 收藏
0