from parsy import string, decimal_digit, generate, char_from from math import prod number = decimal_digit.at_least(1).concat().map(int) operator = string('*') | string('+') lparen = string('(') rparen = string(')') eol = string('\n') space = string(' ') @generate def calc_num(): next_val = yield lparen | number if next_val == '(': # do not return since (5 + 3) * 4 -> after getting 5 + 3, still possible to have a * 4 after lnum = yield calc_num else: lnum = next_val space_or_end = yield space | char_from( ')\n') # number is definitely there, but operator may not be there if space_or_end in ')\n': return [lnum] else: op = yield operator yield space rnum = yield calc_num return [lnum, op] + rnum
def test_decimal_digit(self): self.assertEqual(decimal_digit.at_least(1).concat().parse("9876543210"), "9876543210") self.assertRaises(ParseError, decimal_digit.parse, "¹")
from basic import Sym, WS, Punc from parsy import alt, decimal_digit, regex, seq, string def make_number(sign, int_part, frac_part): result = float(int_part + '.' + frac_part) if frac_part else int(int_part) return result * -1 if sign else result number_literal = seq(string('-').optional(), decimal_digit.at_least(1).concat(), string('.').then(decimal_digit.at_least(1).concat()).optional()).combine(make_number) string_literal = string('"') >> regex(r'[^"]*') << string('"') operator = regex(r'[]+*^/.\\@d_:!-]').map(Sym) func = regex(r'sin|cos|tan|asin|acos|atan|deg|rad|pi|e|ln|log').map(Sym) variable = regex(r'[A-Z]').map(Sym) punc = regex(r'[\[]').map(Punc) whitespace = string(' ').at_least(1).map(WS) stacky_parser = alt(number_literal, operator, punc, func, variable, whitespace).many()
from datetime import datetime from typing import Callable, List, Optional, Tuple from .core import Model from parsy import ( Parser, any_char, decimal_digit, generate, letter, seq, string, whitespace, ) some_digits = decimal_digit.at_least(1).concat() integer = some_digits.map(int).desc("integer") floating = ((some_digits + string(".") + some_digits).map(float).desc("floating-point number")) newline = string("\n") dash = string("-") def line_with(p: Parser) -> Parser: return whitespace.optional() >> p << newline