[cfe-commits] r77668 - /cfe/trunk/utils/test/ShUtil.py

Daniel Dunbar daniel at zuster.org
Fri Jul 31 00:59:18 PDT 2009


Author: ddunbar
Date: Fri Jul 31 02:59:05 2009
New Revision: 77668

URL: http://llvm.org/viewvc/llvm-project?rev=77668&view=rev
Log:
MultiTestRunner: Add module for lexing 'sh' commands.

Added:
    cfe/trunk/utils/test/ShUtil.py

Added: cfe/trunk/utils/test/ShUtil.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/test/ShUtil.py?rev=77668&view=auto

==============================================================================
--- cfe/trunk/utils/test/ShUtil.py (added)
+++ cfe/trunk/utils/test/ShUtil.py Fri Jul 31 02:59:05 2009
@@ -0,0 +1,126 @@
+import Util
+
+class ShLexer:
+    def __init__(self, data):
+        self.data = data
+        self.pos = 0
+        self.end = len(data)
+
+    def eat(self):
+        c = self.data[self.pos]
+        self.pos += 1
+        return c
+
+    def look(self):
+        return self.data[self.pos]
+
+    def maybe_eat(self, c):
+        """
+        maybe_eat(c) - Consume the character c if it is the next character,
+        returning True if a character was consumed. """
+        if self.data[self.pos] == c:
+            self.pos += 1
+            return True
+        return False
+
+    def lex_arg(self, c):
+        if c in "'\"":
+            str = self.lex_arg_quoted(c)
+        else:
+            str = c
+        while self.pos != self.end:
+            c = self.look()
+            if c.isspace() or c in "|><&":
+                break
+            elif c == '"':
+                self.eat()
+                str += self.lex_arg_quoted('"')
+            else:
+                str += self.eat()
+        return str
+
+    def lex_arg_quoted(self, delim):
+        str = ''
+        while self.pos != self.end:
+            c = self.eat()
+            if c == delim:
+                return str
+            elif c == '\\' and delim == '"':
+                # Shell escaping is just '\"' to avoid termination, no actual
+                # escaping.
+                if self.pos == self.end:
+                    Util.warning("escape at end of quoted argument in: %r" % 
+                                 self.data)
+                    return str
+                c = self.eat()
+                if c != delim:
+                    str += '\\'
+                str += c
+            else:
+                str += c
+        Util.warning("missing quote character in %r" % self.data)
+        return str
+
+    def lex_one_token(self):
+        """
+        lex_one_token - Lex a single 'sh' token. """
+
+        c = self.eat()
+        if c == ';':
+            return (c)
+        if c == '|':
+            if self.maybe_eat('|'):
+                return ('||',)
+            return (c,)
+        if c == '&':
+            if self.maybe_eat('&'):
+                return ('&&',)
+            if self.maybe_eat('>'): 
+                return ('&>',)
+            return (c,)
+        if c == '>':
+            if self.maybe_eat('&'):
+                return ('>&',)
+            if self.maybe_eat('>'):
+                return ('>>',)
+            return (c,)
+        if c == '<':
+            if self.maybe_eat('&'):
+                return ('<&',)
+            if self.maybe_eat('>'):
+                return ('<<',)
+        return self.lex_arg(c)
+
+    def lex(self):
+        while self.pos != self.end:
+            if self.look().isspace():
+                self.eat()
+            else:
+                yield self.lex_one_token()
+
+###
+
+import unittest
+
+class TestShLexer(unittest.TestCase):
+    def lex(self, str):
+        return list(ShLexer(str).lex())
+
+    def testops(self):
+        self.assertEqual(self.lex('a2>c'),
+                         ['a2', ('>',), 'c'])
+        self.assertEqual(self.lex('a 2>c'),
+                         ['a', '2', ('>',), 'c'])
+        
+    def testquoting(self):
+        self.assertEqual(self.lex(""" 'a' """),
+                         ['a'])
+        self.assertEqual(self.lex(""" "hello\\"world" """),
+                         ['hello"world'])
+        self.assertEqual(self.lex(""" "hello\\'world" """),
+                         ["hello\\'world"])
+        self.assertEqual(self.lex(""" he"llo wo"rld """),
+                         ["hello world"])
+
+if __name__ == '__main__':
+    unittest.main()





More information about the cfe-commits mailing list