def p_Slot(self, token): self.consume() text = token.text if len(text) == 1: n = Number('1') else: n = text[1:] if n.isdigit(): n = Number(n) else: n = String(n) return Node('Slot', n)
def e_Minus(self, expr1, token, p): q = left_binary_ops['Subtract'] if q < p: return None self.consume() expr2 = self.parse_exp(q + 1) if isinstance(expr2, Number) and not expr2.value.startswith('-'): expr2.value = '-' + expr2.value else: expr2 = Node('Times', Number('1', sign=-1), expr2).flatten() return Node('Plus', expr1, expr2).flatten()
def testList(self): self.check('{x, y}', Node('List', Symbol('x'), Symbol('y'))) self.check('{1}', Node('List', Number('1'))) self.check('{}', Node('List')) self.check('{a,}', Node('List', Symbol('a'), Symbol('Null'))) self.check('{,}', Node('List', Symbol('Null'), Symbol('Null'))) self.check('{a, b,}', Node('List', Symbol('a'), Symbol('b'), Symbol('Null'))) self.check('{,a}', Node('List', Symbol('Null'), Symbol('a'))) self.check('{, a, b}', Node('List', Symbol('Null'), Symbol('a'), Symbol('b'))) self.check('{,a,b,}', Node('List', Symbol('Null'), Symbol('a'), Symbol('b'), Symbol('Null')))
def p_Number(self, token): s = token.text # sign if s[0] == "-": s = s[1:] sign = -1 else: sign = 1 # base s = s.split("^^") if len(s) == 1: base, s = 10, s[0] else: assert len(s) == 2 base, s = int(s[0]), s[1] if not 2 <= base <= 36: self.tokeniser.feeder.message("General", "base", base, token.text, 36) self.tokeniser.sntx_message(token.pos) raise InvalidSyntaxError() # mantissa s = s.split("*^") if len(s) == 1: exp, s = 0, s[0] else: # TODO modify regex and provide error if `exp` is not an int exp, s = int(s[1]), s[0] # precision/accuracy s = s.split("`", 1) if len(s) == 1: s, suffix = s[0], None else: s, suffix = s[0], s[1] for i, c in enumerate(s.lower()): if permitted_digits[c] >= base: self.tokeniser.feeder.message("General", "digit", i + 1, s, base) self.tokeniser.sntx_message(token.pos) raise InvalidSyntaxError() result = Number(s, sign=sign, base=base, suffix=suffix, exp=exp) self.consume() return result
def testFunctional(self): self.check('expr1 @ expr2', Node('expr1', Symbol('expr2'))) self.check('f @@ expr', Node('Apply', Symbol('f'), Symbol('expr'))) self.check('f /@ expr', Node('Map', Symbol('f'), Symbol('expr'))) self.check( 'f @@@ expr', Node('Apply', Symbol('f'), Symbol('expr'), Node('List', Number('1')))) self.check('f //@ expr', Node('MapAll', Symbol('f'), Symbol('expr'))) self.check( 'a @@ b @@ c', Node('Apply', Symbol('a'), Node('Apply', Symbol('b'), Symbol('c')))) self.check('a /@ b @@ c', 'Map[a, Apply[b, c]]') self.check('a @@ b /@ c', 'Apply[a, Map[b, c]]')
def p_Slot(self, token): self.consume() text = token.text if len(text) == 1: n = Number('1') else: n = text[1:] if n.isdigit(): n = Number(n) else: n = String(n) return Node('Slot', n)
def testCompound(self): self.check( 'a ; {b}', Node('CompoundExpression', Symbol('a'), Node('List', Symbol('b')))) self.check('1 ;', Node('CompoundExpression', Number('1'), Symbol('Null'))) self.check('1 ; 5', Node('CompoundExpression', Number('1'), Number('5'))) self.check( '4; 1 ; 5', Node('CompoundExpression', Number('4'), Number('1'), Number('5'))) self.check( '4;1;', Node('CompoundExpression', Number('4'), Number('1'), Symbol('Null'))) self.check( '(a;b);c', Node('CompoundExpression', Node('CompoundExpression', Symbol('a'), Symbol('b')), Symbol('c'))) self.check('f[a;]', 'f[CompoundExpression[a, Null]]')
def testFunctional(self): self.check("expr1 @ expr2", Node("expr1", Symbol("expr2"))) self.check("f @@ expr", Node("Apply", Symbol("f"), Symbol("expr"))) self.check("f /@ expr", Node("Map", Symbol("f"), Symbol("expr"))) self.check( "f @@@ expr", Node("Apply", Symbol("f"), Symbol("expr"), Node("List", Number("1"))), ) self.check("f //@ expr", Node("MapAll", Symbol("f"), Symbol("expr"))) self.check( "a @@ b @@ c", Node("Apply", Symbol("a"), Node("Apply", Symbol("b"), Symbol("c"))), ) self.check("a /@ b @@ c", "Map[a, Apply[b, c]]") self.check("a @@ b /@ c", "Apply[a, Map[b, c]]")
def testList(self): self.check("{x, y}", Node("List", Symbol("x"), Symbol("y"))) self.check("{1}", Node("List", Number("1"))) self.check("{}", Node("List")) self.check("{a,}", Node("List", Symbol("a"), Symbol("Null"))) self.check("{,}", Node("List", Symbol("Null"), Symbol("Null"))) self.check("{a, b,}", Node("List", Symbol("a"), Symbol("b"), Symbol("Null"))) self.check("{,a}", Node("List", Symbol("Null"), Symbol("a"))) self.check("{, a, b}", Node("List", Symbol("Null"), Symbol("a"), Symbol("b"))) self.check( "{,a,b,}", Node("List", Symbol("Null"), Symbol("a"), Symbol("b"), Symbol("Null")), )
def testPlus(self): self.check('+1', Node('Plus', Number('1'))) self.check('1 + 2', Node('Plus', Number('1'), Number('2'))) self.check('1 + 2 + 3', Node('Plus', Number('1'), Number('2'), Number('3'))) self.check('1 + 2 + 3 + 4', 'Plus[1, 2, 3, 4]') self.check('-a', Node('Times', Number('-1'), Symbol('a'))) self.check( 'a - b', Node('Plus', Symbol('a'), Node('Times', Number('-1'), Symbol('b')))) self.check( 'a*b+c', Node('Plus', Node('Times', Symbol('a'), Symbol('b')), Symbol('c'))) self.check( 'a*+b+c', Node('Plus', Node('Times', Symbol('a'), Node('Plus', Symbol('b'))), Symbol('c'))) self.check('a+b*c', 'a+(b*c)') self.check('a*b+c', '(a*b) + c') self.check('1-2', '1 - 2')
def testCompare(self): self.check("1 == 2", Node("Equal", Number("1"), Number("2"))) self.check("1 != 2", Node("Unequal", Number("1"), Number("2"))) self.check("1 == 2 == 3", Node("Equal", Number("1"), Number("2"), Number("3"))) self.check("1 != 2 != 3", Node("Unequal", Number("1"), Number("2"), Number("3"))) self.check("1 > 2", Node("Greater", Number("1"), Number("2"))) self.check("1 >= 2", Node("GreaterEqual", Number("1"), Number("2"))) self.check("1 < 2", Node("Less", Number("1"), Number("2"))) self.check("1 <= 2", Node("LessEqual", Number("1"), Number("2"))) self.check("1 > 2 > 3", Node("Greater", Number("1"), Number("2"), Number("3"))) self.check("1 >= 2 >= 3", Node("GreaterEqual", Number("1"), Number("2"), Number("3"))) self.check("1 < 2 < 3", Node("Less", Number("1"), Number("2"), Number("3"))) self.check("1 <= 2 <= 3", Node("LessEqual", Number("1"), Number("2"), Number("3"))) self.check("1 === 2", Node("SameQ", Number("1"), Number("2"))) self.check("1 =!= 2", Node("UnsameQ", Number("1"), Number("2"))) self.check("1 === 2 === 3", Node("SameQ", Number("1"), Number("2"), Number("3"))) self.check("1 =!= 2 =!= 3", Node("UnsameQ", Number("1"), Number("2"), Number("3")))
def testRepeated(self): self.check("1..", Node("Repeated", Number("1"))) self.check("1...", Node("RepeatedNull", Number("1")))
def testSpan(self): self.check(";;", Node("Span", Number("1"), Symbol("All"))) self.check( "a;;b;;", Node( "Times", Node("Span", Symbol("a"), Symbol("b")), Node("Span", Number("1"), Symbol("All")), ), ) self.check("1;;2;;3", Node("Span", Number("1"), Number("2"), Number("3"))) self.check("1;; ;;3", Node("Span", Number("1"), Symbol("All"), Number("3"))) self.check("1;;;;3", Node("Span", Number("1"), Symbol("All"), Number("3"))) self.check( "1;;2;;", Node( "Times", Node("Span", Number("1"), Number("2")), Node("Span", Number("1"), Symbol("All")), ), ) self.check(" ;;2;;3", Node("Span", Number("1"), Number("2"), Number("3"))) self.check(" ;;2", Node("Span", Number("1"), Number("2"))) self.check("1;; ", Node("Span", Number("1"), Symbol("All"))) self.check(" ;; ", Node("Span", Number("1"), Symbol("All"))) self.check("1;;2;;3;;4;;5;;6", "Times[Span[1, 2, 3], Span[1, 4, 5], Span[1, 6]]") self.check("(a;;b);;c", "Span[Span[a, b], c]")
def testBinOp(self): self.check("1 <> 2 ", Node("StringJoin", Number("1"), Number("2"))) self.check("1 <> 2 <> 3", Node("StringJoin", Number("1"), Number("2"), Number("3"))) self.check("1 ^ 2", Node("Power", Number("1"), Number("2"))) self.check("1 . 2", Node("Dot", Number("1"), Number("2"))) self.check("1 && 2", Node("And", Number("1"), Number("2"))) self.check("1 || 2", Node("Or", Number("1"), Number("2"))) self.check("x /; y", Node("Condition", Symbol("x"), Symbol("y"))) self.check("x -> y", Node("Rule", Symbol("x"), Symbol("y"))) self.check("x :> y", Node("RuleDelayed", Symbol("x"), Symbol("y"))) self.check("x /. y", Node("ReplaceAll", Symbol("x"), Symbol("y"))) self.check("x //. y", Node("ReplaceRepeated", Symbol("x"), Symbol("y"))) self.check("x += y", Node("AddTo", Symbol("x"), Symbol("y"))) self.check("x -= y", Node("SubtractFrom", Symbol("x"), Symbol("y"))) self.check("x *= y", Node("TimesBy", Symbol("x"), Symbol("y"))) self.check("x /= y", Node("DivideBy", Symbol("x"), Symbol("y"))) self.check( "3/2", Node("Times", Number("3"), Node("Power", Number("2"), Number("-1")))) self.check("x ~~ y", Node("StringExpression", Symbol("x"), Symbol("y"))) self.check( "x ~~ y ~~ z", Node("StringExpression", Symbol("x"), Symbol("y"), Symbol("z")), )
def testCompare(self): self.check('1 == 2', Node('Equal', Number('1'), Number('2'))) self.check('1 != 2', Node('Unequal', Number('1'), Number('2'))) self.check('1 == 2 == 3', Node('Equal', Number('1'), Number('2'), Number('3'))) self.check('1 != 2 != 3', Node('Unequal', Number('1'), Number('2'), Number('3'))) self.check('1 > 2', Node('Greater', Number('1'), Number('2'))) self.check('1 >= 2', Node('GreaterEqual', Number('1'), Number('2'))) self.check('1 < 2', Node('Less', Number('1'), Number('2'))) self.check('1 <= 2', Node('LessEqual', Number('1'), Number('2'))) self.check('1 > 2 > 3', Node('Greater', Number('1'), Number('2'), Number('3'))) self.check('1 >= 2 >= 3', Node('GreaterEqual', Number('1'), Number('2'), Number('3'))) self.check('1 < 2 < 3', Node('Less', Number('1'), Number('2'), Number('3'))) self.check('1 <= 2 <= 3', Node('LessEqual', Number('1'), Number('2'), Number('3'))) self.check('1 === 2', Node('SameQ', Number('1'), Number('2'))) self.check('1 =!= 2', Node('UnsameQ', Number('1'), Number('2'))) self.check('1 === 2 === 3', Node('SameQ', Number('1'), Number('2'), Number('3'))) self.check('1 =!= 2 =!= 3', Node('UnsameQ', Number('1'), Number('2'), Number('3')))
def testTimes(self): self.check("1 2", Node("Times", Number("1"), Number("2"))) self.check("1*2", Node("Times", Number("1"), Number("2"))) self.check("1 2 3", Node("Times", Number("1"), Number("2"), Number("3"))) self.check( "(1 2) 3", Node("Times", Node("Times", Number("1"), Number("2")), Number("3")), ) self.check("1*2*3", Node("Times", Number("1"), Number("2"), Number("3"))) self.check( "x ^ 2 y", Node("Times", Node("Power", Symbol("x"), Number("2")), Symbol("y")), )
def testPart(self): self.check("a[[1]]", Node("Part", Symbol("a"), Number("1")))
def testBinOp(self): self.check('1 <> 2 ', Node('StringJoin', Number('1'), Number('2'))) self.check('1 <> 2 <> 3', Node('StringJoin', Number('1'), Number('2'), Number('3'))) self.check('1 ^ 2', Node('Power', Number('1'), Number('2'))) self.check('1 . 2', Node('Dot', Number('1'), Number('2'))) self.check('1 && 2', Node('And', Number('1'), Number('2'))) self.check('1 || 2', Node('Or', Number('1'), Number('2'))) self.check('x /; y', Node('Condition', Symbol('x'), Symbol('y'))) self.check('x -> y', Node('Rule', Symbol('x'), Symbol('y'))) self.check('x :> y', Node('RuleDelayed', Symbol('x'), Symbol('y'))) self.check('x /. y', Node('ReplaceAll', Symbol('x'), Symbol('y'))) self.check('x //. y', Node('ReplaceRepeated', Symbol('x'), Symbol('y'))) self.check('x += y', Node('AddTo', Symbol('x'), Symbol('y'))) self.check('x -= y', Node('SubtractFrom', Symbol('x'), Symbol('y'))) self.check('x *= y', Node('TimesBy', Symbol('x'), Symbol('y'))) self.check('x /= y', Node('DivideBy', Symbol('x'), Symbol('y'))) self.check( '3/2', Node('Times', Number('3'), Node('Power', Number('2'), Number('-1')))) self.check('x ~~ y', Node('StringExpression', Symbol('x'), Symbol('y'))) self.check( 'x ~~ y ~~ z', Node('StringExpression', Symbol('x'), Symbol('y'), Symbol('z')))
def testNonAscii(self): self.check("z \\[Conjugate]", Node("Conjugate", Symbol("z"))) self.check("z \\[Transpose]", Node("Transpose", Symbol("z"))) self.check("z \\[ConjugateTranspose]", Node("ConjugateTranspose", Symbol("z"))) self.check("z \uf3c7 ", Node("Transpose", Symbol("z"))) self.check("z \uf3c8 ", Node("Conjugate", Symbol("z"))) self.check("z \uf3c9 ", Node("ConjugateTranspose", Symbol("z"))) self.check( "\\[Integral] x \\[DifferentialD] x", Node("Integrate", Symbol("x"), Symbol("x")), ) self.check("\\[Del] x", Node("Del", Symbol("x"))) self.check("\\[Square] x", Node("Square", Symbol("x"))) self.check("1 \\[SmallCircle] 2", Node("SmallCircle", Number("1"), Number("2"))) self.check( "1 \\[SmallCircle] 2 \\[SmallCircle] 3", Node("SmallCircle", Number("1"), Number("2"), Number("3")), ) self.check("1 \u2218 2", Node("SmallCircle", Number("1"), Number("2"))) self.check("1 \\[CircleDot] 2", Node("CircleDot", Number("1"), Number("2"))) self.check("1 \u2299 2", Node("CircleDot", Number("1"), Number("2"))) self.check("1 \\[Diamond] 2", Node("Diamond", Number("1"), Number("2"))) self.check("1 \\[Wedge] 2", Node("Wedge", Number("1"), Number("2"))) self.check("1 \\[Vee] 2", Node("Vee", Number("1"), Number("2"))) self.check("1 \\[CircleTimes] 2", Node("CircleTimes", Number("1"), Number("2"))) self.check("1 \\[CenterDot] 2", Node("CenterDot", Number("1"), Number("2"))) self.check("1 \\[Star] 2", Node("Star", Number("1"), Number("2"))) self.check("a \\[Cap] b", "Cap[a,b]") self.check("a \\[Cup] b \\[Cup] c", "Cup[a,b,c]") self.check("a \u2322 b \u2322 c", "Cap[a,b,c]") self.check("a \u2323 b", "Cup[a, b]") self.check("1 \u22C4 2", Node("Diamond", Number("1"), Number("2"))) self.check("1 \u22C0 2", Node("Wedge", Number("1"), Number("2"))) self.check("1 \u22c1 2", Node("Vee", Number("1"), Number("2"))) self.check("1 \u2297 2", Node("CircleTimes", Number("1"), Number("2"))) self.check("1 \u00B7 2", Node("CenterDot", Number("1"), Number("2"))) self.check("1 \u22C6 2", Node("Star", Number("1"), Number("2"))) self.check( "expr1 ** expr2", Node("NonCommutativeMultiply", Symbol("expr1"), Symbol("expr2")), ) self.check( "expr1 ** expr2 ** expr3", Node( "NonCommutativeMultiply", Symbol("expr1"), Symbol("expr2"), Symbol("expr3"), ), ) self.check("1 \\[Cross] 2", Node("Cross", Number("1"), Number("2"))) self.check("1 \uf4a0 2", Node("Cross", Number("1"), Number("2"))) self.check( "3\\[Divide]2", Node("Times", Number("3"), Node("Power", Number("2"), Number("-1"))), ) self.check("3 \u00f7 2", "Times[3, Power[2, -1]]") self.scan_error("3\\2") self.check("1 \\[Times] 2", Node("Times", Number("1"), Number("2"))) self.check("1 \u00d7 2", Node("Times", Number("1"), Number("2"))) self.check("1 \\[PlusMinus] 2", Node("PlusMinus", Number("1"), Number("2"))) self.check("1 \\[MinusPlus] 2", Node("MinusPlus", Number("1"), Number("2"))) self.check("\\[PlusMinus] 1", Node("PlusMinus", Number("1"))) self.check("\\[MinusPlus] 1", Node("MinusPlus", Number("1"))) self.check("\u00b1 1", Node("PlusMinus", Number("1"))) self.check("\u2213 1", Node("MinusPlus", Number("1"))) self.check("1 \\[And] 2", Node("And", Number("1"), Number("2"))) self.check("1 \u2227 2", Node("And", Number("1"), Number("2"))) self.check("1 \\[Or] 2", Node("Or", Number("1"), Number("2"))) self.check("1 \u2228 2", Node("Or", Number("1"), Number("2"))) self.check("a \\[Colon] b", Node("Colon", Symbol("a"), Symbol("b"))) self.check("a \u2236 b", Node("Colon", Symbol("a"), Symbol("b"))) self.check("x1 \\[RightTee] x2", "RightTee[x1, x2]") self.check("x1 \\[DoubleRightTee] x2", "DoubleRightTee[x1, x2]") self.check("x1 \\[LeftTee] x2", "LeftTee[x1, x2]") self.check("x1 \\[DoubleLeftTee] x2", "DoubleLeftTee[x1, x2]")
def testAlternatives(self): self.check("1 | 2", Node("Alternatives", Number("1"), Number("2"))) self.check("1 | 2 | 3", Node("Alternatives", Number("1"), Number("2"), Number("3")))
def testNonAscii(self): self.check('z \\[Conjugate]', Node('Conjugate', Symbol('z'))) self.check('z \\[Transpose]', Node('Transpose', Symbol('z'))) self.check('z \\[ConjugateTranspose]', Node('ConjugateTranspose', Symbol('z'))) self.check('z \uf3c7 ', Node('Transpose', Symbol('z'))) self.check('z \uf3c8 ', Node('Conjugate', Symbol('z'))) self.check('z \uf3c9 ', Node('ConjugateTranspose', Symbol('z'))) self.check('\\[Integral] x \\[DifferentialD] x', Node('Integrate', Symbol('x'), Symbol('x'))) self.check('\\[Del] x', Node('Del', Symbol('x'))) self.check('\\[Square] x', Node('Square', Symbol('x'))) self.check('1 \\[SmallCircle] 2', Node('SmallCircle', Number('1'), Number('2'))) self.check('1 \\[SmallCircle] 2 \\[SmallCircle] 3', Node('SmallCircle', Number('1'), Number('2'), Number('3'))) self.check('1 \u2218 2', Node('SmallCircle', Number('1'), Number('2'))) self.check('1 \\[CircleDot] 2', Node('CircleDot', Number('1'), Number('2'))) self.check('1 \u2299 2', Node('CircleDot', Number('1'), Number('2'))) self.check('1 \\[Diamond] 2', Node('Diamond', Number('1'), Number('2'))) self.check('1 \\[Wedge] 2', Node('Wedge', Number('1'), Number('2'))) self.check('1 \\[Vee] 2', Node('Vee', Number('1'), Number('2'))) self.check('1 \\[CircleTimes] 2', Node('CircleTimes', Number('1'), Number('2'))) self.check('1 \\[CenterDot] 2', Node('CenterDot', Number('1'), Number('2'))) self.check('1 \\[Star] 2', Node('Star', Number('1'), Number('2'))) self.check('a \\[Cap] b', 'Cap[a,b]') self.check('a \\[Cup] b \\[Cup] c', 'Cup[a,b,c]') self.check('a \u2322 b \u2322 c', 'Cap[a,b,c]') self.check('a \u2323 b', 'Cup[a, b]') self.check('1 \u22C4 2', Node('Diamond', Number('1'), Number('2'))) self.check('1 \u22C0 2', Node('Wedge', Number('1'), Number('2'))) self.check('1 \u22c1 2', Node('Vee', Number('1'), Number('2'))) self.check('1 \u2297 2', Node('CircleTimes', Number('1'), Number('2'))) self.check('1 \u00B7 2', Node('CenterDot', Number('1'), Number('2'))) self.check('1 \u22C6 2', Node('Star', Number('1'), Number('2'))) self.check( 'expr1 ** expr2', Node('NonCommutativeMultiply', Symbol('expr1'), Symbol('expr2'))) self.check( 'expr1 ** expr2 ** expr3', Node('NonCommutativeMultiply', Symbol('expr1'), Symbol('expr2'), Symbol('expr3'))) self.check('1 \\[Cross] 2', Node('Cross', Number('1'), Number('2'))) self.check('1 \uf4a0 2', Node('Cross', Number('1'), Number('2'))) self.check( '3\\[Divide]2', Node('Times', Number('3'), Node('Power', Number('2'), Number('-1')))) self.check('3 \u00f7 2', 'Times[3, Power[2, -1]]') self.scan_error('3\\2') self.check('1 \\[Times] 2', Node('Times', Number('1'), Number('2'))) self.check('1 \u00d7 2', Node('Times', Number('1'), Number('2'))) self.check('1 \[PlusMinus] 2', Node('PlusMinus', Number('1'), Number('2'))) self.check('1 \[MinusPlus] 2', Node('MinusPlus', Number('1'), Number('2'))) self.check('\[PlusMinus] 1', Node('PlusMinus', Number('1'))) self.check('\[MinusPlus] 1', Node('MinusPlus', Number('1'))) self.check('\u00b1 1', Node('PlusMinus', Number('1'))) self.check('\u2213 1', Node('MinusPlus', Number('1'))) self.check('1 \\[And] 2', Node('And', Number('1'), Number('2'))) self.check('1 \u2227 2', Node('And', Number('1'), Number('2'))) self.check('1 \\[Or] 2', Node('Or', Number('1'), Number('2'))) self.check('1 \u2228 2', Node('Or', Number('1'), Number('2'))) self.check('a \\[Colon] b', Node('Colon', Symbol('a'), Symbol('b'))) self.check('a \u2236 b', Node('Colon', Symbol('a'), Symbol('b'))) self.check('x1 \\[RightTee] x2', 'RightTee[x1, x2]') self.check('x1 \\[DoubleRightTee] x2', 'DoubleRightTee[x1, x2]') self.check('x1 \\[LeftTee] x2', 'LeftTee[x1, x2]') self.check('x1 \\[DoubleLeftTee] x2', 'DoubleLeftTee[x1, x2]')
def testOut(self): self.check('%%', Node('Out', Number('-2'))) self.check('%%%%', Node('Out', Number('-4'))) self.check('%', Node('Out'))
def testPart(self): self.check('a[[1]]', Node('Part', Symbol('a'), Number('1')))
def testAlternatives(self): self.check('1 | 2', Node('Alternatives', Number('1'), Number('2'))) self.check('1 | 2 | 3', Node('Alternatives', Number('1'), Number('2'), Number('3')))
def testRepeated(self): self.check('1..', Node('Repeated', Number('1'))) self.check('1...', Node('RepeatedNull', Number('1')))
def p_Span(self, token): return self.e_Span(Number('1'), token, 0)
def testTimes(self): self.check('1 2', Node('Times', Number('1'), Number('2'))) self.check('1*2', Node('Times', Number('1'), Number('2'))) self.check('1 2 3', Node('Times', Number('1'), Number('2'), Number('3'))) self.check( '(1 2) 3', Node('Times', Node('Times', Number('1'), Number('2')), Number('3'))) self.check('1*2*3', Node('Times', Number('1'), Number('2'), Number('3'))) self.check( 'x ^ 2 y', Node('Times', Node('Power', Symbol('x'), Number('2')), Symbol('y')))
def testOut(self): self.check("%%", Node("Out", Number("-2"))) self.check("%%%%", Node("Out", Number("-4"))) self.check("%", Node("Out"))
def testSpan(self): self.check(';;', Node('Span', Number('1'), Symbol('All'))) self.check( 'a;;b;;', Node('Times', Node('Span', Symbol('a'), Symbol('b')), Node('Span', Number('1'), Symbol('All')))) self.check('1;;2;;3', Node('Span', Number('1'), Number('2'), Number('3'))) self.check('1;; ;;3', Node('Span', Number('1'), Symbol('All'), Number('3'))) self.check('1;;;;3', Node('Span', Number('1'), Symbol('All'), Number('3'))) self.check( '1;;2;;', Node('Times', Node('Span', Number('1'), Number('2')), Node('Span', Number('1'), Symbol('All')))) self.check(' ;;2;;3', Node('Span', Number('1'), Number('2'), Number('3'))) self.check(' ;;2', Node('Span', Number('1'), Number('2'))) self.check('1;; ', Node('Span', Number('1'), Symbol('All'))) self.check(' ;; ', Node('Span', Number('1'), Symbol('All'))) self.check('1;;2;;3;;4;;5;;6', 'Times[Span[1, 2, 3], Span[1, 4, 5], Span[1, 6]]') self.check('(a;;b);;c', 'Span[Span[a, b], c]')
def check_number(self, s): self.assertEqual(self.parse(s), Number(s))
def p_Number(self, token): result = Number(token.text) self.consume() return result