# Fetch the next expression expr = context.expression() # Eat the next token, that should be a ')' context.consume(expect_class=RightParen) return expr class RightParen(Token): regexp = r'\)' class Comma(Token): regexp = r',' lexer = Lexer() lexer.register_tokens( Symbol, Number, String, Addition, Substraction, Multiplication, Division, LeftParen, RightParen, Comma) _variable_format = re.compile('^' + variable_format + '$') def parse_expression(expression): equal = expression.find('=') if equal == -1: raise InvalidOperation("Missing target variable name", "new_var = %s" % expression, (0, 7))
from tdparser import Lexer, Parser, Token, ParserError from tdparser.topdown import EndToken __all__ = ['parse_expression', 'parse_expressions'] def escape_string(text): return '"%s"' % text.replace('\\', '\\\\').replace('"', '\\"') def unescape_string(text): assert text[0] == text[-1] == '"' return text[1:-1].replace('\\"', '"').replace('\\\\', '\\') lexer = Lexer() class Key(Token): regexp = r'[A-Za-z_][A-Za-z0-9_]*' def nud(self, context): return self class Number(Token): regexp = r'-?\d+' type = 'int' def __init__(self, text): Token.__init__(self, text)
# of same precedence right_side = context.expression(self.lbp) return left + right_side class Substraction(Token): lbp = 10 # Same precedence as addition def led(self, left, context): return left - context.expression(self.lbp) def nud(self, context): """When a '-' is present on the left of an expression.""" # This means that we are returning the opposite of the next expression return - context.expression(self.lbp) class Multiplication(Token): lbp = 20 # Higher precedence than addition/substraction def led(self, left, context): return left * context.expression(self.lbp) lexer = Lexer(with_parens=True) lexer.register_token(Integer, re.compile(r'\d+')) lexer.register_token(Addition, re.compile(r'\+')) lexer.register_token(Substraction, re.compile(r'-')) lexer.register_token(Multiplication, re.compile(r'\*')) def parse(text): return lexer.parse(text)
class Power(Token): lbp = 30 # Higher than mult def led(self, left, context): # We pick expressions with a lower precedence, so that # 2 ** 3 ** 2 computes as 2 ** (3 ** 2) return left ** context.expression(self.lbp - 1) class Log(Token): lbp = 30 # Higher than mult def nud(self, context): return log(float(context.expression(self.lbp - 1))) lexer = Lexer(with_parens=True) lexer.register_token(Integer, re.compile(r'\d+')) lexer.register_token(Float, re.compile(r'\d+\.\d+')) lexer.register_token(Addition, re.compile(r'\+')) lexer.register_token(Substraction, re.compile(r'-')) lexer.register_token(Multiplication, re.compile(r'\*')) lexer.register_token(Division, re.compile(r'/')) lexer.register_token(Power, re.compile(r'\*\*')) lexer.register_token(Log, re.compile(r'log')) def parse(text): return lexer.parse(text)
# Fetch the next expression expr = context.expression() # Eat the next token, that should be a ')' context.consume(expect_class=RightParen) return expr class RightParen(Token): regexp = r'\)' class Comma(Token): regexp = r',' lexer = Lexer() lexer.register_tokens(Symbol, Number, String, Addition, Substraction, Multiplication, Division, LeftParen, RightParen, Comma) _variable_format = re.compile('^' + variable_format + '$') def parse_expression(expression): equal = expression.find('=') if equal == -1: raise InvalidOperation("Missing target variable name", "new_var = %s" % expression, (0, 7)) else: target = expression[:equal].strip() if not _variable_format.match(target): right = equal
from tdparser.topdown import EndToken __all__ = ['parse_expression', 'parse_expressions'] def escape_string(text): return '"%s"' % text.replace('\\', '\\\\').replace('"', '\\"') def unescape_string(text): assert text[0] == text[-1] == '"' return text[1:-1].replace('\\"', '"').replace('\\\\', '\\') lexer = Lexer() class Key(Token): regexp = r'[A-Za-z_][A-Za-z0-9_]*' def nud(self, context): return self class Number(Token): regexp = r'-?\d+' type = 'int' def __init__(self, text): Token.__init__(self, text)
# Fetch the expression to the right, stoping at the next boundary # of same precedence right_side = context.expression(self.lbp) return left + right_side class Substraction(Token): lbp = 10 # Same precedence as addition def led(self, left, context): return left - context.expression(self.lbp) def nud(self, context): """When a '-' is present on the left of an expression.""" # This means that we are returning the opposite of the next expression return - context.expression(self.lbp) class Multiplication(Token): lbp = 20 # Higher precedence than addition/substraction def led(self, left, context): return left * context.expression(self.lbp) lexer = Lexer(with_parens=True) lexer.register_token(Integer, re.compile(r'\d+')) lexer.register_token(Addition, re.compile(r'\+')) lexer.register_token(Substraction, re.compile(r'-')) lexer.register_token(Multiplication, re.compile(r'\*')) def parse(text): return lexer.parse(text)
class LeftParen(Token): match = RightParen def nud(self, context): expr = context.expression() context.consume(expect_class=self.match) return expr def __repr__(self): return '<(>' # регистрация токенов lexer = Lexer() lexer.register_tokens(Integer, Addition, Multiplication, Division) lexer.register_token(LeftParen, re.compile(r'\(')) lexer.register_token(RightParen, re.compile(r'\)')) def parse(text): """Преобразует лексические токены в представление""" return lexer.parse(text) print("(((10+1)*(5+6/(3+1))+4*(3+1)))") print( f'Результат вычеслений после разбора: {parse("(((10+1)*(5+6/(3+1))+4*(3+1)))")}' )