source: proto/Compiler/lookAhead.py @ 2885

Last change on this file since 2885 was 2885, checked in by cameron, 7 years ago

pablo.Lookahead call translation

File size: 2.6 KB
Line 
1#
2# lookAhead.py
3#
4# Copyright 2013, Robert D. Cameron, Kenneth S. Herdy
5# All rights reserved.
6#
7# Information Gathering for Carry Processing in Pablo
8
9import ast
10
11def isLookAhead(builtin_fn):
12   return builtin_fn in ['Lookahead']
13
14def CheckForLookAhead(fncall, builtin_fnmod_noprefix='pablo'):
15  if not isinstance(fncall, ast.Call): return False
16  if isinstance(fncall.func, ast.Name): return isLookAhead(fncall.func)
17  elif isinstance(fncall.func, ast.Attribute) and isinstance(fncall.func.value, ast.Name):
18    if fncall.func.value.id == builtin_fnmod_noprefix: return isLookAhead(fncall.func.attr)
19    else: return False
20  else: return False
21
22class LookAheadError(Exception): pass
23
24#
25# LookAhead Info Set
26#
27class LookAheadInfoSetVisitor(ast.NodeVisitor):
28  def __init__(self, streamFunctionNode):
29    self.LookAheadSet = {}
30    self.generic_visit(streamFunctionNode)
31
32  def visit_Call(self, callnode):
33    self.generic_visit(callnode)
34    if CheckForLookAhead(callnode):
35      if len(callnode.args) == 2:
36        if not isinstance(callnode.args[0], ast.Num):
37          raise LookAheadError('2nd argument to lookahead, if present, must be a numeric constant')
38        peek_amount = callnode.args[1].n
39      elif len(callnode.args) == 2: 
40        peek_amount = 1
41      else: raise LookAheadError('lookahead needs 1 or 2 args')
42      if not isinstance(callnode.args[0], ast.Attribute):
43        raise LookAheadError('lookahead needs a stream within a stream struct, e.g. lex.RAngle')
44      if not isinstance(callnode.args[0].value, ast.Name):
45         raise LookAheadError('lookahead needs a stream within a stream struct, e.g. lex.RAngle')
46      struct_name = callnode.args[0].value.id
47      if not self.LookAheadSet.has_key(struct_name): self.LookAheadSet[struct_name] = []
48      self.LookAheadSet[struct_name].append(callnode.args[0].attr)
49
50class LookAheadTransformer (ast.NodeTransformer):
51  def xfrm(self, t):
52    return self.generic_visit(t)
53  def visit_Call(self, callnode):
54    self.generic_visit(callnode)
55    if not CheckForLookAhead(callnode): return callnode
56    if len(callnode.args) > 1:
57        peek_amount = callnode.args[1].n
58    else: 
59        peek_amount = 1
60    module_name = callnode.args[0].value
61    strm = callnode.args[0].attr
62    b0 = ast.Attribute(ast.Subscript(module_name, ast.Index(ast.Num(0)), ast.Load()), strm, ast.Load())
63    b1 = ast.Attribute(ast.Subscript(module_name, ast.Index(ast.Num(1)), ast.Load()), strm, ast.Load())
64    return ast.Call(ast.Name('pablo_blk_Lookahead_n_<%i>' %  peek_amount, ast.Load()), [b0, b1], [], None, None)
65
66
67if __name__ == "__main__":
68                import doctest
69                doctest.testmod()
Note: See TracBrowser for help on using the repository browser.