|
|
@ -57,9 +57,9 @@ class Lexer: |
|
|
|
('comma', re.compile(r',')), |
|
|
|
('comma', re.compile(r',')), |
|
|
|
('dot', re.compile(r'\.')), |
|
|
|
('dot', re.compile(r'\.')), |
|
|
|
('colon', re.compile(r':')), |
|
|
|
('colon', re.compile(r':')), |
|
|
|
('assign', re.compile(r'==')), |
|
|
|
('equal', re.compile(r'==')), |
|
|
|
('equal', re.compile(r'=')), |
|
|
|
|
|
|
|
('nequals', re.compile(r'\!=')), |
|
|
|
('nequals', re.compile(r'\!=')), |
|
|
|
|
|
|
|
('assign', re.compile(r'=')), |
|
|
|
] |
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
def lex(self, code): |
|
|
|
def lex(self, code): |
|
|
@ -148,6 +148,37 @@ class EmptyNode: |
|
|
|
self.colno = 0 |
|
|
|
self.colno = 0 |
|
|
|
self.value = None |
|
|
|
self.value = None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CodeBlockNode: |
|
|
|
|
|
|
|
def __init__(self, lineno, colno): |
|
|
|
|
|
|
|
self.lineno = lineno |
|
|
|
|
|
|
|
self.colno = colno |
|
|
|
|
|
|
|
self.lines = [] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MethodNode: |
|
|
|
|
|
|
|
def __init__(self, lineno, colno, source_object, name, args): |
|
|
|
|
|
|
|
self.lineno = lineno |
|
|
|
|
|
|
|
self.colno = colno |
|
|
|
|
|
|
|
self.source_object = source_object |
|
|
|
|
|
|
|
self.name = name |
|
|
|
|
|
|
|
assert(isinstance(self.name, str)) |
|
|
|
|
|
|
|
self.args = args |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FunctionNode: |
|
|
|
|
|
|
|
def __init__(self, lineno, colno, func_name, args): |
|
|
|
|
|
|
|
self.lineno = lineno |
|
|
|
|
|
|
|
self.colno = colno |
|
|
|
|
|
|
|
self.func_name = func_name |
|
|
|
|
|
|
|
assert(isinstance(func_name, str)) |
|
|
|
|
|
|
|
self.args = args |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AssignmentNode: |
|
|
|
|
|
|
|
def __init__(self, lineno, colno, var_name, value): |
|
|
|
|
|
|
|
self.lineno = lineno |
|
|
|
|
|
|
|
self.colno = colno |
|
|
|
|
|
|
|
self.var_name = var_name |
|
|
|
|
|
|
|
assert(isinstance(var_name, str)) |
|
|
|
|
|
|
|
self.value = value |
|
|
|
|
|
|
|
|
|
|
|
class ArgumentNode(): |
|
|
|
class ArgumentNode(): |
|
|
|
def __init__(self, token): |
|
|
|
def __init__(self, token): |
|
|
|
self.lineno = token.lineno |
|
|
|
self.lineno = token.lineno |
|
|
@ -165,7 +196,7 @@ class ArgumentNode(): |
|
|
|
def set_kwarg(self, name, value): |
|
|
|
def set_kwarg(self, name, value): |
|
|
|
if self.num_args() > 0: |
|
|
|
if self.num_args() > 0: |
|
|
|
self.order_error = True |
|
|
|
self.order_error = True |
|
|
|
self.kwargs[name.get_value()] = value |
|
|
|
self.kwargs[name] = value |
|
|
|
|
|
|
|
|
|
|
|
def num_args(self): |
|
|
|
def num_args(self): |
|
|
|
return len(self.arguments) |
|
|
|
return len(self.arguments) |
|
|
@ -217,45 +248,53 @@ class Parser: |
|
|
|
raise ParseException('Expecting %s got %s.' % (s, self.current.tid), self.current.lineno, self.current.colno) |
|
|
|
raise ParseException('Expecting %s got %s.' % (s, self.current.tid), self.current.lineno, self.current.colno) |
|
|
|
|
|
|
|
|
|
|
|
def parse(self): |
|
|
|
def parse(self): |
|
|
|
self.codeblock() |
|
|
|
block = self.codeblock() |
|
|
|
|
|
|
|
print(block.lines) |
|
|
|
|
|
|
|
|
|
|
|
def statement(self): |
|
|
|
def statement(self): |
|
|
|
self.e1() |
|
|
|
return self.e1() |
|
|
|
|
|
|
|
|
|
|
|
def e1(self): |
|
|
|
def e1(self): |
|
|
|
self.e2() |
|
|
|
left = self.e2() |
|
|
|
while self.accept('assign'): |
|
|
|
if self.accept('assign'): |
|
|
|
self.e1() |
|
|
|
value = self.e1() |
|
|
|
|
|
|
|
if not isinstance(left, IdNode): |
|
|
|
|
|
|
|
raise ParseException('Assignment target must be an id.', |
|
|
|
|
|
|
|
left.lineno, left.colno) |
|
|
|
|
|
|
|
return AssignmentNode(left.lineno, left.colno, left.value, value) |
|
|
|
|
|
|
|
return left |
|
|
|
|
|
|
|
|
|
|
|
def e2(self): |
|
|
|
def e2(self): |
|
|
|
self.e3() |
|
|
|
left = self.e3() |
|
|
|
if self.accept('or'): |
|
|
|
if self.accept('or'): |
|
|
|
self.e3() |
|
|
|
self.e3() |
|
|
|
|
|
|
|
return left |
|
|
|
|
|
|
|
|
|
|
|
def e3(self): |
|
|
|
def e3(self): |
|
|
|
self.e4() |
|
|
|
left = self.e4() |
|
|
|
if self.accept('and'): |
|
|
|
if self.accept('and'): |
|
|
|
self.e4() |
|
|
|
self.e4() |
|
|
|
|
|
|
|
return left |
|
|
|
|
|
|
|
|
|
|
|
def e4(self): |
|
|
|
def e4(self): |
|
|
|
self.e5() |
|
|
|
left = self.e5() |
|
|
|
if self.accept('equal'): |
|
|
|
if self.accept('equal'): |
|
|
|
self.e5() |
|
|
|
self.e5() |
|
|
|
|
|
|
|
return left |
|
|
|
|
|
|
|
|
|
|
|
def e5(self): |
|
|
|
def e5(self): |
|
|
|
if self.accept('not'): |
|
|
|
if self.accept('not'): |
|
|
|
pass |
|
|
|
pass |
|
|
|
self.e6() |
|
|
|
return self.e6() |
|
|
|
|
|
|
|
|
|
|
|
def e6(self): |
|
|
|
def e6(self): |
|
|
|
left = self.e7() |
|
|
|
left = self.e7() |
|
|
|
if self.accept('dot'): |
|
|
|
if self.accept('dot'): |
|
|
|
self.method_call() |
|
|
|
return self.method_call(left) |
|
|
|
self.e6() |
|
|
|
|
|
|
|
elif self.accept('lparen'): |
|
|
|
elif self.accept('lparen'): |
|
|
|
self.args() |
|
|
|
args = self.args() |
|
|
|
self.expect('rparen') |
|
|
|
self.expect('rparen') |
|
|
|
self.e6() |
|
|
|
return left |
|
|
|
|
|
|
|
|
|
|
|
def e7(self): |
|
|
|
def e7(self): |
|
|
|
if self.accept('('): |
|
|
|
if self.accept('('): |
|
|
@ -302,11 +341,15 @@ class Parser: |
|
|
|
a = ArgumentNode(self.current) |
|
|
|
a = ArgumentNode(self.current) |
|
|
|
return a |
|
|
|
return a |
|
|
|
|
|
|
|
|
|
|
|
def method_call(self): |
|
|
|
def method_call(self, source_object): |
|
|
|
self.e8() |
|
|
|
methodname = self.e8() |
|
|
|
|
|
|
|
if not(isinstance(methodname, IdNode)): |
|
|
|
|
|
|
|
raise ParseException('Method name must be plain id', |
|
|
|
|
|
|
|
self.current.lineno, self.current.colno) |
|
|
|
self.expect('lparen') |
|
|
|
self.expect('lparen') |
|
|
|
self.args() |
|
|
|
args = self.args() |
|
|
|
self.expect('rparen') |
|
|
|
self.expect('rparen') |
|
|
|
|
|
|
|
return MethodNode(methodname.lineno, methodname.colno, source_object, methodname.value, args) |
|
|
|
|
|
|
|
|
|
|
|
def ifelseblock(self): |
|
|
|
def ifelseblock(self): |
|
|
|
while self.accept('elif'): |
|
|
|
while self.accept('elif'): |
|
|
@ -328,15 +371,19 @@ class Parser: |
|
|
|
self.expect('endif') |
|
|
|
self.expect('endif') |
|
|
|
if self.current == 'eol': |
|
|
|
if self.current == 'eol': |
|
|
|
return |
|
|
|
return |
|
|
|
self.statement() |
|
|
|
return self.statement() |
|
|
|
|
|
|
|
|
|
|
|
def codeblock(self): |
|
|
|
def codeblock(self): |
|
|
|
|
|
|
|
block = CodeBlockNode(self.current.lineno, self.current.colno) |
|
|
|
cond = True |
|
|
|
cond = True |
|
|
|
while cond: |
|
|
|
while cond: |
|
|
|
self.line() |
|
|
|
curline = self.line() |
|
|
|
|
|
|
|
if not isinstance(curline, EmptyNode): |
|
|
|
|
|
|
|
block.lines.append(curline) |
|
|
|
cond = self.accept('eol') |
|
|
|
cond = self.accept('eol') |
|
|
|
if self.current == 'elif' or self.current == 'else': |
|
|
|
if self.current == 'elif' or self.current == 'else': |
|
|
|
cond = False |
|
|
|
cond = False |
|
|
|
|
|
|
|
return block |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
if __name__ == '__main__': |
|
|
|
code = open(sys.argv[1]).read() |
|
|
|
code = open(sys.argv[1]).read() |
|
|
|