Commits

Friedrich Weber  committed 30daa56

parser: implemented quoted strings; liblets: some notes on atomic liblets

  • Participants
  • Parent commits 71f04b2

Comments (0)

Files changed (3)

+def pythonize_string(s):
+    return s[1:-1].decode('string-escape')
 
 %%
 
 parser Command:
     ignore: "\\s+"
     token END: "$"
-    token SYMBOL: "[a-zA-Z0-9_.:#/][a-zA-Z0-9_.:#/-]*"
+    token SYMBOL: "[a-zA-Z0-9_.:#/äöüÄÖÜ][a-zA-Z0-9_.:#/äöüÄÖÜ-]*"
     token HYPHEN: "-"
     token DHYPHEN: "--"
     token GT: ">"
+    token STRING: '[rR]?\'([^\\n\'\\\\]|\\\\.)*\'|[rR]?"([^\\n"\\\\]|\\\\.)*"'
 
     rule goal: subject [parameters<<[], {}>>] [additional<<{}>>] END
                 {{ try: parameters }}
                 {{ return (subject, parameters[0], parameters[1], additional) }}
 
     rule parameters<<positional, keywords>>: (parameter<<positional, keywords>>)+ {{ return positional, keywords}}
-    rule parameter<<positional, keywords>>: SYMBOL {{ positional.append(SYMBOL) }} # positional
+    rule parameter<<positional, keywords>>: value {{ positional.append(value) }} # positional
                                           | DHYPHEN SYMBOL ["="] value {{ keywords[SYMBOL] = value }} # keyword
                                           | HYPHEN SYMBOL {{ keywords[SYMBOL] = True }} # trigger  
     rule subject: SYMBOL {{ return SYMBOL }}
     rule additional<<d>>: GT SYMBOL {{ d[GT] = SYMBOL; return d }}
     rule value: SYMBOL {{ return SYMBOL }}
-
-    # no quoted strings atm. sorry.
+              | string {{ return string }}
+    rule string: STRING {{ return pythonize_string(STRING) }}
 
 %%
 

File jambalah/command.py

+def pythonize_string(s):
+    return s[1:-1].decode('string-escape')
 
 
 from string import *
         ('"="', re.compile('=')),
         ('\\s+', re.compile('\\s+')),
         ('END', re.compile('$')),
-        ('SYMBOL', re.compile('[a-zA-Z0-9_.:#/][a-zA-Z0-9_.:#/-]*')),
+        ('SYMBOL', re.compile('[a-zA-Z0-9_.:#/\xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c][a-zA-Z0-9_.:#/\xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c-]*')),
         ('HYPHEN', re.compile('-')),
         ('DHYPHEN', re.compile('--')),
         ('GT', re.compile('>')),
+        ('STRING', re.compile('[rR]?\'([^\\n\'\\\\]|\\\\.)*\'|[rR]?"([^\\n"\\\\]|\\\\.)*"')),
     ]
     def __init__(self, str):
         Scanner.__init__(self,None,['\\s+'],str)
 class Command(Parser):
     def goal(self):
         subject = self.subject()
-        if self._peek('END', 'GT', 'SYMBOL', 'DHYPHEN', 'HYPHEN') not in ['END', 'GT']:
+        if self._peek('END', 'GT', 'DHYPHEN', 'HYPHEN', 'SYMBOL', 'STRING') not in ['END', 'GT']:
             parameters = self.parameters([], {})
         if self._peek('END', 'GT') == 'GT':
             additional = self.additional({})
     def parameters(self, positional, keywords):
         while 1:
             parameter = self.parameter(positional, keywords)
-            if self._peek('SYMBOL', 'DHYPHEN', 'HYPHEN', 'END', 'GT') not in ['SYMBOL', 'DHYPHEN', 'HYPHEN']: break
+            if self._peek('DHYPHEN', 'HYPHEN', 'SYMBOL', 'STRING', 'END', 'GT') not in ['DHYPHEN', 'HYPHEN', 'SYMBOL', 'STRING']: break
         return positional, keywords
 
     def parameter(self, positional, keywords):
-        _token_ = self._peek('SYMBOL', 'DHYPHEN', 'HYPHEN')
-        if _token_ == 'SYMBOL':
-            SYMBOL = self._scan('SYMBOL')
-            positional.append(SYMBOL)
+        _token_ = self._peek('DHYPHEN', 'HYPHEN', 'SYMBOL', 'STRING')
+        if _token_ not in ['DHYPHEN', 'HYPHEN']:
+            value = self.value()
+            positional.append(value)
         elif _token_ == 'DHYPHEN':
             DHYPHEN = self._scan('DHYPHEN')
             SYMBOL = self._scan('SYMBOL')
-            if self._peek('"="', 'SYMBOL') == '"="':
+            if self._peek('"="', 'SYMBOL', 'STRING') == '"="':
                 self._scan('"="')
             value = self.value()
             keywords[SYMBOL] = value
         d[GT] = SYMBOL; return d
 
     def value(self):
-        SYMBOL = self._scan('SYMBOL')
-        return SYMBOL
+        _token_ = self._peek('SYMBOL', 'STRING')
+        if _token_ == 'SYMBOL':
+            SYMBOL = self._scan('SYMBOL')
+            return SYMBOL
+        else:# == 'STRING'
+            string = self.string()
+            return string
+
+    def string(self):
+        STRING = self._scan('STRING')
+        return pythonize_string(STRING)
 
 
 def parse(rule, text):

File jambalah/liblet.py

             return self.get_child_by_name(stuff)
 
 class AtomicLiblet(Liblet):
+    """
+        an atomic liblet is a liblet without children, e.g.
+        an ogg file or a stream.
+
+        The following attributes are required:
+
+        .. attribute:: url
+
+            the uri of the liblet, please make it gstreamer-compatible.
+            *file://* can be prepended implicitly
+            by :func:`player.translate_url`.
+
+        .. attribute:: artist
+
+            the name of the artist. last.fm-ish, please.
+
+        .. attribute:: title
+
+            the title of the song. last.fm please.
+
+        .. attribute:: scrobble
+
+            a boolean that you should set to True if the title could
+            be scrobbled. Set it to False if you can't provide with
+            enough information.
+
+    """
     def __init__(self, jam, parent, url):
         Liblet.__init__(self, jam, parent)
         self.url = url