译自:https://ruslanspivak.com/lsbasi-part6/
(已获得作者授权)
今天,我们通过将带括号的表达式添加到语法,并实现一个能够计算任意深度嵌套表达式的解释器来结束对算术表达式的讨论。
让我们开始吧!
首先,让我们修改语法以支持括号内的表达式,正如在第5部分中所记得的那样,factor规则用于表达式中的基本单位,在那篇文章中,我们仅有的基本单位是整数,今天我们添加了另外一个基本单位,也就是带括号的表达式。
这是我们更新的语法:
expr和term与第5部分完全相同,唯一的变化是factor的产生式,其中LPAREN表示左括号'(',RPAREN表示右括号')',而括号之间的非终结符expr表示expr规则。
这是factor的更新语法图:
因为expr和term的语法规则没有改变,所以它们的语法图看起来与第5部分中的相同:
这是我们新语法的一个有趣功能:递归,如果尝试推导表达式2 * (7 + 3),则将从expr起始符开始,之后将递归地再次使用expr规则来推导表达式(7 + 3)这一部分。
让我们根据语法分解表达式2 *(7 + 3):
好的,让我们开始将新的更新语法转换为代码。
以下是对上一篇文章代码的主要更改:
1、对Lexer进行修改,以返回另外两个标记:LPAREN用于左括号,而RPAREN用于右括号。
2、对解释器的factor函数进行修改,可以解析(parse)除整数以外的带括号的表达式。
这是计算器的完整代码,可以计算任意数量的加,减,乘和除整数运算以及带有任意深度嵌套的带括号的表达式:
# Token types
#
# EOF (end-of-file) token is used to indicate that
# there is no more input left for lexical analysis
INTEGER, PLUS, MINUS, MUL, DIV, LPAREN, RPAREN, EOF = (
'INTEGER', 'PLUS', 'MINUS', 'MUL', 'DIV', '(', ')', 'EOF'
)
class Token(object):
def __init__(self, type, value):
self.type = type
self.value = value
def __str__(self):
"""String representation of the class instance.
Examples:
Token(INTEGER, 3)
Token(PLUS, '+')
Token(MUL, '*')
"""
return 'Token({type}, {value})'.format(
type=self.type,
value=repr(self.value)
)
def __repr__(self):
return self.__str__()
class Lexer(object):
def __init__(self, text):
# client string input, e.g. "4 + 2 * 3 - 6 / 2"
self.text = text
# self.pos is an index into self.text
self.pos = 0
self.current_char = self.text[self.pos]
def error(self):
raise Exception('Invalid character')
def advance(self):
"""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():
self.advance()
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
self.advance()
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():
return Token(INTEGER, self.integer())
if self.current_char == '+':
self.advance()
return Token(PLUS, '+')
if self.current_char == '-':
self.advance()
return Token(MINUS, '-')
if self.current_char
关于找一找教程网
本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。
本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。
[实现一个简单的解释器(6)]http://www.zyiz.net/tech/detail-113704.html