Allow ${expansion} in addition to $(expansion).
authorBenjamin Smedberg <benjamin@smedbergs.us>
Wed, 11 Feb 2009 16:08:54 -0500
changeset 97 d31336e2accf4770dcdb0710719e24b9ef9ed929
parent 96 699803fc5647083d8f7fe5ce68c58235c96f1c15
child 98 ba5f4e0dfe9d2d9af521e0db3aa8ad623546479a
push id51
push userbsmedberg@mozilla.com
push dateWed, 11 Feb 2009 21:48:21 +0000
Allow ${expansion} in addition to $(expansion).
pymake/parser.py
tests/func-refs.mk
tests/var-ref.mk
--- a/pymake/parser.py
+++ b/pymake/parser.py
@@ -733,20 +733,21 @@ PARSESTATE_TOPLEVEL = 0    # at the top 
 PARSESTATE_FUNCTION = 1    # expanding a function call. data is function
 
 # For the following three, data is a tuple of Expansions: (varname, substfrom, substto)
 PARSESTATE_VARNAME = 2     # expanding a variable expansion.
 PARSESTATE_SUBSTFROM = 3   # expanding a variable expansion substitution "from" value
 PARSESTATE_SUBSTTO = 4     # expanding a variable expansion substitution "to" value
 
 class ParseStackFrame(object):
-    def __init__(self, parsestate, expansion, stopon, **kwargs):
+    def __init__(self, parsestate, expansion, stopon, closebrace, **kwargs):
         self.parsestate = parsestate
         self.expansion = expansion
         self.stopon = stopon
+        self.closebrace = closebrace
         for key, value in kwargs.iteritems():
             setattr(self, key, value)
 
 functiontokens = [k for k in functions.functionmap.iterkeys()]
 functiontokens.sort(key=len, reverse=True)
 
 def parsemakesyntax(d, startat, stopon, iterfunc):
     """
@@ -765,17 +766,17 @@ def parsemakesyntax(d, startat, stopon, 
     token and offset will be None
     """
 
     # print "parsemakesyntax(%r)" % d.data
 
     assert callable(iterfunc)
 
     stack = [
-        ParseStackFrame(PARSESTATE_TOPLEVEL, data.Expansion(), stopon)
+        ParseStackFrame(PARSESTATE_TOPLEVEL, data.Expansion(), stopon, closebrace=None)
     ]
 
     di = iterfunc(d, startat)
     offset = startat
 
     while True: # this is not a for loop because `di` changes during the function
         stacktop = stack[-1]
         try:
@@ -796,53 +797,53 @@ def parsemakesyntax(d, startat, stopon, 
                 return stacktop.expansion, token, offset
 
             if stacktop.parsestate == PARSESTATE_FUNCTION:
                 if token == ',':
                     stacktop.expansion = data.Expansion()
                     stacktop.function.append(stacktop.expansion)
 
                     if len(stacktop.function) == stacktop.function.maxargs:
-                        stacktop.stopon = (')',)
-                elif token == ')':
+                        stacktop.stopon = (stacktop.closebrace,)
+                elif token in (')', '}'):
                     stacktop.function.setup()
                     stack.pop()
                     stack[-1].expansion.append(stacktop.function)
                 else:
                     assert False, "Not reached, PARSESTATE_FUNCTION"
             elif stacktop.parsestate == PARSESTATE_VARNAME:
                 if token == ':':
                     stacktop.varname = stacktop.expansion
                     stacktop.parsestate = PARSESTATE_SUBSTFROM
                     stacktop.expansion = data.Expansion()
-                    stacktop.stopon = ('=', ')')
-                elif token == ')':
+                    stacktop.stopon = ('=', stacktop.closebrace)
+                elif token in (')', '}'):
                     stack.pop()
                     stack[-1].expansion.append(functions.VariableRef(stacktop.loc, stacktop.expansion))
                 else:
                     assert False, "Not reached, PARSESTATE_VARNAME"
             elif stacktop.parsestate == PARSESTATE_SUBSTFROM:
                 if token == '=':
                     stacktop.substfrom = stacktop.expansion
                     stacktop.parsestate = PARSESTATE_SUBSTTO
                     stacktop.expansion = data.Expansion()
-                    stacktop.stopon = (')',)
-                elif token == ')':
+                    stacktop.stopon = (stacktop.closebrace,)
+                elif token in (')', '}'):
                     # A substitution of the form $(VARNAME:.ee) is probably a mistake, but make
                     # parses it. Issue a warning. Combine the varname and substfrom expansions to
                     # make the compatible varname. See tests/var-substitutions.mk SIMPLE3SUBSTNAME
                     log.warning("%s: Variable reference looks like substitution without =" % (stacktop.loc, ))
                     stacktop.varname.append(':')
                     stacktop.varname.concat(stacktop.expansion)
                     stack.pop()
                     stack[-1].expansion.append(functions.VariableRef(stacktop.loc, stacktop.varname))
                 else:
                     assert False, "Not reached, PARSESTATE_SUBSTFROM"
             elif stacktop.parsestate == PARSESTATE_SUBSTTO:
-                assert token == ')', "Not reached, PARSESTATE_SUBSTTO"
+                assert token in  (')','}'), "Not reached, PARSESTATE_SUBSTTO"
 
                 stack.pop()
                 stack[-1].expansion.append(functions.SubstitutionRef(stacktop.loc, stacktop.varname,
                                                                      stacktop.substfrom, stacktop.expansion))
             else:
                 assert False, "Unexpected parse state %s" % stacktop.parsestate
 
             continue
@@ -852,35 +853,38 @@ def parsemakesyntax(d, startat, stopon, 
             except StopIteration:
                 # an un-terminated $ expands to nothing
                 break
 
             if c == '$':
                 stacktop.expansion.append('$')
                 continue
 
-            if c == '(':
+            if c in ('(', '{'):
+                closebrace = c == '(' and ')' or '}'
+
                 # look forward for a function name
                 fname, offset = d.findtoken(offset + 1, functiontokens, True)
                 if fname is not None:
                     fn = functions.functionmap[fname](loc)
                     e = data.Expansion()
                     fn.append(e)
                     if len(fn) == fn.maxargs:
                         stopon = (')',)
                     else:
                         stopon = (',', ')')
 
                     stack.append(ParseStackFrame(PARSESTATE_FUNCTION,
-                                                 e, stopon, function=fn))
+                                                 e, stopon, function=fn,
+                                                 closebrace=closebrace))
                     di = iterfunc(d, offset)
                     continue
 
                 e = data.Expansion()
-                stack.append(ParseStackFrame(PARSESTATE_VARNAME, e, (':', ')'), loc=loc))
+                stack.append(ParseStackFrame(PARSESTATE_VARNAME, e, (':', closebrace), closebrace=closebrace, loc=loc))
                 continue
 
             fe = data.Expansion()
             fe.append(c)
             stacktop.expansion.append(functions.VariableRef(loc, fe))
             continue
 
         else:
--- a/tests/func-refs.mk
+++ b/tests/func-refs.mk
@@ -1,8 +1,9 @@
 unknown var = uval
 
 all:
 	test "$(subst a,b,value)" = "vblue"
+	test "${subst a,b,va)lue}" = "vb)lue"
 	test "$( subst a,b,value)" = ""
 	test "$(Subst a,b,value)" = ""
 	test "$(unknown var)" = "uval"
 	@echo TEST-PASS
--- a/tests/var-ref.mk
+++ b/tests/var-ref.mk
@@ -8,11 +8,12 @@ VARC = value # comment
   $(VAR4)  
 $(VAR5)
 
 VAR6$(VAR5) = val6
 
 all:
 	test "$( VAR)" = ""
 	test "$(VAR2)" = "= value"
+	test "${VAR2}" = "= value"
 	test "$(VAR6 )" = "val6"
 	test "$(VARC)" = "value "
 	@echo TEST-PASS