Change skippreproc -> processpre, add #pragma option processing.

Usage:

Options are case insensitive.
This commit is contained in:
Sei Lisa 2016-06-28 03:20:21 +02:00
parent a13b1cb77e
commit 0c3ad9b938
3 changed files with 89 additions and 16 deletions

View file

@ -312,6 +312,70 @@ class parser(object):
if self.pos >= self.length: if self.pos >= self.length:
raise EInternal() # force GetToken to return EOF raise EInternal() # force GetToken to return EOF
def SetOpt(self, option, value):
# See parse() for meaning of options.
if option == 'extendedglobalexpr':
self.extendedglobalexpr = value
if option == 'extendedtypecast':
self.extendedtypecast = value
if option == 'extendedassignment':
self.extendedassignment = value
if option == 'explicitcast':
self.explicitcast = value
if option == 'allowkeyconcat':
self.allowkeyconcat = value
if option == 'allowmultistrings':
self.allowmultistrings = value
if option == 'processpre':
self.processpre = value
# TODO: Allow pure C-style string escapes. This is low-priority.
#if option == 'allowcescapes':
# self.allowcescapes = value
# Enable switch statements.
if option == 'enableswitch':
if not self.enableswitch and value:
self.keywords |= self.switch_keywords
elif self.enableswitch and not value:
self.keywords = self.base_keywords
if self.breakcont:
self.keywords |= self.brkcont_keywords
self.enableswitch = value
# Enable break/continue
if option == 'breakcont':
if not self.breakcont and value:
self.keywords |= self.brkcont_keywords
elif self.breakcont and not value:
self.keywords = self.base_keywords
if self.enableswitch:
self.keywords |= self.switch_keywords
self.breakcont = value
if option == 'errmissingdefault':
self.errmissingdefault = value
if option == 'lazylists':
self.lazylists = value
if option == 'duplabels':
self.duplabels = value
if option == 'shrinknames':
self.shrinknames = value
if option == 'funcoverride':
self.funcoverride = value
def ProcessDirective(self, directive): def ProcessDirective(self, directive):
"""Process a given preprocessor directive during parsing.""" """Process a given preprocessor directive during parsing."""
@ -327,7 +391,7 @@ class parser(object):
r'^#\s*(?:' r'^#\s*(?:'
r'(?:[Ll][Ii][Nn][Ee]\s+)?(\d+)(?:\s+("(?:[^"\\]|\\.)*"))?' r'(?:[Ll][Ii][Nn][Ee]\s+)?(\d+)(?:\s+("(?:[^"\\]|\\.)*"))?'
r'|' r'|'
r'([A-Za-z0-9_]+)\s+(.+?)' r'([A-Za-z0-9_]+)\s+([A-Za-z0-9_]+)\s+([-+,A-Za-z0-9_]+)'
r')\s*$' r')\s*$'
) )
match = self.parse_directive_re.search(directive) match = self.parse_directive_re.search(directive)
@ -351,9 +415,16 @@ class parser(object):
del linenum del linenum
else: else:
assert match.group(3) is not None assert match.group(3) is not None
if match.group(3).lower() == 'pragma': if match.group(3).lower() == 'pragma' and match.group(4) == 'OPT':
# TODO: process #pragma opts = match.group(5).lower().split(',')
warning('pragma not implemented') for opt in opts:
if opt != '':
if opt[0] == '-':
self.SetOpt(opt[1:], False)
elif opt[0] == '+':
self.SetOpt(opt[1:], True)
else:
self.SetOpt(opt, True)
def GetToken(self): def GetToken(self):
"""Lexer""" """Lexer"""
@ -366,8 +437,8 @@ class parser(object):
c = self.script[self.pos] c = self.script[self.pos]
self.pos += 1 self.pos += 1
# Process comments # Process preprocessor directives
if self.skippreproc and self.linestart and c == '#': if self.processpre and self.linestart and c == '#':
# Preprocessor directive. # Preprocessor directive.
# Most are not supposed to reach us but some do: # Most are not supposed to reach us but some do:
# - gcpp generates lines in the output like: # - gcpp generates lines in the output like:
@ -392,6 +463,7 @@ class parser(object):
self.ceof() self.ceof()
continue continue
# Process comments
if c == '/': if c == '/':
if self.script[self.pos:self.pos+1] == '/': if self.script[self.pos:self.pos+1] == '/':
self.pos += 1 self.pos += 1
@ -2398,8 +2470,8 @@ list lazy_list_set(list L, integer i, list v)
# Allow C style string composition of strings: "blah" "blah" = "blahblah" # Allow C style string composition of strings: "blah" "blah" = "blahblah"
self.allowmultistrings = 'allowmultistrings' in options self.allowmultistrings = 'allowmultistrings' in options
# Skip preprocessor directives (specifically #line). # Process preprocessor directives (especially #pragma and #line).
self.skippreproc = 'skippreproc' in options self.processpre = 'processpre' in options
# TODO: Allow pure C-style string escapes. This is low-priority. # TODO: Allow pure C-style string escapes. This is low-priority.
#self.allowcescapes = 'allowcescapes' in options #self.allowcescapes = 'allowcescapes' in options

15
main.py
View file

@ -196,8 +196,8 @@ Preprocessor modes:
pertinent to it. Implies --precmd=cpp pertinent to it. Implies --precmd=cpp
none No preprocessing (default) none No preprocessing (default)
Normally, running the preprocessor needs -O skippreproc to make the output Normally, running the preprocessor needs the option 'processpre' active, to
readable by the optimizer. make the output readable by the optimizer. This option is active by default.
'''.format(progname=sys.argv[0], version=VERSION)) '''.format(progname=sys.argv[0], version=VERSION))
return return
@ -284,10 +284,11 @@ Optimizer options (+ means active by default, - means inactive by default):
warntabs + Suppress warning when a function can't be optimized warntabs + Suppress warning when a function can't be optimized
because it generates a string or list with a tab, or because it generates a string or list with a tab, or
when a string contains a tab. when a string contains a tab.
skippreproc + Skip preprocessor directives in the source as if they processpre + Process some preprocessor directives in the source. This
were comments. Not useful unless the script is itself enables usage of #pragma/#line preprocessor directives,
the output of a preprocessor like GNU cpp, which inserts and is probably necessary if the script is itself the
directives like: # 123 "filename". output of a preprocessor. Note that this option does not
make the optimizer process macros.
explicitcast - Add explicit casts where they are implicit. This option explicitcast - Add explicit casts where they are implicit. This option
is useless with 'optimize' and 'optsigns', and is of is useless with 'optimize' and 'optsigns', and is of
basically no use in general, other than to see where basically no use in general, other than to see where
@ -304,7 +305,7 @@ def main():
# Default options # Default options
options = set(('extendedglobalexpr','extendedtypecast','extendedassignment', options = set(('extendedglobalexpr','extendedtypecast','extendedassignment',
'allowkeyconcat','allowmultistrings','skippreproc','warntabs','optimize', 'allowkeyconcat','allowmultistrings','processpre','warntabs','optimize',
'optsigns','optfloats','constfold','dcr','errmissingdefault', 'optsigns','optfloats','constfold','dcr','errmissingdefault',
)) ))

View file

@ -213,7 +213,7 @@ class Test02_Parser(UnitTestCase):
}}''', }}''',
['explicitcast','extendedtypecast','extendedassignment', ['explicitcast','extendedtypecast','extendedassignment',
'extendedglobalexpr', 'allowmultistrings', 'allowkeyconcat', 'extendedglobalexpr', 'allowmultistrings', 'allowkeyconcat',
'skippreproc', 'duplabels'] 'processpre', 'duplabels']
)) ))
print self.parser.scopeindex print self.parser.scopeindex