Commits

Victor Kotseruba  committed 84d1ae7

support @while, string formatting for all strings (via ast.NodeTransformer)

  • Participants
  • Parent commits 5ae552f

Comments (0)

Files changed (1)

File sass/parser.py

     return value.strip()
 
 
+
+class AstWrap(object):    
+    
+    
+    def __init__(self, owner):
+        self.owner = weakref.proxy(owner)
+    
+    
+    def __getattr__(self, name):
+        return functools.partial(getattr(ast, name),
+                                 col_offset=0,
+                                 lineno=self.owner.lineno)
+    
+
+
+
+class RubyStringFormatter(ast.NodeTransformer):
+    
+    lineno = 0
+    
+    
+    def __init__(self):
+        super(RubyStringFormatter, self).__init__()
+        self.ast = AstWrap(self)
+    
+    
+    def visit_Str(self, node):
+        
+        s = node.s
+        
+        variables = set([])
+        
+        def _var_match(match):
+            variables.add(match.group(1))
+            return '%%(%s)s' % match.group(1)
+        
+        s = re.sub(r'#{!?(\w+)}', _var_match, s)
+        
+        if not variables:
+            return node
+        
+        dct = self.ast.Dict(keys=[self.ast.Str(s=k) for k in variables],
+                            values=[self.ast.Name(id=n, ctx=Load())
+                                    for n in variables],)
+        
+        return ast.copy_location(self.ast.BinOp(left=self.ast.Str(s=s),
+                                                op=self.ast.Mod(),
+                                                right=dct), node)
+
+
 class Parser(object):
     
-    
-    class AstWrap(object):
-        
-        
-        def __init__(self, owner):
-            self.owner = weakref.proxy(owner)
-        
-        
-        def __getattr__(self, name):
-            return functools.partial(getattr(ast, name),
-                                     col_offset=0,
-                                     lineno=self.owner.lineno)
-    
-    
     def __init__(self, indent=2):
         self.indent = indent
-        self.ast = self.AstWrap(self)
+        self.ast = AstWrap(self)
         self.reset()
     
     
             self.leave_ctx()
         ctx = self.ctx
         self.reset()
-        return ctx
+        mod = RubyStringFormatter().visit(ctx)
+        return mod
     
     
     def _push(self, expr):
         elif line.startswith('@for '):
             self.enter_ctx(self.handle_for(line[5:]))
         
+        elif line.startswith('@while '):
+            self.enter_ctx(self.handle_while(line[1:]))
+        
         elif line.startswith('.') or line.startswith('#') or\
                             level < self.get_level(next):
             self.enter_ctx(self.handle_rule(line))
         self._push(loop)
         return loop
     
+    
+    def handle_while(self, data):
+        data = _convert_s(data)
+        loop = ast.parse('%s:pass' % data).body[0]
+        loop.body = []
+        self._push(loop)
+        return loop
+    
+    
     def handle_prop(self, data):
         name, value, expr = self.parse_prop(data)
         if expr:
         )))
     
     
-    def _str(self, s):
-        
-        variables = set([])
-        
-        def _var_match(match):
-            variables.add(match.group(1))
-            return '%%(%s)s' % match.group(1)
-
-        s = re.sub(r'#{!(\w+)}', _var_match, s)
-        
-        dct = self.ast.Dict(keys=[self.ast.Str(s=k) for k in variables],
-                            values=[self.ast.Name(id=n, ctx=Load()) for n in variables])
-        
-        return self.ast.BinOp(left=self.ast.Str(s=s),
-                              op=self.ast.Mod(),
-                              right=dct)
-        
-    
     def handle_rule(self, data):
         
         if filter(lambda p: type(p) is ast.FunctionDef, self.parents + [self.ctx]):
                 self.ast.Assign(targets=[self.ast.Name(id='node', ctx=self.ast.Store())],
                                 value=self.ast.Call(
                                     func=self.ast.Name(id='Node', ctx=self.ast.Load()),
-                                    args=[self._str(data),
+                                    args=[self.ast.Str(data),
                                           self.ast.Name(id='parent', ctx=self.ast.Load()),
                                           self.ast.Name(id='_sheet', ctx=self.ast.Load()),
                                     ],