def p_PatternTest(self, token): self.consume() q = prefix_ops["Definition"] child = self.parse_exp(q) return Node( "Information", child, Node("Rule", Symbol("LongForm"), Symbol("False")) )
def parse_inequality(self, expr1, token, p): tag = token.tag q = flat_binary_ops[tag] if q < p: return None self.consume() head = expr1.get_head_name() expr2 = self.parse_exp(q + 1) if head == 'Inequality' and not expr1.parenthesised: expr1.children.append(Symbol(tag)) expr1.children.append(expr2) elif head in inequality_ops and head != tag and not expr1.parenthesised: children = [] first = True for child in expr1.children: if not first: children.append(Symbol(head)) children.append(child) first = False children.append(Symbol(tag)) children.append(expr2) expr1 = Node('Inequality', *children) else: expr1 = Node(tag, expr1, expr2).flatten() return expr1
def testFunction(self): self.check('x &', Node('Function', Symbol('x'))) self.check('x \\[Function] y', 'Function[x, y]') self.check('x \uf4a1 y', 'Function[x, y]') self.incomplete_error('x \uf4a1') self.check('x & y', Node('Times', Node('Function', Symbol('x')), Symbol('y')))
def testSlot(self): self.check('#2', Node('Slot', Number('2'))) self.check('#', Node('Slot', Number('1'))) self.check('##2', Node('SlotSequence', Number('2'))) self.check('##', Node('SlotSequence', Number('1'))) self.check('%2', Node('Out', Number('2'))) self.check('#a', 'Slot["a"]')
def testFunction(self): self.check("x &", Node("Function", Symbol("x"))) self.check("x \\[Function] y", "Function[x, y]") self.check("x \uf4a1 y", "Function[x, y]") self.incomplete_error("x \uf4a1") self.check("x & y", Node("Times", Node("Function", Symbol("x")), Symbol("y")))
def testGetPut(self): self.check('<<"filename"', Node('Get', Filename('"filename"'))) self.check('1 >> filename', Node('Put', Number('1'), Filename('filename'))) self.check('1 >>> filename', Node('PutAppend', Number('1'), Filename('filename'))) self.check('<< filename', Node('Get', Filename('filename')))
def testMessage(self): self.check('1 :: "abc"', Node("MessageName", Number("1"), String("abc"))) self.check( '1 :: "abc" :: "123"', Node("MessageName", Number("1"), String("abc"), String("123")), )
def testGetPut(self): self.check('<<"filename"', Node("Get", Filename('"filename"'))) self.check("1 >> filename", Node("Put", Number("1"), Filename("filename"))) self.check("1 >>> filename", Node("PutAppend", Number("1"), Filename("filename"))) self.check("<< filename", Node("Get", Filename("filename")))
def e_Span(self, expr1, token, p): q = ternary_ops['Span'] if q < p: return None if expr1.get_head_name() == 'Span' and not expr1.parenthesised: return None self.consume() # Span[expr1, expr2] token = self.next() if token.tag == 'Span': expr2 = Symbol('All') elif token.tag == 'END' and self.bracket_depth == 0: # So that e.g. 'x = 1 ;;' doesn't wait for newline in the frontend expr2 = Symbol('All') return Node('Span', expr1, expr2) else: messages = list(self.feeder.messages) try: expr2 = self.parse_exp(q + 1) except TranslateError: expr2 = Symbol('All') self.backtrack(token.pos) self.feeder.messages = messages token = self.next() if token.tag == 'Span': self.consume() messages = list(self.feeder.messages) try: expr3 = self.parse_exp(q + 1) return Node('Span', expr1, expr2, expr3) except TranslateError: self.backtrack(token.pos) self.feeder.messages = messages return Node('Span', expr1, expr2)
def testSlot(self): self.check("#2", Node("Slot", Number("2"))) self.check("#", Node("Slot", Number("1"))) self.check("##2", Node("SlotSequence", Number("2"))) self.check("##", Node("SlotSequence", Number("1"))) self.check("%2", Node("Out", Number("2"))) self.check("#a", 'Slot["a"]')
def e_ApplyList(self, expr1, token, p): q = right_binary_ops['Apply'] if q < p: return None self.consume() expr2 = self.parse_exp(q) expr3 = Node('List', Number('1')) return Node('Apply', expr1, expr2, expr3)
def e_Divide(self, expr1, token, p): q = left_binary_ops['Divide'] if q < p: return None self.consume() expr2 = self.parse_exp(q + 1) return Node('Times', expr1, Node('Power', expr2, Number('-1'))).flatten()
def e_Divide(self, expr1, token, p): q = left_binary_ops["Divide"] if q < p: return None self.consume() expr2 = self.parse_exp(q + 1) return Node("Times", expr1, Node("Power", expr2, Number("1", sign=-1))).flatten()
def e_ApplyList(self, expr1, token, p): q = right_binary_ops["Apply"] if q < p: return None self.consume() expr2 = self.parse_exp(q) expr3 = Node("List", Number("1")) return Node("Apply", expr1, expr2, expr3)
def p_Information(self, token): self.consume() q = prefix_ops["Information"] child = self.parse_exp(q) if child.__class__ is not Symbol: raise InvalidSyntaxError() return Node("Information", child, Node("Rule", Symbol("LongForm"), Symbol("True")))
def p_Out(self, token): self.consume() text = token.text if text == "%": return Node("Out") if text.endswith("%"): n = str(-len(text)) else: n = text[1:] return Node("Out", Number(n))
def p_Out(self, token): self.consume() text = token.text if text == '%': return Node('Out') if text.endswith('%'): n = str(-len(text)) else: n = text[1:] return Node('Out', Number(n))
def e_Derivative(self, expr1, token, p): q = postfix_ops['Derivative'] if q < p: return None n = 0 while self.next().tag == 'Derivative': self.consume() n += 1 head = Node('Derivative', Number(str(n))) return Node(head, expr1)
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 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'), expr2).flatten() return Node('Plus', expr1, expr2).flatten()
def e_Function(self, expr1, token, p): q = postfix_ops['Function'] if q < p: return None # postfix or right-binary determined by symbol self.consume() if token.text == '&': return Node('Function', expr1) else: expr2 = self.parse_exp(q) return Node('Function', expr1, expr2)
def b_SqrtBox(self, box0, token, p): if box0 is not None: return None self.consume() q = misc_ops['SqrtBox'] box1 = self.parse_box(q) if self.next().tag == 'OtherscriptBox': self.consume() box2 = self.parse_box(q) return Node('RadicalBox', box1, box2) else: return Node('SqrtBox', box1)
def b_FormBox(self, box1, token, p): q = misc_ops["FormBox"] if q < p: return None if box1 is None: box1 = Symbol("StandardForm") # RawForm elif is_symbol_name(box1.value): box1 = Symbol(box1.value, context=None) else: box1 = Node("Removed", String("$$Failure")) self.consume() box2 = self.parse_box(q) return Node("FormBox", box2, box1)
def b_FormBox(self, box1, token, p): q = misc_ops['FormBox'] if q < p: return None if box1 is None: box1 = Symbol('StandardForm') # RawForm elif is_symbol_name(box1.value): box1 = Symbol(box1.value, context=None) else: box1 = Node('Removed', String('$$Failure')) self.consume() box2 = self.parse_box(q) return Node('FormBox', box2, box1)
def testBang(self): self.check('5!', Node('Factorial', Number('5'))) self.check('5 !', Node('Factorial', Number('5'))) self.check('5 ! !', Node('Factorial', Node('Factorial', Number('5')))) self.check('!1', Node('Not', Number('1'))) self.check('5 !!', Node('Factorial2', Number('5'))) self.check('x ! y', Node('Times', Node('Factorial', Symbol('x')), Symbol('y')))
def p_Pattern(self, token): self.consume() text = token.text if "." in text: name = text[:-2] if name: return Node( "Optional", Node("Pattern", Symbol(name, context=None), Node("Blank")), ) else: return Node("Optional", Node("Blank")) pieces = text.split("_") count = len(pieces) - 1 if count == 1: name = "Blank" elif count == 2: name = "BlankSequence" elif count == 3: name = "BlankNullSequence" if pieces[-1]: blank = Node(name, Symbol(pieces[-1], context=None)) else: blank = Node(name) if pieces[0]: return Node("Pattern", Symbol(pieces[0], context=None), blank) else: return blank
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 b_OverscriptBox(self, box1, token, p): q = misc_ops['OverscriptBox'] if q < p: return None if box1 is None: box1 = String('') self.consume() box2 = self.parse_box(q) if self.next().tag == 'OtherscriptBox': self.consume() box3 = self.parse_box(misc_ops['UnderoverscriptBox']) return Node('UnderoverscriptBox', box1, box3, box2) else: return Node('OverscriptBox', box1, box2)
def b_OverscriptBox(self, box1, token, p): q = misc_ops["OverscriptBox"] if q < p: return None if box1 is None: box1 = String("") self.consume() box2 = self.parse_box(q) if self.next().tag == "OtherscriptBox": self.consume() box3 = self.parse_box(misc_ops["UnderoverscriptBox"]) return Node("UnderoverscriptBox", box1, box3, box2) else: return Node("OverscriptBox", box1, box2)
def p_Pattern(self, token): self.consume() text = token.text if '.' in text: name = text[:-2] if name: return Node( 'Optional', Node('Pattern', Symbol(name, context=None), Node('Blank'))) else: return Node('Optional', Node('Blank')) pieces = text.split('_') count = len(pieces) - 1 if count == 1: name = 'Blank' elif count == 2: name = 'BlankSequence' elif count == 3: name = 'BlankNullSequence' if pieces[-1]: blank = Node(name, Symbol(pieces[-1], context=None)) else: blank = Node(name) if pieces[0]: return Node('Pattern', Symbol(pieces[0], context=None), blank) else: return blank