示例#1
0
 def parse_seq(self):
     result = []
     while True:
         token = self.next_noend()
         tag = token.tag
         if tag == "RawComma":
             self.tokeniser.feeder.message("Syntax", "com")
             result.append(Symbol("Null"))
             self.consume()
         elif tag in ("RawRightAssociation", "RawRightBrace",
                      "RawRightBracket"):
             if result:
                 self.tokeniser.feeder.message("Syntax", "com")
                 result.append(Symbol("Null"))
             break
         else:
             result.append(self.parse_exp(0))
             token = self.next_noend()
             tag = token.tag
             if tag == "RawComma":
                 self.consume()
                 continue
             elif tag in ("RawRightAssociation", "RawRightBrace",
                          "RawRightBracket"):
                 break
     return result
示例#2
0
 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
示例#3
0
文件: parser.py 项目: srossd/Mathics
 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"))
     )
示例#4
0
 def parse_seq(self):
     result = []
     while True:
         token = self.next_noend()
         tag = token.tag
         if tag == 'RawComma':
             self.tokeniser.feeder.message('Syntax', 'com')
             result.append(Symbol('Null'))
             self.consume()
         elif tag in ('RawRightAssociation', 'RawRightBrace',
                      'RawRightBracket'):
             if result:
                 self.tokeniser.feeder.message('Syntax', 'com')
                 result.append(Symbol('Null'))
             break
         else:
             result.append(self.parse_exp(0))
             token = self.next_noend()
             tag = token.tag
             if tag == 'RawComma':
                 self.consume()
                 continue
             elif tag in ('RawRightAssociation', 'RawRightBrace',
                          'RawRightBracket'):
                 break
     return result
示例#5
0
 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
示例#6
0
 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')))
示例#7
0
    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)
示例#8
0
 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")))
示例#9
0
 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')))
示例#10
0
 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
示例#11
0
 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")))
示例#12
0
 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]]')
示例#13
0
 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")))
示例#14
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')))
示例#15
0
    def testExpression(self):
        self.check('expr1[expr2]', Node('expr1', Symbol('expr2')))
        self.check('expr1[expr2][expr3]', Node(Node('expr1', Symbol('expr2')), Symbol('expr3')))
        self.check('expr1[[expr2]]', Node('Part', Symbol('expr1'), Symbol('expr2')))
        self.check('expr1[[expr2, expr3]]', Node('Part', Symbol('expr1'), Symbol('expr2'), Symbol('expr3')))
        self.check('expr1[[expr2]][[expr3]]', Node('Part', Node('Part', Symbol('expr1'), Symbol('expr2')), Symbol('expr3')))

        self.check('expr1 ~ expr2 ~ expr3', Node('expr2', Symbol('expr1'), Symbol('expr3')))
        self.check('x~f~y', 'f[x, y]')
示例#16
0
    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")
示例#17
0
 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]")
示例#18
0
 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)
示例#19
0
 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)
示例#20
0
 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]]")
示例#21
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")),
        )
示例#22
0
    def testBlank(self):
        self.check('f_', Node('Pattern', Symbol('f'), Node('Blank')))
        self.check('f__', Node('Pattern', Symbol('f'), Node('BlankSequence')))
        self.check('f___', Node('Pattern', Symbol('f'), Node('BlankNullSequence')))

        self.check('_', 'Blank[]')
        self.check('_expr', 'Blank[expr]')
        self.check('__', 'BlankSequence[]')
        self.check('__expr', 'BlankSequence[expr]')
        self.check('___', 'BlankNullSequence[]')
        self.check('___expr', 'BlankNullSequence[expr]')

        self.check('_.', 'Optional[Blank[]]')
        self.check('symb_', 'Pattern[symb, Blank[]]')
        self.check('symb_expr', 'Pattern[symb, Blank[expr]]')
        self.check('symb__', 'Pattern[symb, BlankSequence[]]')
        self.check('symb__expr', 'Pattern[symb, BlankSequence[expr]]')
        self.check('symb___', 'Pattern[symb, BlankNullSequence[]]')
        self.check('symb___expr', 'Pattern[symb, BlankNullSequence[expr]]')
        self.check('symb_.', 'Optional[Pattern[symb, Blank[]]]')
示例#23
0
    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')
示例#24
0
    def testBlank(self):
        self.check("f_", Node("Pattern", Symbol("f"), Node("Blank")))
        self.check("f__", Node("Pattern", Symbol("f"), Node("BlankSequence")))
        self.check("f___",
                   Node("Pattern", Symbol("f"), Node("BlankNullSequence")))

        self.check("_", "Blank[]")
        self.check("_expr", "Blank[expr]")
        self.check("__", "BlankSequence[]")
        self.check("__expr", "BlankSequence[expr]")
        self.check("___", "BlankNullSequence[]")
        self.check("___expr", "BlankNullSequence[expr]")

        self.check("_.", "Optional[Blank[]]")
        self.check("symb_", "Pattern[symb, Blank[]]")
        self.check("symb_expr", "Pattern[symb, Blank[expr]]")
        self.check("symb__", "Pattern[symb, BlankSequence[]]")
        self.check("symb__expr", "Pattern[symb, BlankSequence[expr]]")
        self.check("symb___", "Pattern[symb, BlankNullSequence[]]")
        self.check("symb___expr", "Pattern[symb, BlankNullSequence[expr]]")
        self.check("symb_.", "Optional[Pattern[symb, Blank[]]]")
示例#25
0
 def testOptional(self):
     self.check('x:expr', Node('Pattern', Symbol('x'), Symbol('expr')))
     self.check(
         'x_:expr',
         Node('Optional', Node('Pattern', Symbol('x'), Node('Blank')),
              Symbol('expr')))
     self.check(
         'f:a|b',
         Node('Pattern', Symbol('f'),
              Node('Alternatives', Symbol('a'), Symbol('b'))))
     self.check('rev:(True|False):False',
                'Optional[Pattern[rev, Alternatives[True, False]], False]')
示例#26
0
 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]')
示例#27
0
    def e_Semicolon(self, expr1, token, p):
        q = flat_binary_ops['CompoundExpression']
        if q < p:
            return None
        self.consume()

        # XXX this has to come before call to self.next()
        pos = self.tokeniser.pos
        messages = list(self.feeder.messages)

        # So that e.g. 'x = 1;' doesn't wait for newline in the frontend
        tag = self.next().tag
        if tag == 'END' and self.bracket_depth == 0:
            expr2 = Symbol('Null')
            return Node('CompoundExpression', expr1, expr2).flatten()

        # XXX look for next expr otherwise backtrack
        try:
            expr2 = self.parse_exp(q + 1)
        except TranslateError:
            self.backtrack(pos)
            self.feeder.messages = messages
            expr2 = Symbol('Null')
        return Node('CompoundExpression', expr1, expr2).flatten()
示例#28
0
 def testOptional(self):
     self.check("x:expr", Node("Pattern", Symbol("x"), Symbol("expr")))
     self.check(
         "x_:expr",
         Node("Optional", Node("Pattern", Symbol("x"), Node("Blank")),
              Symbol("expr")),
     )
     self.check(
         "f:a|b",
         Node("Pattern", Symbol("f"),
              Node("Alternatives", Symbol("a"), Symbol("b"))),
     )
     self.check(
         "rev:(True|False):False",
         "Optional[Pattern[rev, Alternatives[True, False]], False]",
     )
示例#29
0
 def testSymbol(self):
     self.check("xX", Symbol("xX"))
     self.check("context`name", Symbol("context`name"))
     self.check("`name", Symbol("`name"))
     self.check("`context`name", Symbol("`context`name"))
示例#30
0
    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]")