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

（已获得作者授权）

1、它们以图形方式表示编程语言的规范（语法）(grammar)。
2、它们可以用来帮助编写解析器(parser),我们可以按照简单的规则将图表映射(map)为代码。

• 3
• 3 + 4
• 7-3 + 2-1

>>> 3
3
>>> 3 + 4
7
>>> 7 - 3 + 2 - 1
5


>>> 3 +
File "<stdin>", line 1
3 +
^
SyntaxError: invalid syntax


def term(self):
self.eat(INTEGER)

def expr(self):
# set current token to the first token taken from the input
self.current_token = self.get_next_token()

self.term()
while self.current_token.type in (PLUS, MINUS):
token = self.current_token
if token.type == PLUS:
self.eat(PLUS)
self.term()
elif token.type == MINUS:
self.eat(MINUS)
self.term()


def term(self):
"""Return an INTEGER token value"""
token = self.current_token
self.eat(INTEGER)

def expr(self):
"""Parser / Interpreter """
# set current token to the first token taken from the input
self.current_token = self.get_next_token()

result = self.term()
while self.current_token.type in (PLUS, MINUS):
token = self.current_token
if token.type == PLUS:
self.eat(PLUS)
result = result + self.term()
elif token.type == MINUS:
self.eat(MINUS)
result = result - self.term()

return result


# 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 + 3", 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]

##########################################################
# Lexer code                                             #
##########################################################
def error(self):
raise Exception('Invalid syntax')

"""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. One token at a time.
"""
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()

##########################################################
# Parser / Interpreter code                              #
##########################################################
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 term(self):
"""Return an INTEGER token value."""
token = self.current_token
self.eat(INTEGER)

def expr(self):
"""Arithmetic expression parser / interpreter."""
# set current token to the first token taken from the input
self.current_token = self.get_next_token()

result = self.term()
while self.current_token.type in (PLUS, MINUS):
token = self.current_token
if token.type == PLUS:
self.eat(PLUS)
result = result + self.term()
elif token.type == MINUS:
self.eat(MINUS)
result = result - self.term()

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 calc3.py
calc> 3
3
calc> 7 - 4
3
calc> 10 + 5
15
calc> 7 - 3 + 2 - 1
5
calc> 10 + 1 + 2 - 3 + 4 + 6 - 15
5
calc> 3 +
Traceback (most recent call last):
File "calc3.py", line 147, in <module>
main()
File "calc3.py", line 142, in main
result = interpreter.expr()
File "calc3.py", line 123, in expr
result = result + self.term()
File "calc3.py", line 110, in term
self.eat(INTEGER)
File "calc3.py", line 105, in eat
self.error()
File "calc3.py", line 45, in error
raise Exception('Invalid syntax')
Exception: Invalid syntax


1、为仅包含乘法和除法的算术表达式绘制语法图，例如"7 * 4 / 2 * 3"。
2、修改计算器的源代码以解释仅包含乘法和除法的算术表达式，例如"7 * 4 / 2 * 3"。
3、从头开始编写一个解释器，处理诸如"7 - 3 + 2 - 1"之类的算术表达式。使用你喜欢的任何编程语言，并在不看示例的情况下将其写在脑海中，请考虑所涉及的组件：一个词法分析器，它接受输入并将其转换为Token流；解析器，将从词法分析器提供的Token流中尝试识别该流中的结构；以及在解析器成功解析（识别）有效算术表达式后生成结果的解释器。将这些组合在一起，花一些时间将学到的知识翻译成可用于算术表达式的解释器。

1、什么是语法图？
2、什么是语法分析？
3、什么是语法分析器？

posted on 2020-03-01 19:47  Xlgd  阅读(...)  评论(...编辑  收藏

• 随笔 - 23
• 文章 - 0
• 评论 - 4