Skip to content

Instantly share code, notes, and snippets.

@ikeikeikeike
Created March 26, 2012 17:30
Show Gist options
  • Save ikeikeikeike/2207007 to your computer and use it in GitHub Desktop.
Save ikeikeikeike/2207007 to your computer and use it in GitHub Desktop.
parser.py
# -*- coding: utf-8 -*-
import sys
import ply.yacc as yacc
from lexer import AssignLexer
import core
_quiet = True
class AssignLogger(yacc.PlyLogger):
def debug(self, *args, **kwargs):
if not _quiet:
super(type(self), self).debug(*args, **kwargs)
class AssignParser(object):
tokens = AssignLexer.tokens
def __init__(self, **yacc_args):
self.lexer = None
self.yacc_args = yacc_args
def parse(self, source_text, debug=0):
if self.lexer is None:
self.lexer = AssignLexer()
self.parser = yacc.yacc(module=self,
errorlog=AssignLogger(sys.stderr), **self.yacc_args)
return self.parser.parse(source_text, lexer=self.lexer, debug=debug)
def p_error(self, p):
if hasattr(p.lexer, "lexdata"):
source = p.lexer.lexdata
begin = source.rfind('\n', 0, p.lexpos)
end = source.find('\n', p.lexpos)
line = source[begin + 1:end]
print('Syntax error in input: row=%d col=%d\nerror => %s'
% (p.lineno, p.lexpos - begin, line))
else:
print('Syntax error in input')
def Assign(self, left, right):
if isinstance(left, core.Name):
return core.Assign([core.AssName(left.name, 'OP_ASSIGN')], right)
else:
raise SyntaxError("Can't do that yet")
def p_expr_stmt(self, p):
"""expr_stmt : testlist ASSIGN testlist
| testlist """
if len(p) == 2:
# a list of expressions
p[0] = core.Discard(p[1])
else:
p[0] = self.Assign(p[1], p[3])
def p_atom_name(self, p):
"""atom : NAME"""
p[0] = core.Name(p[1])
def p_atom_number(self, p):
"""atom : NUMBER"""
p[0] = core.Const(p[1])
def p_atom_string(self, p):
"""atom : STRING"""
p[0] = core.Const(p[1])
def p_testlist(self, p):
"""testlist : testlist_multi"""
if len(p) == 2:
p[0] = p[1]
else:
if isinstance(p[1], list):
p[0] = p[1]
else:
p[0] = [p[1]]
if isinstance(p[0], list):
raise AssertionError("not implemented")
def p_testlist_multi(self, p):
"""testlist_multi : test"""
if len(p) == 2:
# singleton
p[0] = p[1]
else:
if isinstance(p[1], list):
p[0] = p[1] + [p[3]]
else:
raise AssertionError("not implemented")
def p_test(self, p):
"""test : comparison"""
p[0] = p[1]
_binary_ops = {
"+": core.Add,
"-": core.Sub,
"*": core.Mul,
"/": core.Div,
}
_unary_ops = {
"+": core.UnaryAdd,
"-": core.UnarySub,
}
def p_comparison(self, p):
"""comparison : comparison PLUS comparison
| comparison MINUS comparison
| comparison MULT comparison
| comparison DIV comparison
| PLUS comparison
| MINUS comparison
| power"""
if len(p) == 4:
p[0] = self._binary_ops[p[2]]((p[1], p[3]))
elif len(p) == 3:
p[0] = self._unary_ops[p[1]](p[2])
else:
p[0] = p[1]
def p_power(self, p):
"""power : atom"""
if len(p) == 2:
p[0] = p[1]
else:
raise AssertionError("not implemented")
if __name__ == '__main__':
import pprint
# enable AssignLogger
_quiet = False
source_text = """
'test'
"""
syntax_tree = AssignParser().parse(source_text, debug=0)
pprint.pprint(syntax_tree)
print("----------")
source_text = """
1 * 2 - 1 / 3
"""
syntax_tree = AssignParser().parse(source_text, debug=0)
pprint.pprint(syntax_tree)
print("----------")
source_text = """
name = 1 + 2 + 10
"""
syntax_tree = AssignParser().parse(source_text, debug=0)
pprint.pprint(syntax_tree)
print("----------")
source_text = """
name = "name"
"""
syntax_tree = AssignParser().parse(source_text, debug=0)
pprint.pprint(syntax_tree)
print("----------")
source_text = """
name = "(`Д´)ノ"
"""
syntax_tree = AssignParser().parse(source_text, debug=0)
pprint.pprint(syntax_tree)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment