summaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2019-05-23 15:20:41 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2019-05-23 14:19:11 +0000
commita2e0f19b61453dc472bca657935310dcfbf9fc86 (patch)
treec8472ec3542e71694615245efe72855359505a83 /util
parent6dfeb81bcb05360e83a55b519886014c55e8e771 (diff)
Make debug token output actually work for the pro2cmake qmake parser
setName() and setDebug() need to be called on a parser element before the parser element is used as a sub-element in another parser element, otherwise the debug output is not shown. Hence the "iterate over all locals" approach works only partially. Instead add a new decorating function add_element() for the construction of each parser element, and make sure to enable debugging inside that function. Unfortunately there is no clean way to avoid duplicating the parser element name both in the local variable and in the function argument. Change-Id: Iaa9ed9b7dbb22ec084070b9c049cf51c841d442c Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
Diffstat (limited to 'util')
-rwxr-xr-xutil/cmake/pro2cmake.py252
1 files changed, 143 insertions, 109 deletions
diff --git a/util/cmake/pro2cmake.py b/util/cmake/pro2cmake.py
index fbf153b057..0f3f796227 100755
--- a/util/cmake/pro2cmake.py
+++ b/util/cmake/pro2cmake.py
@@ -681,7 +681,8 @@ class Scope(object):
class QmakeParser:
def __init__(self, *, debug: bool = False) -> None:
- self._Grammar = self._generate_grammar(debug)
+ self.debug = debug
+ self._Grammar = self._generate_grammar()
@staticmethod
def set_up_py_parsing_nicer_debug_output():
@@ -709,54 +710,72 @@ class QmakeParser:
pp._defaultSuccessDebugAction = decrease_indent(pp._defaultSuccessDebugAction)
pp._defaultExceptionDebugAction = decrease_indent(pp._defaultExceptionDebugAction)
-
- def _generate_grammar(self, debug: bool):
+ def _generate_grammar(self):
# Define grammar:
pp.ParserElement.setDefaultWhitespaceChars(' \t')
- LC = pp.Suppress(pp.Literal('\\\n'))
- EOL = pp.Suppress(pp.LineEnd())
- Else = pp.Keyword('else')
- Identifier = pp.Word(pp.alphas + '_', bodyChars=pp.alphanums+'_-./')
- BracedValue = pp.nestedExpr(ignoreExpr=pp.quotedString \
- | pp.QuotedString(quoteChar='$(',
- endQuoteChar=')',
- escQuote='\\',
- unquoteResults=False)
- ).setParseAction(lambda s, l, t: ['(', *t[0], ')'])
+ def add_element(name: str, value: pp.ParserElement):
+ nonlocal self
+ if self.debug:
+ value.setName(name)
+ value.setDebug()
+ return value
+
+ LC = add_element('LC', pp.Suppress(pp.Literal('\\\n')))
+
+ EOL = add_element('EOL', pp.Suppress(pp.LineEnd()))
+ Else = add_element('Else', pp.Keyword('else'))
+ Identifier = add_element('Identifier', pp.Word(pp.alphas + '_',
+ bodyChars=pp.alphanums+'_-./'))
+ BracedValue = add_element('BracedValue',
+ pp.nestedExpr(
+ ignoreExpr=pp.quotedString |
+ pp.QuotedString(quoteChar='$(',
+ endQuoteChar=')',
+ escQuote='\\',
+ unquoteResults=False)
+ ).setParseAction(lambda s, l, t: ['(', *t[0], ')']))
Substitution \
- = pp.Combine(pp.Literal('$')
- + (((pp.Literal('$') + Identifier
- + pp.Optional(pp.nestedExpr()))
- | (pp.Literal('(') + Identifier + pp.Literal(')'))
- | (pp.Literal('{') + Identifier + pp.Literal('}'))
- | (pp.Literal('$') + pp.Literal('{')
- + Identifier + pp.Optional(pp.nestedExpr())
- + pp.Literal('}'))
- | (pp.Literal('$') + pp.Literal('[') + Identifier
- + pp.Literal(']'))
- )))
- LiteralValuePart = pp.Word(pp.printables, excludeChars='$#{}()')
+ = add_element('Substitution',
+ pp.Combine(pp.Literal('$')
+ + (((pp.Literal('$') + Identifier
+ + pp.Optional(pp.nestedExpr()))
+ | (pp.Literal('(') + Identifier + pp.Literal(')'))
+ | (pp.Literal('{') + Identifier + pp.Literal('}'))
+ | (pp.Literal('$') + pp.Literal('{')
+ + Identifier + pp.Optional(pp.nestedExpr())
+ + pp.Literal('}'))
+ | (pp.Literal('$') + pp.Literal('[') + Identifier
+ + pp.Literal(']'))
+ ))))
+ LiteralValuePart = add_element('LiteralValuePart',
+ pp.Word(pp.printables, excludeChars='$#{}()'))
SubstitutionValue \
- = pp.Combine(pp.OneOrMore(Substitution | LiteralValuePart
- | pp.Literal('$')))
- Value = pp.NotAny(Else | pp.Literal('}') | EOL) \
- + (pp.QuotedString(quoteChar='"', escChar='\\')
- | SubstitutionValue
- | BracedValue)
-
- Values = pp.ZeroOrMore(Value + pp.Optional(LC))('value')
-
- Op = pp.Literal('=') | pp.Literal('-=') | pp.Literal('+=') \
- | pp.Literal('*=')
-
- Key = Identifier
-
- Operation = Key('key') + pp.Optional(LC) \
- + Op('operation') + pp.Optional(LC) \
- + Values('value')
- CallArgs = pp.Optional(LC) + pp.nestedExpr()\
+ = add_element('SubstitutionValue',
+ pp.Combine(pp.OneOrMore(Substitution
+ | LiteralValuePart
+ | pp.Literal('$'))))
+ Value \
+ = add_element('Value',
+ pp.NotAny(Else | pp.Literal('}') | EOL) \
+ + (pp.QuotedString(quoteChar='"', escChar='\\')
+ | SubstitutionValue
+ | BracedValue))
+
+ Values = add_element('Values', pp.ZeroOrMore(Value + pp.Optional(LC))('value'))
+
+ Op = add_element('OP',
+ pp.Literal('=') | pp.Literal('-=') | pp.Literal('+=') \
+ | pp.Literal('*='))
+
+ Key = add_element('Key', Identifier)
+
+ Operation = add_element('Operation',
+ Key('key') + pp.Optional(LC) \
+ + Op('operation') + pp.Optional(LC) \
+ + Values('value'))
+ CallArgs = add_element('CallArgs', pp.Optional(LC) + pp.nestedExpr())
def parse_call_args(results):
out = ''
@@ -768,80 +787,95 @@ class QmakeParser:
return out
CallArgs.setParseAction(parse_call_args)
- Load = pp.Keyword('load') + CallArgs('loaded')
- Include = pp.Keyword('include') + CallArgs('included')
- Option = pp.Keyword('option') + CallArgs('option')
- DefineTestDefinition = pp.Suppress(pp.Keyword('defineTest') + CallArgs
- + pp.nestedExpr(opener='{', closer='}', ignoreExpr=pp.LineEnd())) # ignore the whole thing...
- ForLoop = pp.Suppress(pp.Keyword('for') + CallArgs
- + pp.nestedExpr(opener='{', closer='}', ignoreExpr=pp.LineEnd())) # ignore the whole thing...
- ForLoopSingleLine = pp.Suppress(pp.Keyword('for') + CallArgs
- + pp.Literal(':') + pp.SkipTo(EOL, ignore=LC)) # ignore the whole thing...
- FunctionCall = pp.Suppress(Identifier + pp.nestedExpr())
-
- Scope = pp.Forward()
-
- Statement = pp.Group(Load | Include | Option | ForLoop | ForLoopSingleLine \
- | DefineTestDefinition | FunctionCall | Operation)
- StatementLine = Statement + (EOL | pp.FollowedBy('}'))
- StatementGroup = pp.ZeroOrMore(StatementLine | Scope | pp.Suppress(EOL))
-
- Block = pp.Suppress('{') + pp.Optional(LC | EOL) \
- + StatementGroup + pp.Optional(LC | EOL) \
- + pp.Suppress('}') + pp.Optional(LC | EOL)
-
- ConditionEnd = pp.FollowedBy((pp.Optional(pp.White())
- + pp.Optional(LC) + (pp.Literal(':') \
- | pp.Literal('{') \
- | pp.Literal('|'))))
-
- ConditionPart1 = (pp.Optional('!') + Identifier + pp.Optional(BracedValue))
- ConditionPart2 = pp.CharsNotIn('#{}|:=\\\n')
- ConditionPart = (ConditionPart1 ^ ConditionPart2) + pp.Optional(LC) + ConditionEnd
-
- ConditionOp = pp.Literal('|') ^ pp.Literal(':')
- ConditionLC = pp.Suppress(pp.Optional(pp.White(' ') + LC + pp.White(' ')))
-
- ConditionRepeated = pp.ZeroOrMore((ConditionOp) + ConditionLC + ConditionPart)
-
- Condition = pp.Combine(ConditionPart + ConditionRepeated)
+
+ Load = add_element('Load', pp.Keyword('load') + CallArgs('loaded'))
+ Include = add_element('Include', pp.Keyword('include') + CallArgs('included'))
+ Option = add_element('Option', pp.Keyword('option') + CallArgs('option'))
+
+ # ignore the whole thing...
+ DefineTestDefinition = add_element(
+ 'DefineTestDefinition',
+ pp.Suppress(pp.Keyword('defineTest') + CallArgs
+ + pp.nestedExpr(opener='{', closer='}', ignoreExpr=pp.LineEnd())))
+
+ # ignore the whole thing...
+ ForLoop = add_element(
+ 'ForLoop',
+ pp.Suppress(pp.Keyword('for') + CallArgs
+ + pp.nestedExpr(opener='{', closer='}', ignoreExpr=pp.LineEnd())))
+
+ # ignore the whole thing...
+ ForLoopSingleLine = add_element(
+ 'ForLoopSingleLine',
+ pp.Suppress(pp.Keyword('for') + CallArgs
+ + pp.Literal(':') + pp.SkipTo(EOL, ignore=LC)))
+
+ # ignore the whole thing...
+ FunctionCall = add_element('FunctionCall', pp.Suppress(Identifier + pp.nestedExpr()))
+
+ Scope = add_element('Scope', pp.Forward())
+
+ Statement = add_element('Statement',
+ pp.Group(Load | Include | Option | ForLoop | ForLoopSingleLine
+ | DefineTestDefinition | FunctionCall | Operation))
+ StatementLine = add_element('StatementLine', Statement + (EOL | pp.FollowedBy('}')))
+ StatementGroup = add_element('StatementGroup',
+ pp.ZeroOrMore(StatementLine | Scope | pp.Suppress(EOL)))
+
+ Block = add_element('Block',
+ pp.Suppress('{') + pp.Optional(LC | EOL)
+ + StatementGroup + pp.Optional(LC | EOL)
+ + pp.Suppress('}') + pp.Optional(LC | EOL))
+
+ ConditionEnd = add_element('ConditionEnd',
+ pp.FollowedBy((pp.Optional(pp.White())
+ + pp.Optional(LC) + (pp.Literal(':')
+ | pp.Literal('{')
+ | pp.Literal('|')))))
+
+ ConditionPart1 = add_element('ConditionPart1',
+ (pp.Optional('!') + Identifier + pp.Optional(BracedValue)))
+ ConditionPart2 = add_element('ConditionPart2', pp.CharsNotIn('#{}|:=\\\n'))
+ ConditionPart = add_element(
+ 'ConditionPart',
+ (ConditionPart1 ^ ConditionPart2) + pp.Optional(LC) + ConditionEnd)
+
+ ConditionOp = add_element('ConditionOp', pp.Literal('|') ^ pp.Literal(':'))
+ ConditionLC = add_element('ConditionLC',
+ pp.Suppress(pp.Optional(pp.White(' ') + LC + pp.White(' '))))
+
+ ConditionRepeated = add_element('ConditionRepeated',
+ pp.ZeroOrMore((ConditionOp) + ConditionLC + ConditionPart))
+
+ Condition = add_element('Condition', pp.Combine(ConditionPart + ConditionRepeated))
Condition.setParseAction(lambda x: ' '.join(x).strip().replace(':', ' && ').strip(' && '))
# Weird thing like write_file(a)|error() where error() is the alternative condition
# which happens to be a function call. In this case there is no scope, but our code expects
# a scope with a list of statements, so create a fake empty statement.
- ConditionEndingInFunctionCall = pp.Suppress(ConditionOp) + FunctionCall \
- + pp.Empty().setParseAction(lambda x: [[]])\
- .setResultsName('statements')
-
- SingleLineScope = pp.Suppress(pp.Literal(':')) + pp.Optional(LC) \
- + pp.Group(Block | (Statement + EOL))('statements')
- MultiLineScope = pp.Optional(LC) + Block('statements')
-
- SingleLineElse = pp.Suppress(pp.Literal(':')) + pp.Optional(LC) \
- + (Scope | Block | (Statement + pp.Optional(EOL)))
- MultiLineElse = Block
- ElseBranch = pp.Suppress(Else) + (SingleLineElse | MultiLineElse)
+ ConditionEndingInFunctionCall = add_element(
+ 'ConditionEndingInFunctionCall', pp.Suppress(ConditionOp) + FunctionCall
+ + pp.Empty().setParseAction(lambda x: [[]])
+ .setResultsName('statements'))
+
+ SingleLineScope = add_element('SingleLineScope',
+ pp.Suppress(pp.Literal(':')) + pp.Optional(LC)
+ + pp.Group(Block | (Statement + EOL))('statements'))
+ MultiLineScope = add_element('MultiLineScope',
+ pp.Optional(LC) + Block('statements'))
+
+ SingleLineElse = add_element('SingleLineElse',
+ pp.Suppress(pp.Literal(':')) + pp.Optional(LC)
+ + (Scope | Block | (Statement + pp.Optional(EOL))))
+ MultiLineElse = add_element('MultiLineElse', Block)
+ ElseBranch = add_element('ElseBranch', pp.Suppress(Else) + (SingleLineElse | MultiLineElse))
+
+ # Scope is already add_element'ed in the forward declaration above.
Scope <<= pp.Optional(LC) \
- + pp.Group(Condition('condition') \
- + (SingleLineScope | MultiLineScope | ConditionEndingInFunctionCall) \
+ + pp.Group(Condition('condition')
+ + (SingleLineScope | MultiLineScope | ConditionEndingInFunctionCall)
+ pp.Optional(ElseBranch)('else_statements'))
- if debug:
- for ename in 'LC EOL ' \
- 'Condition ConditionPart ConditionEnd ' \
- 'Else ElseBranch SingleLineElse MultiLineElse ' \
- 'SingleLineScope MultiLineScope ' \
- 'Identifier ' \
- 'Key Op Values Value BracedValue ' \
- 'Scope Block ' \
- 'StatementGroup StatementLine Statement '\
- 'Load Include Option DefineTestDefinition ForLoop ' \
- 'FunctionCall CallArgs Operation'.split():
- expr = locals()[ename]
- expr.setName(ename)
- expr.setDebug()
-
Grammar = StatementGroup('statements')
Grammar.ignore(pp.pythonStyleComment())