diff options
Diffstat (limited to 'mesonbuild/mparser.py')
-rw-r--r-- | mesonbuild/mparser.py | 127 |
1 files changed, 75 insertions, 52 deletions
diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index f593c8e..ad1fedd 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -22,10 +22,12 @@ class ParseException(MesonException): self.colno = colno class Token: - def __init__(self, tid, lineno, colno, value): + def __init__(self, tid, subdir, lineno, colno, bytespan, value): self.tid = tid + self.subdir = subdir self.lineno = lineno self.colno = colno + self.bytespan = bytespan self.value = value def __eq__(self, other): @@ -71,7 +73,7 @@ class Lexer: ('questionmark', re.compile(r'\?')), ] - def lex(self, code): + def lex(self, code, subdir): lineno = 1 line_start = 0 loc = 0; @@ -87,7 +89,10 @@ class Lexer: curline = lineno col = mo.start()-line_start matched = True + span_start = loc loc = mo.end() + span_end = loc + bytespan = (span_start, span_end) match_text = mo.group() if tid == 'ignore' or tid == 'comment': break @@ -123,40 +128,41 @@ class Lexer: tid = match_text else: value = match_text - yield Token(tid, curline, col, value) + yield Token(tid, subdir, curline, col, bytespan, value) break if not matched: raise ParseException('lexer', lineno, col) -class BooleanNode: - def __init__(self, token, value): +class ElementaryNode: + def __init__(self, token): self.lineno = token.lineno + self.subdir = token.subdir self.colno = token.colno + self.value = token.value + self.bytespan = token.bytespan + +class BooleanNode(ElementaryNode): + def __init__(self, token, value): + super().__init__(token) self.value = value assert(isinstance(self.value, bool)) -class IdNode: +class IdNode(ElementaryNode): def __init__(self, token): - self.lineno = token.lineno - self.colno = token.colno - self.value = token.value + super().__init__(token) assert(isinstance(self.value, str)) def __str__(self): return "Id node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno) -class NumberNode: +class NumberNode(ElementaryNode): def __init__(self, token): - self.lineno = token.lineno - self.colno = token.colno - self.value = token.value + super().__init__(token) assert(isinstance(self.value, int)) -class StringNode: +class StringNode(ElementaryNode): def __init__(self, token): - self.lineno = token.lineno - self.colno = token.colno - self.value = token.value + super().__init__(token) assert(isinstance(self.value, str)) def __str__(self): @@ -164,20 +170,23 @@ class StringNode: class ArrayNode: def __init__(self, args): + self.subdir = args.subdir self.lineno = args.lineno self.colno = args.colno self.args = args class EmptyNode: def __init__(self): + self.subdir ='' self.lineno = 0 self.colno = 0 self.value = None class OrNode: - def __init__(self, lineno, colno, left, right): - self.lineno = lineno - self.colno = colno + def __init__(self, left, right): + self.subdir = left.subdir + self.lineno = left.lineno + self.colno = left.colno self.left = left self.right = right @@ -189,42 +198,48 @@ class AndNode: self.right = right class ComparisonNode: - def __init__(self, lineno, colno, ctype, left, right): - self.lineno = lineno - self.colno = colno + def __init__(self, ctype, left, right): + self.lineno = left.lineno + self.colno = left.colno + self.subdir = left.subdir self.left = left self.right = right self.ctype = ctype class ArithmeticNode: - def __init__(self, lineno, colno, operation, left, right): - self.lineno = lineno - self.colno = colno + def __init__(self,operation, left, right): + self.subdir = left.subdir + self.lineno = left.lineno + self.colno = left.colno self.left = left self.right = right self.operation = operation class NotNode: - def __init__(self, lineno, colno, value): - self.lineno = lineno - self.colno = colno + def __init__(self, location_node, value): + self.subdir = location_node.subdir + self.lineno = location_node.lineno + self.colno = location_node.colno self.value = value class CodeBlockNode: - def __init__(self, lineno, colno): - self.lineno = lineno - self.colno = colno + def __init__(self, location_node): + self.subdir = location_node.subdir + self.lineno = location_node.lineno + self.colno = location_node.colno self.lines = [] class IndexNode: def __init__(self, iobject, index): self.iobject = iobject self.index = index + self.subdir = iobject.subdir self.lineno = iobject.lineno self.colno = iobject.colno class MethodNode: - def __init__(self, lineno, colno, source_object, name, args): + def __init__(self, subdir, lineno, colno, source_object, name, args): + self.subdir = subdir self.lineno = lineno self.colno = colno self.source_object = source_object @@ -233,7 +248,8 @@ class MethodNode: self.args = args class FunctionNode: - def __init__(self, lineno, colno, func_name, args): + def __init__(self, subdir, lineno, colno, func_name, args): + self.subdir = subdir self.lineno = lineno self.colno = colno self.func_name = func_name @@ -272,9 +288,10 @@ class IfClauseNode(): self.elseblock = EmptyNode() class UMinusNode(): - def __init__(self, lineno, colno, value): - self.lineno = lineno - self.colno = colno + def __init__(self, current_location, value): + self.subdir = current_location.subdir + self.lineno = current_location.lineno + self.colno = current_location.colno self.value = value class IfNode(): @@ -296,7 +313,9 @@ class ArgumentNode(): def __init__(self, token): self.lineno = token.lineno self.colno = token.colno + self.subdir = token.subdir self.arguments = [] + self.commas = [] self.kwargs = {} self.order_error = False @@ -351,8 +370,8 @@ comparison_map = {'equal': '==', # 9 plain token class Parser: - def __init__(self, code): - self.stream = Lexer().lex(code) + def __init__(self, code, subdir): + self.stream = Lexer().lex(code, subdir) self.getsym() self.in_ternary = False @@ -360,7 +379,7 @@ class Parser: try: self.current = next(self.stream) except StopIteration: - self.current = Token('eof', 0, 0, None) + self.current = Token('eof', '', 0, 0, (0, 0), None) def accept(self, s): if self.current.tid == s: @@ -409,7 +428,7 @@ class Parser: def e2(self): left = self.e3() while self.accept('or'): - left = OrNode(left.lineno, left.colno, left, self.e3()) + left = OrNode(left, self.e3()) return left def e3(self): @@ -422,7 +441,7 @@ class Parser: left = self.e5() for nodename, operator_type in comparison_map.items(): if self.accept(nodename): - return ComparisonNode(left.lineno, left.colno, operator_type, left, self.e5()) + return ComparisonNode(operator_type, left, self.e5()) return left def e5(self): @@ -431,38 +450,38 @@ class Parser: def e5add(self): left = self.e5sub() if self.accept('plus'): - return ArithmeticNode(left.lineno, left.colno, 'add', left, self.e5add()) + return ArithmeticNode('add', left, self.e5add()) return left def e5sub(self): left = self.e5mod() if self.accept('dash'): - return ArithmeticNode(left.lineno, left.colno, 'sub', left, self.e5sub()) + return ArithmeticNode('sub', left, self.e5sub()) return left def e5mod(self): left = self.e5mul() if self.accept('percent'): - return ArithmeticNode(left.lineno, left.colno, 'mod', left, self.e5mod()) + return ArithmeticNode('mod', left, self.e5mod()) return left def e5mul(self): left = self.e5div() if self.accept('star'): - return ArithmeticNode(left.lineno, left.colno, 'mul', left, self.e5mul()) + return ArithmeticNode('mul', left, self.e5mul()) return left def e5div(self): left = self.e6() if self.accept('fslash'): - return ArithmeticNode(left.lineno, left.colno, 'div', left, self.e5div()) + return ArithmeticNode('div', left, self.e5div()) return left def e6(self): if self.accept('not'): - return NotNode(self.current.lineno, self.current.colno, self.e7()) + return NotNode(self.current, self.e7()) if self.accept('dash'): - return UMinusNode(self.current.lineno, self.current.colno, self.e7()) + return UMinusNode(self.current, self.e7()) return self.e7() def e7(self): @@ -473,7 +492,7 @@ class Parser: if not isinstance(left, IdNode): raise ParseException('Function call must be applied to plain id', left.lineno, left.colno) - left = FunctionNode(left.lineno, left.colno, left.value, args) + left = FunctionNode(left.subdir, left.lineno, left.colno, left.value, args) go_again = True while go_again: go_again = False @@ -516,15 +535,19 @@ class Parser: a = ArgumentNode(s) while not isinstance(s, EmptyNode): + potential = self.current if self.accept('comma'): + a.commas.append(potential) a.append(s) elif self.accept('colon'): if not isinstance(s, IdNode): raise ParseException('Keyword argument must be a plain identifier.', s.lineno, s.colno) a.set_kwarg(s.value, self.statement()) + potential = self.current if not self.accept('comma'): return a + a.commas.append(potential) else: a.append(s) return a @@ -539,7 +562,7 @@ class Parser: self.expect('lparen') args = self.args() self.expect('rparen') - method = MethodNode(methodname.lineno, methodname.colno, source_object, methodname.value, args) + method = MethodNode(methodname.subdir, methodname.lineno, methodname.colno, source_object, methodname.value, args) if self.accept('dot'): return self.method_call(method) return method @@ -593,7 +616,7 @@ class Parser: return self.statement() def codeblock(self): - block = CodeBlockNode(self.current.lineno, self.current.colno) + block = CodeBlockNode(self.current) cond = True while cond: curline = self.line() |