Commit 2f022483 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Changed compiler directive comment format

--HG--
rename : tests/compile/c_options.pyx => tests/compile/c_directives.pyx
rename : tests/errors/e_options.pyx => tests/errors/e_directives.pyx
parent 8fc68f38
......@@ -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'))
......
......@@ -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
......
......@@ -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:"):]
while s.sy == 'commentline':
m = COMPILER_DIRECTIVE_COMMENT_RE.match(s.systring)
if m:
name = m.group(1)
try:
result.update(Options.parse_option_list(opts))
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]" % (
......
......@@ -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]
......
#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
# 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
"""
#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"
"""
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment