Logo Search packages:      
Sourcecode: zope-loginmanager version File versions

Compiler.py

from string import join,split,strip
import tokenize, cStringIO
from spark import GenericParser






































class Token:
    def __init__(self, type, attr=None, lineno='???'):
        self.type = type
        self.attr = attr
        self.lineno = lineno

    def __cmp__(self, o):
        return cmp(self.type, o)
    ###
    def __getitem__(self,key): raise IndexError,key
    def __repr__(self):
        return "%s(%s)" % (self.type,self.attr)
    def __len__(self): return 0
    def __str__(self):
        return str(self.attr or self.type)

_map = {
    tokenize.ENDMARKER    : 'ENDMARKER',
    tokenize.NAME         : 'NAME',
    tokenize.NUMBER        : 'NUMBER',
    tokenize.STRING        : 'STRING',
    tokenize.NEWLINE    : 'NEWLINE',
    tokenize.INDENT        : 'INDENT',
    tokenize.DEDENT        : 'DEDENT', }

_rw = {
    'and'        : None,    'assert'    : None,
    'break'        : None,    'class'        : None,
    'continue'    : None,    'def'        : None,
    'del'        : None,    'elif'        : None,
    'else'        : None,    'except'    : None,
    'exec'        : None,    'finally'    : None,
    'for'        : None,    'from'        : None,
    'global'    : None,    'if'        : None,
    'import'    : None,    'in'        : None,
    'is'        : None,    'lambda'    : None,
    'not'        : None,    'or'        : None,
    'pass'        : None,   'print'        : None,
    'raise'        : None,    'return'    : None,
    'try'        : None,    'while'        : None,
}
kw = """
    WITH COMPUTE SELF WHEN OBJECT ADDED DELETED CHANGED STORE USING CALL SAVING IN
    QUERY OTHERWISE LET INITIALIZE
    """

_kw={}
for k in split(strip(kw)): _kw[k]=None

is_kw = _kw.has_key    


def scan(f):
    tokens = []

    def callback(value, lexeme, (lineno, column), end, line, list=tokens):
        attr = None
        type = lexeme

        if value in (tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE, tokenize.INDENT, tokenize.DEDENT):
            return
        elif _map.has_key(value):
            if is_kw(lexeme):
                type = lexeme
            elif value != tokenize.NAME or not _rw.has_key(lexeme):
                attr = lexeme
                type = _map[value]

        t = Token(type, attr=attr, lineno=lineno)
        list.append(t)

    tokenize.tokenize(f.readline, callback)
    return tokens









class AST:
    def __init__(self, type):
        self.type = type
        self._kids = []

    def __getitem__(self, i):
        return self._kids[i]
        
    def __len__(self):
        return len(self._kids)
        
    def __setslice__(self, low, high, seq):
        self._kids[low:high] = seq
        
    def __cmp__(self, o):
        return cmp(self.type, o)

    def __str__(self):
        return join(map(str,self._kids),'')

    def __getslice__(self, low, high):
        return self._kids[low:high]

    def __repr__(self):
        return self.type+`self[:]`
















if __name__=='__main__':

    # Debugging versions of compiler output
    
    class Compute(AST):
        type = 'COMPUTE'
        def __init__(self,*args,**args):
            self._kids=list(args)+kw.items()

    class Trigger(Compute):
        type="TRIGGER"
        
    class PersistAttrs(AST):
        type="PERSIST"
        def __init__(self,args):
            self._kids = list(args)
    
    class Expression(AST):
        def __init__(self,expr):
            self.expr = expr

        def __repr__(self): return 'EXPR(%s)' % self.expr
        def __str__(self): return self.expr

    class Initialize(Compute): 
        type="INITIALIZE"

    class Name(Compute):
        type="NAME"


else:
    from Components import Compute, Trigger, PersistAttrs, Initialize
    from Products.ZPatterns.Expressions import Expression, Name







class SkinScriptParser(GenericParser):

    def __init__(self, start='script'):
        GenericParser.__init__(self, start)

    def typestring(self, token):
        return token.type

    def error(self, token):
        raise SyntaxError, "Syntax error at `%s' (line %s)" % (token, token.lineno)
        
    def p_script(self,args):
        """
            statement ::= compute
            statement ::= persist
            statement ::= trigger
            statement ::= saver
            statement ::= store
            statement ::= initialize

            script ::= statements ENDMARKER
            name_or_assign ::= assign
            name_or_assign ::= uncalled_name

            self_or_expr  ::= self_as_none
            self_or_expr  ::= py_expr
            opt_saving    ::= saving_clause

            memento ::= assign
            memento ::= called_name
        """
        return args[0]

    def p_py_expr(self,args):
        """
            py_expr     ::= testlist
            assign_expr ::= test
        """
        return Expression(args[0])


    def p_statements(self,args):
        """
            statements ::= statements statement
            statements ::= statement

            attrspeclist  ::= attrspeclist , attributespec
            attrspeclist  ::= attributespec

            assignmentlist ::= assignmentlist , name_or_assign
            assignmentlist ::= name_or_assign

            assignonlylist ::= assignonlylist , assign
            assignonlylist ::= assign

            mementolist ::= mementolist , memento
            mementolist ::= memento

            eventlist     ::= eventlist , event
            eventlist     ::= event
        """
        if len(args)>1:
            a = args[0]; a.append(args[-1]); return a
        else:
            return [args[0]]
            
    def p_trigger(self,args):
        """
            trigger ::= when_clause CALL py_expr opt_saving
        """
        t = Trigger(args[0],[],        args[2],args[3])
        t.lineno = args[1].lineno
        return t

    def p_saver(self,args):
        """
            saver   ::= when_clause STORE attrspeclist USING py_expr opt_saving
        """
        t = Trigger(args[0],args[2],args[4],args[5], onlySave=1)
        t.lineno = args[1].lineno
        return t

    def p_compute(self,args):
        """
            compute ::= WITH self_or_expr COMPUTE assignmentlist optional_defaultattrs
        """
        c = Compute(args[1],args[3],defaults=args[4])
        c.lineno = args[0].lineno; return c
        
    def p_compute_query(self,args):
        """
            compute ::= WITH QUERY py_expr COMPUTE assignmentlist optional_defaultattrs
        """
        c = Compute(args[2],args[4],is_query=1,defaults=args[5])
        c.lineno = args[0].lineno; return c

    def p_initialize(self,args):
        """
            initialize ::= INITIALIZE OBJECT WITH assignonlylist
        """
        c = Initialize(args[-1]); c.lineno = args[0].lineno; return c
        
    def p_persist(self,args):
        """
            persist ::= STORE attrspeclist IN SELF
        """
        p = PersistAttrs(args[1])
        p.lineno = args[0].lineno
        return p
        
    def p_store(self,args):
        """
            store   ::= STORE attrspeclist USING py_expr opt_saving
        """
        t = Trigger(
            ('ADD','DELETE','CHANGE'), args[1],args[3],args[4], onlySave=1
        )
        t.lineno = args[0].lineno
        return t




    def p_optional_defaultattrs(self,args):
        """
            optional_defaultattrs ::= OTHERWISE LET assignonlylist
            optional_defaultattrs ::= 
        """
        if len(args): return args[2]
        return ()

    def p_event(self,args):
        """
            event         ::= ADDED
            event         ::= DELETED
            event         ::= CHANGED
            
            attributespec ::= NAME
            attributespec ::= *
        """
        return str(args[0])

    def p_called_name(self,args):
        """
            called_name  ::= NAME
        """
        name = str(args[0])
        return (name,Name(name,1))


    def p_uncalled_name(self,args):
        """
            uncalled_name  ::= NAME
        """
        name = str(args[0])
        return (name,Name(name,0))


    def p_assign(self,args):
        """
            assign ::=   NAME = assign_expr
        """
        return (str(args[0]),args[2])

    def p_self_as_none(self,args):
        """
            self_as_none  ::= SELF
        """
        return None

    def p_opt_saving(self,args):
        """
            opt_saving    ::=
        """
        return []

    def p_when_clause(self,args):
        """
            when_clause   ::= WHEN OBJECT eventlist
        """
        m = {'ADDED':'ADD','CHANGED':'CHANGE','DELETED':'DELETE'}.get
        return tuple(map(m,args[2]))


    def p_saving_clause(self,args):
        """
            saving_clause ::= SAVING mementolist
        """
        return args[1]
















    def p_testlist(self, args):
        '''
            varargslist ::= extraargs
            varargslist ::= primaryargs , extraargs
            varargslist ::= primaryargs opt_comma

            primaryargs ::= primaryargs , fpdef = test
            primaryargs ::= primaryargs , fpdef
            primaryargs ::= fpdef = test
            primaryargs ::= fpdef

            extraargs ::= * NAME
            extraargs ::= * NAME , ** NAME
            extraargs ::= * NAME , * * NAME
            extraargs ::= ** NAME
            extraargs ::= * * NAME

            fpdef ::= NAME
            fpdef ::= ( fplist )

            fplist ::= bare_fplist opt_comma

            bare_fplist ::= bare_fplist , fpdef
            bare_fplist ::= fpdef

            test ::= lambdef
            test ::= or_test


            or_test ::= or_test or and_test
            or_test ::= and_test

            and_test ::= and_test and not_test
            and_test ::= not_test

            not_test ::= not not_test
            not_test ::= comparison

            comparison ::= comparison comp_op expr
            comparison ::= expr

            comp_op ::= <
            comp_op ::= >
            comp_op ::= ==
            comp_op ::= >=
            comp_op ::= <=
            comp_op ::= <>
            comp_op ::= !=
            comp_op ::= in
            comp_op ::= not in
            comp_op ::= is
            comp_op ::= is not

            expr ::= expr | xor_expr
            expr ::= xor_expr

            xor_expr ::= xor_expr ^ and_expr
            xor_expr ::= and_expr

            and_expr ::= and_expr & shift_expr
            and_expr ::= shift_expr

            shift_expr ::= shift_expr << arith_expr
            shift_expr ::= shift_expr >> arith_expr
            shift_expr ::= arith_expr

            arith_expr ::= arith_expr + term
            arith_expr ::= arith_expr - term
            arith_expr ::= term

            term ::= term * factor
            term ::= term / factor
            term ::= term % factor
            term ::= factor

            factor ::= + factor
            factor ::= - factor
            factor ::= ~ factor
            factor ::= power



            power ::= atom trailer_list power_list
            power ::= atom trailer_list
            power ::= atom power_list
            power ::= atom

            trailer_list ::= trailer_list trailer
            trailer_list ::= trailer

            power_list ::= power_list ** factor
            power_list ::= ** factor

            atom ::= ( testlist )
            atom ::= ( )
            atom ::= [ testlist ]
            atom ::= [ ]
            atom ::= { dictmaker }
            atom ::= { }
            atom ::= ` testlist `
            atom ::= NAME
            atom ::= NUMBER
            atom ::= string_list

            string_list ::= string_list STRING
            string_list ::= STRING

            lambdef ::= lambda varargslist : test
            lambdef ::= lambda : test

            trailer ::= ( arglist )
            trailer ::= ( )
            trailer ::= [ subscriptlist ]
            trailer ::= . NAME

            subscriptlist ::= bare_subscriptlist opt_comma

            bare_subscriptlist ::= bare_subscriptlist , subscript
            bare_subscriptlist ::= subscript




            subscript ::= . . .
            subscript ::= test
            subscript ::= opt_test : opt_test
            subscript ::= opt_test : opt_test : opt_test

            testlist ::= bare_testlist opt_comma

            bare_testlist ::= bare_testlist , test
            bare_testlist ::= test

            dictmaker ::= bare_dictmaker opt_comma

            bare_dictmaker ::= bare_dictmaker , test : test
            bare_dictmaker ::= test : test

            arglist ::= bare_arglist opt_comma

            bare_arglist ::= bare_arglist , argument
            bare_arglist ::= argument

            argument ::= test = test
            argument ::= test

            opt_test ::= test
            opt_test ::=
            opt_comma ::= ,
            opt_comma ::=
        '''
        return join(map(str,args),' ')






        


        


def parse(tokens,start='script'):
    parser = SkinScriptParser(start=start)
    return tuple(parser.parse(tokens))

def scans(s):      return scan(cStringIO.StringIO(s))    
def compile(s):    return parse(scans(s))



if __name__=='__main__':

    t=scans(
        """
        WITH 1+2 COMPUTE foo,bar=baz
        STORE foo,bar,wazoo IN SELF
        STORE spam USING foobly+1 SAVING wahoo=(99),shiz,fez=bez
        WITH SELF COMPUTE blah=shazam
        WHEN OBJECT DELETED CALL pasta() SAVING pizza,fruit=(nuts),pizza
        WHEN OBJECT ADDED,CHANGED STORE dessert USING freezer
        WITH gazoo*3 COMPUTE spam
        """
    )
    
    p=parse(t)
    print
    for j in p: print `j`

Generated by  Doxygen 1.6.0   Back to index