xref: /aosp_15_r20/external/vulkan-headers/registry/parse_dependency.py (revision 902771965e4c6d39c75c62130a6a330c08b024db)
1*90277196SAndroid Build Coastguard Worker#!/usr/bin/python3
2*90277196SAndroid Build Coastguard Worker
3*90277196SAndroid Build Coastguard Worker# Copyright 2022-2024 The Khronos Group Inc.
4*90277196SAndroid Build Coastguard Worker# Copyright 2003-2019 Paul McGuire
5*90277196SAndroid Build Coastguard Worker# SPDX-License-Identifier: MIT
6*90277196SAndroid Build Coastguard Worker
7*90277196SAndroid Build Coastguard Worker# apirequirements.py - parse 'depends' expressions in API XML
8*90277196SAndroid Build Coastguard Worker# Supported methods:
9*90277196SAndroid Build Coastguard Worker#   dependency - the expression string
10*90277196SAndroid Build Coastguard Worker#
11*90277196SAndroid Build Coastguard Worker# evaluateDependency(dependency, isSupported) evaluates the expression,
12*90277196SAndroid Build Coastguard Worker# returning a boolean result. isSupported takes an extension or version name
13*90277196SAndroid Build Coastguard Worker# string and returns a boolean.
14*90277196SAndroid Build Coastguard Worker#
15*90277196SAndroid Build Coastguard Worker# dependencyLanguage(dependency) returns an English string equivalent
16*90277196SAndroid Build Coastguard Worker# to the expression, suitable for header file comments.
17*90277196SAndroid Build Coastguard Worker#
18*90277196SAndroid Build Coastguard Worker# dependencyNames(dependency) returns a set of the extension and
19*90277196SAndroid Build Coastguard Worker# version names in the expression.
20*90277196SAndroid Build Coastguard Worker#
21*90277196SAndroid Build Coastguard Worker# dependencyMarkup(dependency) returns a string containing asciidoctor
22*90277196SAndroid Build Coastguard Worker# markup for English equivalent to the expression, suitable for extension
23*90277196SAndroid Build Coastguard Worker# appendices.
24*90277196SAndroid Build Coastguard Worker#
25*90277196SAndroid Build Coastguard Worker# All may throw a ParseException if the expression cannot be parsed or is
26*90277196SAndroid Build Coastguard Worker# not completely consumed by parsing.
27*90277196SAndroid Build Coastguard Worker
28*90277196SAndroid Build Coastguard Worker# Supported expressions at present:
29*90277196SAndroid Build Coastguard Worker#   - extension names
30*90277196SAndroid Build Coastguard Worker#   - '+' as AND connector
31*90277196SAndroid Build Coastguard Worker#   - ',' as OR connector
32*90277196SAndroid Build Coastguard Worker#   - parenthesization for grouping
33*90277196SAndroid Build Coastguard Worker
34*90277196SAndroid Build Coastguard Worker# Based on `examples/fourFn.py` from the
35*90277196SAndroid Build Coastguard Worker# https://github.com/pyparsing/pyparsing/ repository.
36*90277196SAndroid Build Coastguard Worker
37*90277196SAndroid Build Coastguard Workerfrom pyparsing import (
38*90277196SAndroid Build Coastguard Worker    Literal,
39*90277196SAndroid Build Coastguard Worker    Word,
40*90277196SAndroid Build Coastguard Worker    Group,
41*90277196SAndroid Build Coastguard Worker    Forward,
42*90277196SAndroid Build Coastguard Worker    alphas,
43*90277196SAndroid Build Coastguard Worker    alphanums,
44*90277196SAndroid Build Coastguard Worker    Regex,
45*90277196SAndroid Build Coastguard Worker    ParseException,
46*90277196SAndroid Build Coastguard Worker    CaselessKeyword,
47*90277196SAndroid Build Coastguard Worker    Suppress,
48*90277196SAndroid Build Coastguard Worker    delimitedList,
49*90277196SAndroid Build Coastguard Worker    infixNotation,
50*90277196SAndroid Build Coastguard Worker)
51*90277196SAndroid Build Coastguard Workerimport math
52*90277196SAndroid Build Coastguard Workerimport operator
53*90277196SAndroid Build Coastguard Workerimport pyparsing as pp
54*90277196SAndroid Build Coastguard Workerimport re
55*90277196SAndroid Build Coastguard Worker
56*90277196SAndroid Build Coastguard Workerfrom apiconventions import APIConventions as APIConventions
57*90277196SAndroid Build Coastguard Workerconventions = APIConventions()
58*90277196SAndroid Build Coastguard Worker
59*90277196SAndroid Build Coastguard Workerdef markupPassthrough(name):
60*90277196SAndroid Build Coastguard Worker    """Pass a name (leaf or operator) through without applying markup"""
61*90277196SAndroid Build Coastguard Worker    return name
62*90277196SAndroid Build Coastguard Worker
63*90277196SAndroid Build Coastguard Workerdef leafMarkupAsciidoc(name):
64*90277196SAndroid Build Coastguard Worker    """Markup a leaf name as an asciidoc link to an API version or extension
65*90277196SAndroid Build Coastguard Worker       anchor.
66*90277196SAndroid Build Coastguard Worker
67*90277196SAndroid Build Coastguard Worker       - name - version or extension name"""
68*90277196SAndroid Build Coastguard Worker
69*90277196SAndroid Build Coastguard Worker    return conventions.formatVersionOrExtension(name)
70*90277196SAndroid Build Coastguard Worker
71*90277196SAndroid Build Coastguard Workerdef leafMarkupC(name):
72*90277196SAndroid Build Coastguard Worker    """Markup a leaf name as a C expression, using conventions of the
73*90277196SAndroid Build Coastguard Worker       Vulkan Validation Layers
74*90277196SAndroid Build Coastguard Worker
75*90277196SAndroid Build Coastguard Worker       - name - version or extension name"""
76*90277196SAndroid Build Coastguard Worker
77*90277196SAndroid Build Coastguard Worker    (apivariant, major, minor) = apiVersionNameMatch(name)
78*90277196SAndroid Build Coastguard Worker
79*90277196SAndroid Build Coastguard Worker    if apivariant is not None:
80*90277196SAndroid Build Coastguard Worker        return name
81*90277196SAndroid Build Coastguard Worker    else:
82*90277196SAndroid Build Coastguard Worker        return f'ext.{name}'
83*90277196SAndroid Build Coastguard Worker
84*90277196SAndroid Build Coastguard WorkeropMarkupAsciidocMap = { '+' : 'and', ',' : 'or' }
85*90277196SAndroid Build Coastguard Worker
86*90277196SAndroid Build Coastguard Workerdef opMarkupAsciidoc(op):
87*90277196SAndroid Build Coastguard Worker    """Markup an operator as an asciidoc spec markup equivalent
88*90277196SAndroid Build Coastguard Worker
89*90277196SAndroid Build Coastguard Worker       - op - operator ('+' or ',')"""
90*90277196SAndroid Build Coastguard Worker
91*90277196SAndroid Build Coastguard Worker    return opMarkupAsciidocMap[op]
92*90277196SAndroid Build Coastguard Worker
93*90277196SAndroid Build Coastguard WorkeropMarkupCMap = { '+' : '&&', ',' : '||' }
94*90277196SAndroid Build Coastguard Worker
95*90277196SAndroid Build Coastguard Workerdef opMarkupC(op):
96*90277196SAndroid Build Coastguard Worker    """Markup an operator as a C language equivalent
97*90277196SAndroid Build Coastguard Worker
98*90277196SAndroid Build Coastguard Worker       - op - operator ('+' or ',')"""
99*90277196SAndroid Build Coastguard Worker
100*90277196SAndroid Build Coastguard Worker    return opMarkupCMap[op]
101*90277196SAndroid Build Coastguard Worker
102*90277196SAndroid Build Coastguard Worker
103*90277196SAndroid Build Coastguard Worker# Unfortunately global to be used in pyparsing
104*90277196SAndroid Build Coastguard WorkerexprStack = []
105*90277196SAndroid Build Coastguard Worker
106*90277196SAndroid Build Coastguard Workerdef push_first(toks):
107*90277196SAndroid Build Coastguard Worker    """Push a token on the global stack
108*90277196SAndroid Build Coastguard Worker
109*90277196SAndroid Build Coastguard Worker       - toks - first element is the token to push"""
110*90277196SAndroid Build Coastguard Worker
111*90277196SAndroid Build Coastguard Worker    exprStack.append(toks[0])
112*90277196SAndroid Build Coastguard Worker
113*90277196SAndroid Build Coastguard Worker# An identifier (version or extension name)
114*90277196SAndroid Build Coastguard WorkerdependencyIdent = Word(alphanums + '_')
115*90277196SAndroid Build Coastguard Worker
116*90277196SAndroid Build Coastguard Worker# Infix expression for depends expressions
117*90277196SAndroid Build Coastguard WorkerdependencyExpr = pp.infixNotation(dependencyIdent,
118*90277196SAndroid Build Coastguard Worker    [ (pp.oneOf(', +'), 2, pp.opAssoc.LEFT), ])
119*90277196SAndroid Build Coastguard Worker
120*90277196SAndroid Build Coastguard Worker# BNF grammar for depends expressions
121*90277196SAndroid Build Coastguard Worker_bnf = None
122*90277196SAndroid Build Coastguard Workerdef dependencyBNF():
123*90277196SAndroid Build Coastguard Worker    """
124*90277196SAndroid Build Coastguard Worker    boolop  :: '+' | ','
125*90277196SAndroid Build Coastguard Worker    extname :: Char(alphas)
126*90277196SAndroid Build Coastguard Worker    atom    :: extname | '(' expr ')'
127*90277196SAndroid Build Coastguard Worker    expr    :: atom [ boolop atom ]*
128*90277196SAndroid Build Coastguard Worker    """
129*90277196SAndroid Build Coastguard Worker    global _bnf
130*90277196SAndroid Build Coastguard Worker    if _bnf is None:
131*90277196SAndroid Build Coastguard Worker        and_, or_ = map(Literal, '+,')
132*90277196SAndroid Build Coastguard Worker        lpar, rpar = map(Suppress, '()')
133*90277196SAndroid Build Coastguard Worker        boolop = and_ | or_
134*90277196SAndroid Build Coastguard Worker
135*90277196SAndroid Build Coastguard Worker        expr = Forward()
136*90277196SAndroid Build Coastguard Worker        expr_list = delimitedList(Group(expr))
137*90277196SAndroid Build Coastguard Worker        atom = (
138*90277196SAndroid Build Coastguard Worker            boolop[...]
139*90277196SAndroid Build Coastguard Worker            + (
140*90277196SAndroid Build Coastguard Worker                (dependencyIdent).setParseAction(push_first)
141*90277196SAndroid Build Coastguard Worker                | Group(lpar + expr + rpar)
142*90277196SAndroid Build Coastguard Worker            )
143*90277196SAndroid Build Coastguard Worker        )
144*90277196SAndroid Build Coastguard Worker
145*90277196SAndroid Build Coastguard Worker        expr <<= atom + (boolop + atom).setParseAction(push_first)[...]
146*90277196SAndroid Build Coastguard Worker        _bnf = expr
147*90277196SAndroid Build Coastguard Worker    return _bnf
148*90277196SAndroid Build Coastguard Worker
149*90277196SAndroid Build Coastguard Worker
150*90277196SAndroid Build Coastguard Worker# map operator symbols to corresponding arithmetic operations
151*90277196SAndroid Build Coastguard Worker_opn = {
152*90277196SAndroid Build Coastguard Worker    '+': operator.and_,
153*90277196SAndroid Build Coastguard Worker    ',': operator.or_,
154*90277196SAndroid Build Coastguard Worker}
155*90277196SAndroid Build Coastguard Worker
156*90277196SAndroid Build Coastguard Workerdef evaluateStack(stack, isSupported):
157*90277196SAndroid Build Coastguard Worker    """Evaluate an expression stack, returning a boolean result.
158*90277196SAndroid Build Coastguard Worker
159*90277196SAndroid Build Coastguard Worker     - stack - the stack
160*90277196SAndroid Build Coastguard Worker     - isSupported - function taking a version or extension name string and
161*90277196SAndroid Build Coastguard Worker       returning True or False if that name is supported or not."""
162*90277196SAndroid Build Coastguard Worker
163*90277196SAndroid Build Coastguard Worker    op, num_args = stack.pop(), 0
164*90277196SAndroid Build Coastguard Worker    if isinstance(op, tuple):
165*90277196SAndroid Build Coastguard Worker        op, num_args = op
166*90277196SAndroid Build Coastguard Worker
167*90277196SAndroid Build Coastguard Worker    if op in '+,':
168*90277196SAndroid Build Coastguard Worker        # Note: operands are pushed onto the stack in reverse order
169*90277196SAndroid Build Coastguard Worker        op2 = evaluateStack(stack, isSupported)
170*90277196SAndroid Build Coastguard Worker        op1 = evaluateStack(stack, isSupported)
171*90277196SAndroid Build Coastguard Worker        return _opn[op](op1, op2)
172*90277196SAndroid Build Coastguard Worker    elif op[0].isalpha():
173*90277196SAndroid Build Coastguard Worker        return isSupported(op)
174*90277196SAndroid Build Coastguard Worker    else:
175*90277196SAndroid Build Coastguard Worker        raise Exception(f'invalid op: {op}')
176*90277196SAndroid Build Coastguard Worker
177*90277196SAndroid Build Coastguard Workerdef evaluateDependency(dependency, isSupported):
178*90277196SAndroid Build Coastguard Worker    """Evaluate a dependency expression, returning a boolean result.
179*90277196SAndroid Build Coastguard Worker
180*90277196SAndroid Build Coastguard Worker     - dependency - the expression
181*90277196SAndroid Build Coastguard Worker     - isSupported - function taking a version or extension name string and
182*90277196SAndroid Build Coastguard Worker       returning True or False if that name is supported or not."""
183*90277196SAndroid Build Coastguard Worker
184*90277196SAndroid Build Coastguard Worker    global exprStack
185*90277196SAndroid Build Coastguard Worker    exprStack = []
186*90277196SAndroid Build Coastguard Worker    results = dependencyBNF().parseString(dependency, parseAll=True)
187*90277196SAndroid Build Coastguard Worker    val = evaluateStack(exprStack[:], isSupported)
188*90277196SAndroid Build Coastguard Worker    return val
189*90277196SAndroid Build Coastguard Worker
190*90277196SAndroid Build Coastguard Workerdef evalDependencyLanguage(stack, leafMarkup, opMarkup, parenthesize, root):
191*90277196SAndroid Build Coastguard Worker    """Evaluate an expression stack, returning an English equivalent
192*90277196SAndroid Build Coastguard Worker
193*90277196SAndroid Build Coastguard Worker     - stack - the stack
194*90277196SAndroid Build Coastguard Worker     - leafMarkup, opMarkup, parenthesize - same as dependencyLanguage
195*90277196SAndroid Build Coastguard Worker     - root - True only if this is the outer (root) expression level"""
196*90277196SAndroid Build Coastguard Worker
197*90277196SAndroid Build Coastguard Worker    op, num_args = stack.pop(), 0
198*90277196SAndroid Build Coastguard Worker    if isinstance(op, tuple):
199*90277196SAndroid Build Coastguard Worker        op, num_args = op
200*90277196SAndroid Build Coastguard Worker    if op in '+,':
201*90277196SAndroid Build Coastguard Worker        # Could parenthesize, not needed yet
202*90277196SAndroid Build Coastguard Worker        rhs = evalDependencyLanguage(stack, leafMarkup, opMarkup, parenthesize, root = False)
203*90277196SAndroid Build Coastguard Worker        opname = opMarkup(op)
204*90277196SAndroid Build Coastguard Worker        lhs = evalDependencyLanguage(stack, leafMarkup, opMarkup, parenthesize, root = False)
205*90277196SAndroid Build Coastguard Worker        if parenthesize and not root:
206*90277196SAndroid Build Coastguard Worker            return f'({lhs} {opname} {rhs})'
207*90277196SAndroid Build Coastguard Worker        else:
208*90277196SAndroid Build Coastguard Worker            return f'{lhs} {opname} {rhs}'
209*90277196SAndroid Build Coastguard Worker    elif op[0].isalpha():
210*90277196SAndroid Build Coastguard Worker        # This is an extension or feature name
211*90277196SAndroid Build Coastguard Worker        return leafMarkup(op)
212*90277196SAndroid Build Coastguard Worker    else:
213*90277196SAndroid Build Coastguard Worker        raise Exception(f'invalid op: {op}')
214*90277196SAndroid Build Coastguard Worker
215*90277196SAndroid Build Coastguard Workerdef dependencyLanguage(dependency, leafMarkup, opMarkup, parenthesize):
216*90277196SAndroid Build Coastguard Worker    """Return an API dependency expression translated to a form suitable for
217*90277196SAndroid Build Coastguard Worker       asciidoctor conditionals or header file comments.
218*90277196SAndroid Build Coastguard Worker
219*90277196SAndroid Build Coastguard Worker     - dependency - the expression
220*90277196SAndroid Build Coastguard Worker     - leafMarkup - function taking an extension / version name and
221*90277196SAndroid Build Coastguard Worker                    returning an equivalent marked up version
222*90277196SAndroid Build Coastguard Worker     - opMarkup - function taking an operator ('+' / ',') name name and
223*90277196SAndroid Build Coastguard Worker                  returning an equivalent marked up version
224*90277196SAndroid Build Coastguard Worker     - parenthesize - True if parentheses should be used in the resulting
225*90277196SAndroid Build Coastguard Worker                      expression, False otherwise"""
226*90277196SAndroid Build Coastguard Worker
227*90277196SAndroid Build Coastguard Worker    global exprStack
228*90277196SAndroid Build Coastguard Worker    exprStack = []
229*90277196SAndroid Build Coastguard Worker    results = dependencyBNF().parseString(dependency, parseAll=True)
230*90277196SAndroid Build Coastguard Worker    return evalDependencyLanguage(exprStack, leafMarkup, opMarkup, parenthesize, root = True)
231*90277196SAndroid Build Coastguard Worker
232*90277196SAndroid Build Coastguard Worker# aka specmacros = False
233*90277196SAndroid Build Coastguard Workerdef dependencyLanguageComment(dependency):
234*90277196SAndroid Build Coastguard Worker    """Return dependency expression translated to a form suitable for
235*90277196SAndroid Build Coastguard Worker       comments in headers of emitted C code, as used by the
236*90277196SAndroid Build Coastguard Worker       docgenerator."""
237*90277196SAndroid Build Coastguard Worker    return dependencyLanguage(dependency, leafMarkup = markupPassthrough, opMarkup = opMarkupAsciidoc, parenthesize = True)
238*90277196SAndroid Build Coastguard Worker
239*90277196SAndroid Build Coastguard Worker# aka specmacros = True
240*90277196SAndroid Build Coastguard Workerdef dependencyLanguageSpecMacros(dependency):
241*90277196SAndroid Build Coastguard Worker    """Return dependency expression translated to a form suitable for
242*90277196SAndroid Build Coastguard Worker       comments in headers of emitted C code, as used by the
243*90277196SAndroid Build Coastguard Worker       interfacegenerator."""
244*90277196SAndroid Build Coastguard Worker    return dependencyLanguage(dependency, leafMarkup = leafMarkupAsciidoc, opMarkup = opMarkupAsciidoc, parenthesize = False)
245*90277196SAndroid Build Coastguard Worker
246*90277196SAndroid Build Coastguard Workerdef dependencyLanguageC(dependency):
247*90277196SAndroid Build Coastguard Worker    """Return dependency expression translated to a form suitable for
248*90277196SAndroid Build Coastguard Worker       use in C expressions"""
249*90277196SAndroid Build Coastguard Worker    return dependencyLanguage(dependency, leafMarkup = leafMarkupC, opMarkup = opMarkupC, parenthesize = True)
250*90277196SAndroid Build Coastguard Worker
251*90277196SAndroid Build Coastguard Workerdef evalDependencyNames(stack):
252*90277196SAndroid Build Coastguard Worker    """Evaluate an expression stack, returning the set of extension and
253*90277196SAndroid Build Coastguard Worker       feature names used in the expression.
254*90277196SAndroid Build Coastguard Worker
255*90277196SAndroid Build Coastguard Worker     - stack - the stack"""
256*90277196SAndroid Build Coastguard Worker
257*90277196SAndroid Build Coastguard Worker    op, num_args = stack.pop(), 0
258*90277196SAndroid Build Coastguard Worker    if isinstance(op, tuple):
259*90277196SAndroid Build Coastguard Worker        op, num_args = op
260*90277196SAndroid Build Coastguard Worker    if op in '+,':
261*90277196SAndroid Build Coastguard Worker        # Do not evaluate the operation. We only care about the names.
262*90277196SAndroid Build Coastguard Worker        return evalDependencyNames(stack) | evalDependencyNames(stack)
263*90277196SAndroid Build Coastguard Worker    elif op[0].isalpha():
264*90277196SAndroid Build Coastguard Worker        return { op }
265*90277196SAndroid Build Coastguard Worker    else:
266*90277196SAndroid Build Coastguard Worker        raise Exception(f'invalid op: {op}')
267*90277196SAndroid Build Coastguard Worker
268*90277196SAndroid Build Coastguard Workerdef dependencyNames(dependency):
269*90277196SAndroid Build Coastguard Worker    """Return a set of the extension and version names in an API dependency
270*90277196SAndroid Build Coastguard Worker       expression. Used when determining transitive dependencies for spec
271*90277196SAndroid Build Coastguard Worker       generation with specific extensions included.
272*90277196SAndroid Build Coastguard Worker
273*90277196SAndroid Build Coastguard Worker     - dependency - the expression"""
274*90277196SAndroid Build Coastguard Worker
275*90277196SAndroid Build Coastguard Worker    global exprStack
276*90277196SAndroid Build Coastguard Worker    exprStack = []
277*90277196SAndroid Build Coastguard Worker    results = dependencyBNF().parseString(dependency, parseAll=True)
278*90277196SAndroid Build Coastguard Worker    # print(f'names(): stack = {exprStack}')
279*90277196SAndroid Build Coastguard Worker    return evalDependencyNames(exprStack)
280*90277196SAndroid Build Coastguard Worker
281*90277196SAndroid Build Coastguard Workerdef markupTraverse(expr, level = 0, root = True):
282*90277196SAndroid Build Coastguard Worker    """Recursively process a dependency in infix form, transforming it into
283*90277196SAndroid Build Coastguard Worker       asciidoctor markup with expression nesting indicated by indentation
284*90277196SAndroid Build Coastguard Worker       level.
285*90277196SAndroid Build Coastguard Worker
286*90277196SAndroid Build Coastguard Worker       - expr - expression to process
287*90277196SAndroid Build Coastguard Worker       - level - indentation level to render expression at
288*90277196SAndroid Build Coastguard Worker       - root - True only on initial call"""
289*90277196SAndroid Build Coastguard Worker
290*90277196SAndroid Build Coastguard Worker    if level > 0:
291*90277196SAndroid Build Coastguard Worker        prefix = '{nbsp}{nbsp}' * level * 2 + ' '
292*90277196SAndroid Build Coastguard Worker    else:
293*90277196SAndroid Build Coastguard Worker        prefix = ''
294*90277196SAndroid Build Coastguard Worker    str = ''
295*90277196SAndroid Build Coastguard Worker
296*90277196SAndroid Build Coastguard Worker    for elem in expr:
297*90277196SAndroid Build Coastguard Worker        if isinstance(elem, pp.ParseResults):
298*90277196SAndroid Build Coastguard Worker            if not root:
299*90277196SAndroid Build Coastguard Worker                nextlevel = level + 1
300*90277196SAndroid Build Coastguard Worker            else:
301*90277196SAndroid Build Coastguard Worker                # Do not indent the outer expression
302*90277196SAndroid Build Coastguard Worker                nextlevel = level
303*90277196SAndroid Build Coastguard Worker
304*90277196SAndroid Build Coastguard Worker            str = str + markupTraverse(elem, level = nextlevel, root = False)
305*90277196SAndroid Build Coastguard Worker        elif elem in ('+', ','):
306*90277196SAndroid Build Coastguard Worker            str = str + f'{prefix}{opMarkupAsciidoc(elem)} +\n'
307*90277196SAndroid Build Coastguard Worker        else:
308*90277196SAndroid Build Coastguard Worker            str = str + f'{prefix}{leafMarkupAsciidoc(elem)} +\n'
309*90277196SAndroid Build Coastguard Worker
310*90277196SAndroid Build Coastguard Worker    return str
311*90277196SAndroid Build Coastguard Worker
312*90277196SAndroid Build Coastguard Workerdef dependencyMarkup(dependency):
313*90277196SAndroid Build Coastguard Worker    """Return asciidoctor markup for a human-readable equivalent of an API
314*90277196SAndroid Build Coastguard Worker       dependency expression, suitable for use in extension appendix
315*90277196SAndroid Build Coastguard Worker       metadata.
316*90277196SAndroid Build Coastguard Worker
317*90277196SAndroid Build Coastguard Worker     - dependency - the expression"""
318*90277196SAndroid Build Coastguard Worker
319*90277196SAndroid Build Coastguard Worker    parsed = dependencyExpr.parseString(dependency)
320*90277196SAndroid Build Coastguard Worker    return markupTraverse(parsed)
321*90277196SAndroid Build Coastguard Worker
322*90277196SAndroid Build Coastguard Workerif __name__ == "__main__":
323*90277196SAndroid Build Coastguard Worker    for str in [ 'VK_VERSION_1_0', 'cl_khr_extension_name', 'XR_VERSION_3_2', 'CL_VERSION_1_0' ]:
324*90277196SAndroid Build Coastguard Worker        print(f'{str} -> {conventions.formatVersionOrExtension(str)}')
325*90277196SAndroid Build Coastguard Worker    import sys
326*90277196SAndroid Build Coastguard Worker    sys.exit(0)
327*90277196SAndroid Build Coastguard Worker
328*90277196SAndroid Build Coastguard Worker    termdict = {
329*90277196SAndroid Build Coastguard Worker        'VK_VERSION_1_1' : True,
330*90277196SAndroid Build Coastguard Worker        'false' : False,
331*90277196SAndroid Build Coastguard Worker        'true' : True,
332*90277196SAndroid Build Coastguard Worker    }
333*90277196SAndroid Build Coastguard Worker    termSupported = lambda name: name in termdict and termdict[name]
334*90277196SAndroid Build Coastguard Worker
335*90277196SAndroid Build Coastguard Worker    def test(dependency, expected):
336*90277196SAndroid Build Coastguard Worker        val = False
337*90277196SAndroid Build Coastguard Worker        try:
338*90277196SAndroid Build Coastguard Worker            val = evaluateDependency(dependency, termSupported)
339*90277196SAndroid Build Coastguard Worker        except ParseException as pe:
340*90277196SAndroid Build Coastguard Worker            print(dependency, f'failed parse: {dependency}')
341*90277196SAndroid Build Coastguard Worker        except Exception as e:
342*90277196SAndroid Build Coastguard Worker            print(dependency, f'failed eval: {dependency}')
343*90277196SAndroid Build Coastguard Worker
344*90277196SAndroid Build Coastguard Worker        if val == expected:
345*90277196SAndroid Build Coastguard Worker            True
346*90277196SAndroid Build Coastguard Worker            # print(f'{dependency} = {val} (as expected)')
347*90277196SAndroid Build Coastguard Worker        else:
348*90277196SAndroid Build Coastguard Worker            print(f'{dependency} ERROR: {val} != {expected}')
349*90277196SAndroid Build Coastguard Worker
350*90277196SAndroid Build Coastguard Worker    # Verify expressions are evaluated left-to-right
351*90277196SAndroid Build Coastguard Worker
352*90277196SAndroid Build Coastguard Worker    test('false,false+false', False)
353*90277196SAndroid Build Coastguard Worker    test('false,false+true', False)
354*90277196SAndroid Build Coastguard Worker    test('false,true+false', False)
355*90277196SAndroid Build Coastguard Worker    test('false,true+true', True)
356*90277196SAndroid Build Coastguard Worker    test('true,false+false', False)
357*90277196SAndroid Build Coastguard Worker    test('true,false+true', True)
358*90277196SAndroid Build Coastguard Worker    test('true,true+false', False)
359*90277196SAndroid Build Coastguard Worker    test('true,true+true', True)
360*90277196SAndroid Build Coastguard Worker
361*90277196SAndroid Build Coastguard Worker    test('false,(false+false)', False)
362*90277196SAndroid Build Coastguard Worker    test('false,(false+true)', False)
363*90277196SAndroid Build Coastguard Worker    test('false,(true+false)', False)
364*90277196SAndroid Build Coastguard Worker    test('false,(true+true)', True)
365*90277196SAndroid Build Coastguard Worker    test('true,(false+false)', True)
366*90277196SAndroid Build Coastguard Worker    test('true,(false+true)', True)
367*90277196SAndroid Build Coastguard Worker    test('true,(true+false)', True)
368*90277196SAndroid Build Coastguard Worker    test('true,(true+true)', True)
369*90277196SAndroid Build Coastguard Worker
370*90277196SAndroid Build Coastguard Worker
371*90277196SAndroid Build Coastguard Worker    test('false+false,false', False)
372*90277196SAndroid Build Coastguard Worker    test('false+false,true', True)
373*90277196SAndroid Build Coastguard Worker    test('false+true,false', False)
374*90277196SAndroid Build Coastguard Worker    test('false+true,true', True)
375*90277196SAndroid Build Coastguard Worker    test('true+false,false', False)
376*90277196SAndroid Build Coastguard Worker    test('true+false,true', True)
377*90277196SAndroid Build Coastguard Worker    test('true+true,false', True)
378*90277196SAndroid Build Coastguard Worker    test('true+true,true', True)
379*90277196SAndroid Build Coastguard Worker
380*90277196SAndroid Build Coastguard Worker    test('false+(false,false)', False)
381*90277196SAndroid Build Coastguard Worker    test('false+(false,true)', False)
382*90277196SAndroid Build Coastguard Worker    test('false+(true,false)', False)
383*90277196SAndroid Build Coastguard Worker    test('false+(true,true)', False)
384*90277196SAndroid Build Coastguard Worker    test('true+(false,false)', False)
385*90277196SAndroid Build Coastguard Worker    test('true+(false,true)', True)
386*90277196SAndroid Build Coastguard Worker    test('true+(true,false)', True)
387*90277196SAndroid Build Coastguard Worker    test('true+(true,true)', True)
388*90277196SAndroid Build Coastguard Worker
389*90277196SAndroid Build Coastguard Worker    # Check formatting
390*90277196SAndroid Build Coastguard Worker    for dependency in [
391*90277196SAndroid Build Coastguard Worker        #'true',
392*90277196SAndroid Build Coastguard Worker        #'true+true+false',
393*90277196SAndroid Build Coastguard Worker        'true+false',
394*90277196SAndroid Build Coastguard Worker        'true+(true+false),(false,true)',
395*90277196SAndroid Build Coastguard Worker        #'true+((true+false),(false,true))',
396*90277196SAndroid Build Coastguard Worker        'VK_VERSION_1_0+VK_KHR_display',
397*90277196SAndroid Build Coastguard Worker        #'VK_VERSION_1_1+(true,false)',
398*90277196SAndroid Build Coastguard Worker    ]:
399*90277196SAndroid Build Coastguard Worker        print(f'expr = {dependency}\n{dependencyMarkup(dependency)}')
400*90277196SAndroid Build Coastguard Worker        print(f'  spec language = {dependencyLanguageSpecMacros(dependency)}')
401*90277196SAndroid Build Coastguard Worker        print(f'  comment language = {dependencyLanguageComment(dependency)}')
402*90277196SAndroid Build Coastguard Worker        print(f'  C language = {dependencyLanguageC(dependency)}')
403*90277196SAndroid Build Coastguard Worker        print(f'  names = {dependencyNames(dependency)}')
404*90277196SAndroid Build Coastguard Worker        print(f'  value = {evaluateDependency(dependency, termSupported)}')
405