pykid / pykid / parser.py

'''
Created on Mar 3, 2012

@author: xmonader
'''
from ply import yacc
from lexer import *
#program : blocks
#blocks: block*
#block: statements
#statements: statement*
#statement: expr | funccall | funcdef
#funccall: ID(argslist)(.funcall(argslist)*)
#argslist
#expr: term + expr
#    |  term - expr
#term: factor * term
#    | factor / term
#factor: NUMBER
#      | ID


    
precedence = (
    ('left','PLUS','MINUS'),
    ('left','TIMES','DIVIDE'),
    ('right','UMINUS'),
)

def p_block(p):
    """block : stmtlist
             | innerblock
    """
    print p[1]
    p[0]=None
    
def p_innerblock(p):
    """innerblock : LBRACE stmtlist RBRACE
                 | LBRACE RBRACE
    """
    p[0]=('INNERBLOCK', p[2])
    
def p_stmtlist(p):
    """stmtlist : stmtlist SEMICOLON stmt
                | stmt
    """
    #print type(p)
    stmtlist=[]
    if len(p)==2:
        stmtlist.append(p[1])
    else:
        for el in [p[1], p[3]]:
            if isinstance(el, list):
                stmtlist.extend(el)
            else:
                stmtlist.append(el)
        
    #for s in stmtlist: 
    #    print s, type(s)
    
    stmts = [ x for x in stmtlist] #if x is not None]
    print "stmtslist", stmts
    #print "codeblock"
    p[0]=stmts
    

def p_stmt_funccall(p):
    """
        stmt : ID LPAREN argslist RPAREN
    """
    funcname=p[1]
    argslist=p[3]
    print "calling func: ", funcname
    print "with args: ", argslist
    p[0]=('FUNCCALL', funcname, argslist)
    

def p_argslist(p):
    """
        argslist : argslist COMMA expr
                | expr
                |
    """ 
    args=[]
    if len(p)==1:
        p[0]=args
        return

    if len(p)==2:
        args.append(p[1])
    else:
        for el in [p[1], p[3]]:
            if isinstance(el, list):
                args.extend(el)
            else: 
                args.append(el)
    p[0]=args

def p_funcdef(p):
    """funcdef : ID LPAREN argslist RPAREN EQUALS FUNCTION innerblock
    """
    print "lenp:", len(p)
    fname=p[1]
    print "fname: ", fname
    args=p[3]
    print "with params:", args
    innerblock=p[7]
    p[0]=('FUNC', innerblock)

def p_stmt_funcdef(p):
    """stmt : funcdef"""
    p[0]=p[1]
def p_stmt_expr(p):
    'stmt : expr'
    p[0] = p[1]

def p_stmt(p):
    'stmt : '

def p_expression_uminus(p):
    "expr : '-' expr %prec UMINUS"
    p[0] = -p[2]
    
def p_expression_plus(p):
    'expr : expr PLUS term'
    p[0] = p[1] + p[3]

def p_expression_minus(p):
    'expr : expr MINUS term'
    p[0] = p[1] + p[3]
    
def p_expression_term(p):
    'expr : term'
    p[0] = p[1]
#
def p_factor_variable(p):
    'factor : ID'
    p[0]=p[1]
def p_term_times(p):
    'term : term TIMES factor'
    p[0] = p[1] * p[3]
    
def p_term_div(p):
    'term : term DIVIDE factor'
    p[0] = p[1] / p[3]
    
def p_term_factor(p):
    'term : factor'
    p[0] = p[1]
    
def p_factor_number(p):
    'factor : NUMBER'
    p[0] = p[1]

def p_factor_expr(p):
    'factor : LPAREN expr RPAREN'
    p[0] = p[2]
    
def p_error(p):
    print "Syntax error"

if __name__=="__main__":
    #line="{1+20 + (3+2)*5 ;  3+5; 6+1;}"
    #line="{ print(5,3,6+6) ; 1+2; 5+2}"
    line="f(x,y)=function{print(3)}"
    p=yacc.yacc()
    p.parse(line, debug=False)
    
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.