Changed compiler directive comment format
authorDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Fri, 15 Aug 2008 21:54:28 +0000 (23:54 +0200)
committerDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Fri, 15 Aug 2008 21:54:28 +0000 (23:54 +0200)
--HG--
rename : tests/compile/c_options.pyx => tests/compile/c_directives.pyx
rename : tests/errors/e_options.pyx => tests/errors/e_directives.pyx

Cython/Compiler/Lexicon.py
Cython/Compiler/Options.py
Cython/Compiler/Parsing.py
Cython/Compiler/Scanning.py
tests/compile/c_directives.pyx [moved from tests/compile/c_options.pyx with 50% similarity]
tests/errors/e_directives.pyx [new file with mode: 0644]
tests/errors/e_options.pyx [deleted file]

index 0c94dc7d059054c3262b863ed19abfa15533ed50..6b13ecd59aed08e5a27b524432f2c331ed623b5f 100644 (file)
@@ -79,9 +79,7 @@ def make_lexicon():
     escaped_newline = Str("\\\n")
     lineterm = Eol + Opt(Str("\n"))
 
-    comment_start = Str("#")
-    comment = comment_start + Rep(AnyBut("\n"))    
-    option_comment = comment_start + Str("cython:") + Rep(AnyBut("\n"))
+    comment = Str("#") + Rep(AnyBut("\n"))    
     
     return Lexicon([
         (name, 'IDENT'),
@@ -98,13 +96,12 @@ def make_lexicon():
         #(stringlit, 'STRING'),
         (beginstring, Method('begin_string_action')),
         
-        (option_comment, Method('option_comment')),
         (comment, IGNORE),
         (spaces, IGNORE),
         (escaped_newline, IGNORE),
         
         State('INDENT', [
-            (option_comment + lineterm, Method('option_comment')),
+            (comment + lineterm, Method('commentline')),
             (Opt(spaces) + Opt(comment) + lineterm, IGNORE),
             (indentation, Method('indentation_action')),
             (Eof, Method('eof_action'))
index 69ab2cae211a96f16b104284705684e4c74e3b0d..1e3b694e60cbf9df4e8a69af044ac54259b04bcb 100644 (file)
@@ -63,6 +63,30 @@ option_defaults = {
     'boundscheck' : True
 }
 
+def parse_option_value(name, value):
+    """
+    Parses value as an option value for the given name and returns
+    the interpreted value. None is returned if the option does not exist.    
+
+    >>> print parse_option_value('nonexisting', 'asdf asdfd')
+    None
+    >>> parse_option_value('boundscheck', 'True')
+    True
+    >>> parse_option_value('boundscheck', 'true')
+    Traceback (most recent call last):
+       ...
+    ValueError: boundscheck directive must be set to True or False
+    
+    """
+    type = option_types.get(name)
+    if not type: return None
+    if type is bool:
+        if value == "True": return True
+        elif value == "False": return False
+        else: raise ValueError("%s directive must be set to True or False" % name)
+    else:
+        assert False
+
 def parse_option_list(s):
     """
     Parses a comma-seperated list of pragma options. Whitespace
index 5d3009a633ec015c49079c696d3879c04363552d..8a900a66472ac0119e8ca8348505eb12e7d4b99a 100644 (file)
@@ -2348,14 +2348,20 @@ def p_code(s, level=None):
             repr(s.sy), repr(s.systring)))
     return body
 
-def p_option_comments(s):
+COMPILER_DIRECTIVE_COMMENT_RE = re.compile(r"^#\s*([a-z]+)\s*=(.*)$")
+
+def p_compiler_directive_comments(s):
     result = {}
-    while s.sy == 'option_comment':
-        opts = s.systring[len("#cython:"):]
-        try:
-            result.update(Options.parse_option_list(opts))
-        except ValueError, e:
-            s.error(e.message, fatal=False)
+    while s.sy == 'commentline':
+        m = COMPILER_DIRECTIVE_COMMENT_RE.match(s.systring)
+        if m:
+            name = m.group(1)
+            try:
+                value = Options.parse_option_value(str(name), str(m.group(2).strip()))
+            except ValueError, e:
+                s.error(e.message, fatal=False)
+            if value is not None: # can be False!
+                result[name] = value
         s.next()
     return result
 
@@ -2369,8 +2375,8 @@ def p_module(s, pxd, full_module_name):
     else:
         level = 'module'
 
-    option_comments = p_option_comments(s)
-    s.parse_option_comments = False
+    option_comments = p_compiler_directive_comments(s)
+    s.parse_comments = False
     body = p_statement_list(s, Ctx(level = level), first_statement = 1)
     if s.sy != 'EOF':
         s.error("Syntax error in statement [%s,%s]" % (
index 618168d809003cb30d25420b6fc40b5500fc94de..a2981504eed2a228463df88b95eb5378d27e7826 100644 (file)
@@ -306,7 +306,7 @@ class PyrexScanner(Scanner):
             self.compile_time_env = initial_compile_time_env()
             self.compile_time_eval = 1
             self.compile_time_expr = 0
-        self.parse_option_comments = True
+        self.parse_comments = True
         self.source_encoding = source_encoding
         self.trace = trace_scanner
         self.indentation_stack = [0]
@@ -316,12 +316,9 @@ class PyrexScanner(Scanner):
         self.sy = ''
         self.next()
 
-    def option_comment(self, text):
-        # #cython:-comments should be treated as literals until
-        # parse_option_comments is set to False, at which point
-        # they should be ignored.
-        if self.parse_option_comments:
-            self.produce('option_comment', text)    
+    def commentline(self, text):
+        if self.parse_comments:
+            self.produce('commentline', text)    
     
     def current_level(self):
         return self.indentation_stack[-1]
similarity index 50%
rename from tests/compile/c_options.pyx
rename to tests/compile/c_directives.pyx
index c638cb19682b85401269e8d72451f2e2ac577ad5..322bd43f0add4e5c1363c56aee1464921f3d06e2 100644 (file)
@@ -1,28 +1,34 @@
-#cython: boundscheck=False
+#     boundscheck  =  False
+# ignoreme = OK
+
+# This testcase is most useful if you inspect the generated C file
 
 print 3
 
 cimport python_dict as asadf, python_exc, cython as cy
 
+def e(object[int, 2] buf):
+    print buf[3, 2] # no bc
+
 @cy.boundscheck(False)
 def f(object[int, 2] buf):
-    print buf[3, 2]
+    print buf[3, 2] # no bc
 
 @cy.boundscheck(True)
 def g(object[int, 2] buf):
-    # Please leave this comment, 
-#cython: this should have no special meaning
+    # The below line should have no meaning 
+# boundscheck = False
     # even if the above line doesn't follow indentation.
-    print buf[3, 2]
+    print buf[3, 2] # bc
 
 def h(object[int, 2] buf):
-    print buf[3, 2]
+    print buf[3, 2] # no bc
     with cy.boundscheck(True):
-        print buf[3,2]
+        print buf[3,2] # bc
 
 from cython cimport boundscheck as bc
 
 def i(object[int] buf):
     with bc(True):
-        print buf[3]
+        print buf[3] # bs
     
diff --git a/tests/errors/e_directives.pyx b/tests/errors/e_directives.pyx
new file mode 100644 (file)
index 0000000..c626b4f
--- /dev/null
@@ -0,0 +1,15 @@
+
+# nonexistant = True
+# boundscheck = true
+# boundscheck = 9
+
+print 3
+
+# Options should not be interpreted any longer:
+# boundscheck = true
+
+_ERRORS = u"""
+3:0: boundscheck directive must be set to True or False
+4:0: boundscheck directive must be set to True or False
+"""
+
diff --git a/tests/errors/e_options.pyx b/tests/errors/e_options.pyx
deleted file mode 100644 (file)
index 0c82adc..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-
-#cython: nonexistant
-#cython: some=9
-
-# The one below should NOT raise an error
-
-#cython: boundscheck=True
-
-# However this one should
-#cython: boundscheck=sadf
-
-print 3
-
-#cython: boundscheck=True
-
-_ERRORS = u"""
-2:0: Expected "=" in option "nonexistant"
-3:0: Unknown option: "some"
-10:0: Must pass a boolean value for option "boundscheck"
-"""
-