From 6cfd7d65d96ec3c5d6b85fd579240333ad343fc0 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Wed, 26 Dec 2012 21:34:55 +0200 Subject: [PATCH] Track line numbers in AST nodes. --- nodes.py | 46 +++++++++++++++++++++++++--------------------- parser.py | 19 +++++++++---------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/nodes.py b/nodes.py index 952319d1b..af52a30f8 100644 --- a/nodes.py +++ b/nodes.py @@ -15,7 +15,11 @@ # limitations under the License. class Node(): - pass + def __init__(self, lineno): + self.line_number = lineno + + def lineno(self): + return self.line_number class Expression(Node): pass @@ -24,30 +28,30 @@ class Statement(Node): pass class AtomExpression(Expression): - def __init__(self, value): - Expression.__init__(self) + def __init__(self, value, lineno): + Expression.__init__(self, lineno) self.value = value class StringExpression(Expression): - def __init__(self, value): - Expression.__init__(self) + def __init__(self, value, lineno): + Expression.__init__(self, lineno) self.value = value class AtomStatement(Statement): - def __init__(self, value): - Statement.__init__(self) + def __init__(self, value, lineno): + Statement.__init__(self, lineno) assert(type(value) == type('')) self.value = value class StringStatement(Statement): - def __init__(self, value): + def __init__(self, value, lineno): assert(type(value) == type('')) - Statement.__init__(self) + Statement.__init__(self, lineno) self.value = value class FunctionCall(Statement): - def __init__(self, func_name, arguments): - Statement.__init__(self) + def __init__(self, func_name, arguments, lineno): + Statement.__init__(self, lineno) self.func_name = func_name self.arguments = arguments @@ -55,21 +59,21 @@ class FunctionCall(Statement): return self.func_name.value class MethodCall(Statement): - def __init__(self, object_name, method_name, arguments): - Statement.__init__(self) + def __init__(self, object_name, method_name, arguments, lineno): + Statement.__init__(self, lineno) self.object_name = object_name self.method_name = method_name self.arguments = arguments class Assignment(Statement): - def __init__(self, var_name, value): - Statement.__init__(self) + def __init__(self, var_name, value, lineno): + Statement.__init__(self, lineno) self.var_name = var_name self.value = value class CodeBlock(Statement): - def __init__(self): - Statement.__init__(self) + def __init__(self, lineno): + Statement.__init__(self, lineno) self.statements = [] def prepend(self, statement): @@ -79,8 +83,8 @@ class CodeBlock(Statement): return self.statements class Arguments(Statement): - def __init__(self): - Statement.__init__(self) + def __init__(self, lineno): + Statement.__init__(self, lineno) self.arguments = [] def prepend(self, statement): @@ -88,7 +92,7 @@ class Arguments(Statement): def statement_from_expression(expr): if isinstance(expr, AtomExpression): - return AtomStatement(expr.value) + return AtomStatement(expr.value, expr.lineno()) if isinstance(expr, StringExpression): - return StringStatement(expr.value) + return StringStatement(expr.value, expr.lineno()) raise RuntimeError('Can not convert unknown expression to a statement.') diff --git a/parser.py b/parser.py index 639a19ae3..2fd634328 100755 --- a/parser.py +++ b/parser.py @@ -76,29 +76,29 @@ def p_codeblock(t): def p_codeblock_last(t): 'codeblock : statement EOL' - cb = nodes.CodeBlock() + cb = nodes.CodeBlock(t.lineno(1)) cb.prepend(t[1]) t[0] = cb def p_expression_atom(t): 'expression : ATOM' - t[0] = nodes.AtomExpression(t[1]) + t[0] = nodes.AtomExpression(t[1], t.lineno(1)) def p_expression_string(t): 'expression : STRING' - t[0] = nodes.StringExpression(t[1]) + t[0] = nodes.StringExpression(t[1], t.lineno(1)) def p_statement_assign(t): 'statement : expression EQUALS statement' - t[0] = nodes.Assignment(t[1], t[3]) + t[0] = nodes.Assignment(t[1], t[3], t.lineno(1)) def p_statement_func_call(t): 'statement : expression LPAREN args RPAREN' - t[0] = nodes.FunctionCall(t[1], t[3]) + t[0] = nodes.FunctionCall(t[1], t[3], t.lineno(1)) def p_statement_method_call(t): 'statement : expression DOT expression LPAREN args RPAREN' - t[0] = nodes.MethodCall(t[1], t[3], t[5]) + t[0] = nodes.MethodCall(t[1], t[3], t[5], t.lineno(1)) def p_statement_expression(t): 'statement : expression' @@ -112,13 +112,13 @@ def p_args_multiple(t): def p_args_single(t): 'args : statement' - args = nodes.Arguments() + args = nodes.Arguments(t.lineno(1)) args.prepend(t[1]) t[0] = args def p_args_none(t): 'args :' - t[0] = nodes.Arguments() + t[0] = nodes.Arguments(t.lineno(0)) def p_error(t): print('Parser errored out at: ' + t.value) @@ -141,8 +141,7 @@ def test_lexer(): def test_parser(): code = """func_call('something', 'or else') objectname.methodname(abc) - emptycall() - """ + emptycall()""" print(build_ast(code)) def build_ast(code):