def testParagraph(self):
     tokens = [x for x in TeX().input('1\n   2\n   \n   3\n').itertokens()]
     expected = [
         Other('1'),
         Space(' '),
         Other('2'),
         Space(' '),
         EscapeSequence('par'),
         Other('3'),
         Space(' ')
     ]
     self.assertEqual(tokens, expected)
 def testComment(self):
     tokens = [x for x in TeX().input('line % comment').itertokens()]
     expected = [
         Letter('l'),
         Letter('i'),
         Letter('n'),
         Letter('e'),
         Space(' ')
     ]
     self.assertEqual(tokens, expected)
    def testExercises(self):
        """ Exercises in the TeX book """
        # 8.4
        tokens = [x for x in TeX().input(r' $x^2$~  \TeX  ^^C').itertokens()]
        expected = [
            MathShift('$'),
            Letter('x'),
            Superscript('^'),
            Other('2'),
            MathShift('$'),
            EscapeSequence('active::~'),
            Space(' '),
            EscapeSequence('TeX'),
            Other('\x03')
        ]
        self.assertEqual(tokens, expected)

        # 8.5
        tokens = [x for x in TeX().input('Hi!\n\n\n').itertokens()]
        expected = [
            Letter('H'),
            Letter('i'),
            Other('!'),
            Space(' '),
            EscapeSequence('par')
        ]
        self.assertEqual(tokens, expected)

        # 8.6
        tokens = [
            x for x in TeX().input(r'^^B^^BM^^A^^B^^C^^M^^@\M ').itertokens()
        ]
        expected = [
            Other('\x02'),
            Other('\x02'),
            Letter('M'),
            Other('\x01'),
            Other('\x02'),
            Other('\x03'),
            Space(' '),
            EscapeSequence('M')
        ]
        self.assertEqual(tokens, expected)
 def testTokens(self):
     tokens = [x for x in TeX().input(r'{\hskip 36 pt}').itertokens()]
     expected = [
         BeginGroup('{'),
         EscapeSequence('hskip'),
         Other('3'),
         Other('6'),
         Space(' '),
         Letter('p'),
         Letter('t'),
         EndGroup('}')
     ]
     self.assertEqual(tokens, expected)
 def testDoubleSuper(self):
     tokens = [x for x in TeX().input('^^I ^^A ^^@ ^^M').itertokens()]
     expected = [Other('\x01'), Space(' ')]
     self.assertEqual(tokens, expected)
    def testSymbols(self):
        tokens = [x for x in TeX().input('\\ { } $ & # ^ _ ~ %').itertokens()]
        expected = [
            EscapeSequence(' '),
            BeginGroup('{'),
            Space(' '),
            EndGroup('}'),
            Space(' '),
            MathShift('$'),
            Space(' '),
            Alignment('&'),
            Space(' '),
            Parameter('#'),
            Space(' '),
            Superscript('^'),
            Space(' '),
            Subscript('_'),
            Space(' '),
            EscapeSequence('active::~'),
            Space(' ')
        ]
        self.assertEqual(tokens, expected)

        tokens = [
            x for x in TeX().input(
                r'\\ \{ \} \$ \& \# \^ \_ \~ \%').itertokens()
        ]
        expected = [
            EscapeSequence('\\'),
            Space(' '),
            EscapeSequence('{'),
            Space(' '),
            EscapeSequence('}'),
            Space(' '),
            EscapeSequence('$'),
            Space(' '),
            EscapeSequence('&'),
            Space(' '),
            EscapeSequence('#'),
            Space(' '),
            EscapeSequence('^'),
            Space(' '),
            EscapeSequence('_'),
            Space(' '),
            EscapeSequence('~'),
            Space(' '),
            EscapeSequence('%')
        ]
        self.assertEqual(tokens, expected)
Beispiel #7
0
    def evaluate(self, tex, test: Union[List[Token], TeXFragment]) -> _boolToken:
        """Reorganise a test expression into postfix and evaluate it."""
        stack: List[Union[Token, number]] = []
        postfix: List[Union[Token, number]] = []
        test_iter = iter(test)
        for tok in test_iter:
            # Handle literal integers with tex.readNumber
            number_tokens: List[Token] = []
            while tok.catcode == Token.CC_OTHER and (tok not in ['<', '>', '=']):
                number_tokens.append(tok)
                tok = next(test_iter, Space())
            if len(number_tokens) > 0:
                value: int = tex.readInternalType(number_tokens, tex.readNumber)
                postfix.append(number(value))

            # Handle parentheses and booleans
            if tok.catcode == Token.CC_SPACE or tok is None:
                pass
            elif isinstance(tok, _boolToken):
                postfix.append(tok)
            elif tok.nodeName == '(':
                stack.append(tok)
            elif tok.nodeName == ')':
                while len(stack) > 0:
                    if not isinstance(stack[-1], number) and stack[-1].nodeName == '(':
                        break
                    postfix.append(stack.pop())
                stack.pop()  # (
            else:
                # Handle operators and precedence
                while len(stack) > 0 and self.prec(tok) <= self.prec(stack[-1]):
                    postfix.append(stack.pop())
                stack.append(tok)
        while len(stack) > 0:
            postfix.append(stack.pop())

        # Now evaluate the expression in postfix form
        while len(postfix) > 0:
            tok = postfix.pop(0)
            if isinstance(tok, _boolToken):
                stack.append(tok)
            elif isinstance(tok, number):
                stack.append(tok)
            elif isinstance(tok, _and) or isinstance(tok, AND):
                op1 = stack.pop()
                op2 = stack.pop()
                if isinstance(op1, _boolToken) and isinstance(op2, _boolToken):
                    stack.append(_true() if op1.state and op2.state else _false())
                else:
                    raise ValueError('Missing expected boolean value')
            elif isinstance(tok, _or) or isinstance(tok, OR):
                op1 = stack.pop()
                op2 = stack.pop()
                if isinstance(op1, _boolToken) and isinstance(op2, _boolToken):
                    stack.append(_true() if op1.state or op2.state else _false())
                else:
                    raise ValueError('Missing expected boolean value')
            elif isinstance(tok, _not) or isinstance(tok, NOT):
                op1 = stack.pop()
                if isinstance(op1, _boolToken):
                    stack.append(_false() if op1.state else _true())
                else:
                    raise ValueError('Missing expected boolean value')
            elif tok == '>':
                op2 = stack.pop()
                op1 = stack.pop()
                if isinstance(op1, number) and isinstance(op2, number):
                    stack.append(_true() if op1 > op2 else _false())
                else:
                    raise ValueError('Missing expected number')
            elif tok == '<':
                op2 = stack.pop()
                op1 = stack.pop()
                if isinstance(op1, number) and isinstance(op2, number):
                    stack.append(_true() if op1 < op2 else _false())
                else:
                    raise ValueError('Missing expected number')
            elif tok == '=':
                op2 = stack.pop()
                op1 = stack.pop()
                if isinstance(op1, number) and isinstance(op2, number):
                    stack.append(_true() if op1 == op2 else _false())
                else:
                    raise ValueError('Missing expected number')

        if len(stack) > 0 and isinstance(stack[-1], _boolToken):
            return stack[-1]
        else:
            return _false()