Example #1
0
    def _define_parser(self, locale, grammar):
        """
        Build a parser for ``grammar`` and return it.

        :param locale: The locale of the ``grammar``.
        :type locale: basestring
        :param grammar: The grammar for the parser to be built.
        :type grammar: Grammar
        :return: The convertible parser built from ``grammar``.
        :rtype: ConvertibleParser

        Here the ``locale`` is not used.

        """
        parser = ConvertibleParser(grammar)
        return parser
Example #2
0
 def __init__(self, *args, **kwargs):
     super(BaseGrammarTest, self).__init__(*args, **kwargs)
     # Let's use the convertible parser to ease testing:
     self.parser = ConvertibleParser(self.grammar)
Example #3
0
class BaseGrammarTest(object):
    """
    Base test case for a grammar and the expressions its parser could handle.
    
    Subclasses must define all the following attributes for the test case to
    work.
    
    .. attribute:: grammar
        
        An instance of the grammar to be tested. **This attribute must be set
        in the subclasses**, like this::
        
            from booleano.parser import Grammar
            
            class TestMyGrammar(BaseGrammarTest):
            
                grammar = Grammar(ne="<>")
    
        :type: :class:`booleano.parser.Grammar`
    
    .. attribute:: expressions
    
        A dictionary with all the valid expressions recognized by the grammar,
        where each key is the expression itself and its item is the mock
        representation of the operation.
        
        :type: dict
    
    .. attribute:: badformed_expressions
    
        A list of expressions that are bad-formed in the :attr:`grammar`.
        
        :type: list
    
    .. attribute:: single_operands
    
        A dictionary where the key is an expression that contains a single
        operand (i.e., no operator) and the item is the :term:`root node` of the
        expected :term:`parse tree`.
        
        :type: dict
    
    .. attribute:: invalid_operands
    
        A list of expressions which contain a single operand and it is invalid.
        
        :type: list
    
    """
    
    def __init__(self, *args, **kwargs):
        super(BaseGrammarTest, self).__init__(*args, **kwargs)
        # Let's use the convertible parser to ease testing:
        self.parser = ConvertibleParser(self.grammar)
    
    def test_expressions(self):
        """Valid expressions should yield the expected parse tree."""
        for expression, expected_node in self.expressions.items():
            
            # Making a Nose test generator:
            def check():
                tree = self.parser(expression)
                expected_node.check_equivalence(tree.root_node)
            check.description = 'Operation "%s" should yield "%s"' % \
                                (expression, expected_node)
            
            yield check
    
    def test_badformed_expressions(self):
        """Expressions with an invalid syntax must not yield a parse tree."""
        for expression in self.badformed_expressions:
            
            # Making a Nose test generator:
            @raises(ParseException)
            def check():
                self.parser(expression)
            check.description = "'%s' is an invalid expression" % expression
            
            yield check
    
    def test_single_operands(self):
        """
        Expressions made up of a single operand must yield the expected operand.
        
        """
        operand_parser = self.parser.define_operand().parseString
        
        for expression, expected_operand in self.single_operands.items():
            
            # Making a Nose test generator:
            def check():
                node = operand_parser(expression, parseAll=True)
                eq_(1, len(node))
                expected_operand.check_equivalence(node[0])
            check.description = ('Single operand "%s" should return %s' %
                                 (expression, expected_operand))
            
            yield check
    
    def test_invalid_operands(self):
        """
        Expressions representing invalid operands must not yield a parse tree.
        
        """
        operand_parser = self.parser.define_operand().parseString
        for expression in self.invalid_operands:
            
            # Making a Nose test generator:
            @raises(ParseException)
            def check():
                operand_parser(expression, parseAll=True)
            check.description = ('"%s" is an invalid operand' %
                                 expression)
            
            yield check
Example #4
0
 def __init__(self, *args, **kwargs):
     super(BaseGrammarTest, self).__init__(*args, **kwargs)
     # Let's use the convertible parser to ease testing:
     self.parser = ConvertibleParser(self.grammar)
Example #5
0
class BaseGrammarTest(object):
    """
    Base test case for a grammar and the expressions its parser could handle.
    
    Subclasses must define all the following attributes for the test case to
    work.
    
    .. attribute:: grammar
        
        An instance of the grammar to be tested. **This attribute must be set
        in the subclasses**, like this::
        
            from booleano.parser import Grammar
            
            class TestMyGrammar(BaseGrammarTest):
            
                grammar = Grammar(ne="<>")
    
        :type: :class:`booleano.parser.Grammar`
    
    .. attribute:: expressions
    
        A dictionary with all the valid expressions recognized by the grammar,
        where each key is the expression itself and its item is the mock
        representation of the operation.
        
        :type: dict
    
    .. attribute:: badformed_expressions
    
        A list of expressions that are bad-formed in the :attr:`grammar`.
        
        :type: list
    
    .. attribute:: single_operands
    
        A dictionary where the key is an expression that contains a single
        operand (i.e., no operator) and the item is the :term:`root node` of the
        expected :term:`parse tree`.
        
        :type: dict
    
    .. attribute:: invalid_operands
    
        A list of expressions which contain a single operand and it is invalid.
        
        :type: list
    
    """
    def __init__(self, *args, **kwargs):
        super(BaseGrammarTest, self).__init__(*args, **kwargs)
        # Let's use the convertible parser to ease testing:
        self.parser = ConvertibleParser(self.grammar)

    def test_expressions(self):
        """Valid expressions should yield the expected parse tree."""
        for expression, expected_node in self.expressions.items():

            # Making a Nose test generator:
            def check():
                tree = self.parser(expression)
                expected_node.check_equivalence(tree.root_node)
            check.description = 'Operation "%s" should yield "%s"' % \
                                (expression, expected_node)

            yield check

    def test_badformed_expressions(self):
        """Expressions with an invalid syntax must not yield a parse tree."""
        for expression in self.badformed_expressions:

            # Making a Nose test generator:
            @raises(ParseException)
            def check():
                self.parser(expression)

            check.description = "'%s' is an invalid expression" % expression

            yield check

    def test_single_operands(self):
        """
        Expressions made up of a single operand must yield the expected operand.
        
        """
        operand_parser = self.parser.define_operand().parseString

        for expression, expected_operand in self.single_operands.items():

            # Making a Nose test generator:
            def check():
                node = operand_parser(expression, parseAll=True)
                eq_(1, len(node))
                expected_operand.check_equivalence(node[0])

            check.description = ('Single operand "%s" should return %s' %
                                 (expression, expected_operand))

            yield check

    def test_invalid_operands(self):
        """
        Expressions representing invalid operands must not yield a parse tree.
        
        """
        operand_parser = self.parser.define_operand().parseString
        for expression in self.invalid_operands:

            # Making a Nose test generator:
            @raises(ParseException)
            def check():
                operand_parser(expression, parseAll=True)

            check.description = ('"%s" is an invalid operand' % expression)

            yield check
Example #6
0
    def test_custom_tokens_against_trees(self):
        """
        All the custom tokens in the grammar must be taken into account by the
        parser.

        To test that custom tokens are used, and in order to test many scenarios
        writen few lines of code, we're going to convert operation nodes into
        boolean expressions (using the relevant grammar), and then these
        expressions will be parsed to check if the result is the original
        tree.

        """

        grammars = (
            # A grammar that overrides all the default tokens:
            Grammar(
                **{
                    'not': "not",
                    'and': "and",
                    'xor': "xor",
                    'or': "or",
                    'eq': "equals",
                    'ne': "different-from",
                    'lt': "less-than",
                    'le': "less-equal",
                    'gt': "greater-than",
                    'ge': "greater-equal",
                    'belongs_to': "belongs-to",
                    'is_subset': "is-subset-of",
                    'set_start': "\\",
                    'set_end': "/",
                    'element_separator': ";",
                    'arguments_start': "[",
                    'arguments_end': "]",
                    'arguments_separator': ";",
                    'namespace_separator': ".",
                }),
            # Now let's try a grammar where some operators represent the
            # initial characters of other operators:
            Grammar(
                **{
                    'eq': "is",
                    'ne': "isn't",
                    'lt': "is less than",
                    'gt': "is greater than",
                    'le': "is less than or equal to",
                    'ge': "is greater than or equal to",
                    'belongs_to': "is included in",
                    'is_subset': "is subset of",
                }))

        for grammar_num in range(len(grammars)):
            grammar = grammars[grammar_num]
            parser = ConvertibleParser(grammar)
            convert_to_string = StringConverter(grammar)

            for operation in self.expressions.values():
                expression = convert_to_string(operation)

                # Using a Nose test generator:
                def check():
                    new_operation = parser(expression).root_node
                    eq_(
                        operation, new_operation,
                        u'Original operation: %s --- Returned operation: %s' %
                        (repr(operation), repr(new_operation)))

                check.description = (u"The following expression is valid in "
                                     u"the grammar #%r: %r" %
                                     (grammar_num, expression))

                yield check