예제 #1
0
 def test_node_combine(self):
     node = ntype("int")
     self.assertTrue(isinstance(ntype("int"), Node))
     list(
         map(
             self.assertTrue,
             [
                 isinstance(nvalue("smth"), Node),
                 isinstance(node + node, Node),
                 isinstance(node | node, Node),
                 isinstance(many(node), Node),
                 isinstance(oneplus(node), Node),
                 isinstance(future(), Node),
                 isinstance(node.join(node), Node),
                 isinstance(maby(node), Node),
                 isinstance(exact("smth"), Node),
                 isinstance(finish(), Node),
                 isinstance(skip(node), Node),
             ],
         )
     )
예제 #2
0
    def parse(self, tokens):
        
        #=======================================================================
        # helpers
        #=======================================================================
        
        def create_end(node, ignore=True):
            def _foo(token):
                val = getattr(token, "value", token)
                node.define_with_revert(long_op + skip(exact("/" + val)) + long_cl)
                return Ignore() if ignore else token
            return _foo
        
        def revert(node, ignore=True):          
            def _foo(token):
                node.revert()
                return Ignore() if ignore else token            
            return _foo
        
        text = ntype(EXTERNAL) >> (lambda t: TextChunk(t.value))
        
        #=======================================================================
        # reserved words
        #=======================================================================
        rfor = exact("for")
        rif = exact("if")
        relse = skip(exact("else"))
        rin = skip(exact("in"))
        rblock = (exact("block"))
        rextend = skip(exact("extend"))
        rmethod = skip(exact("method"))
        rstrict = exact("strict") >> (lambda t: t.value)
        rimplicit = exact("implicit") >> (lambda t: t.value)
        
        #=======================================================================
        # small items
        #=======================================================================
        word = ntype("word") >> (lambda t: ContextVar(t.value))
        integer = ntype("integer") >> (lambda t: int(t.value))
        binopt = ntype("binary") >> (lambda t: select_opt(t.value))
        string = ntype("string") >> (lambda t: String(t.value[1:-1]))
        number = integer
        twospot = skip(exact(":"))
      
        #=======================================================================
        # границы блоков
        #=======================================================================
        
        short_op = skip(exact(SHORT_OPEN))
        short_cl = skip(exact(SHORT_CLOSE))
        
        long_op = skip(exact(LONG_OPEN))
        long_cl = skip(exact(LONG_CLOSE))
        
        stuff = future()
        
        #=======================================================================
        # chain chunk
        #=======================================================================
        
        short_meat = future()        
        short_block = short_op + short_meat + short_cl
        
        #=======================================================================
        # function
        #=======================================================================
        function = future()
        function.define((word + 
            skip(exact("(")) + 
            maby((number | string | word | function).join(skip(exact(",")))) + 
            skip(exact(")"))) >> self.__function)      
                       
        #=======================================================================
        # chain chunk  
        #=======================================================================
        arrow = skip(exact(">"))
        short_meat.define((word + many(arrow + function)) >> self.__chain)
                
        #=======================================================================
        # if chunk
        #=======================================================================
        endif = future()
        ifchunk = (long_op + (rif >> create_end(endif)) + 
            (((number | word) + maby(binopt + (number | word))) >> self.__if_head) + 
            long_cl + 
            ((stuff + maby(long_op + relse + long_cl + stuff)) >> self.__if_body) + 
            endif) >> self.__if

        #=======================================================================
        # for chunk
        #=======================================================================
        endfor = future()
        forchunk = (long_op + (rfor >> create_end(endfor)) + 
            ((word.join(skip(exact(","))) + rin + (function | word)) >> self.__for_head) + 
            long_cl + 
            (stuff >> list) + 
            endfor) >> self.__for
        
        #=======================================================================
        # block chunk
        #=======================================================================
        endblock = future()
        block_chunk = (long_op + 
            (rblock >> create_end(endblock)) + twospot + word + long_cl + 
            (stuff >> list) + endblock) >> self.__block
              
        #=======================================================================
        # mod chunk
        #=======================================================================
        endmod = future()
        mod_chunk = (long_op + 
            (word >> create_end(endmod, ignore=False)) + 
            ((exact("+") >> (lambda _: True)) | (exact("-") >> (lambda _: False))) + 
            long_cl + (stuff >> list) + (endmod >> revert(endmod))) >> self.__mod
                 
        #=======================================================================
        # comment
        #=======================================================================
        comment = skip(long_op + exact("#") + string + long_cl)
        
        #=======================================================================
        # extend chunk
        #=======================================================================
        extend = (long_op + skip(exact("#")) + rextend + twospot + word + 
            maby(rmethod + twospot + (rstrict | rimplicit)) + long_cl) >> self.__extend
        
        #=======================================================================
        # разный стафф
        #=======================================================================
        stuff.define(many(
            text | short_block | ifchunk | 
            forchunk | block_chunk | mod_chunk | 
            comment | extend))           
        
        return [x for x in (stuff + finish()).parse(tokens)[0] if not isinstance(x, Ignore)]
예제 #3
0
 def _foo(token):
     val = getattr(token, "value", token)
     node.define_with_revert(long_op + skip(exact("/" + val)) + long_cl)
     return Ignore() if ignore else token
예제 #4
0
 def parse(tokens):
     integer = ntype("int") >> (lambda t: int(t.value))
     three = exact("3") >> (lambda t: int(t.value))
     comma = skip(ntype(","))
     parser = integer + comma + three
     return parser.parse(tokens)[0]