docs: doxygen fix siphon under python3
[vpp.git] / doxygen / siphon / parsers.py
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at:
4 #
5 #     http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 # See the License for the specific language governing permissions and
11 # limitations under the License.
12
13 import html
14 import pyparsing as pp
15
16 # Some useful primitives
17 ident = pp.Word(pp.alphas + "_", pp.alphas + pp.nums + "_")
18 intNum = pp.Word(pp.nums)
19 hexNum = pp.Literal("0x") + pp.Word(pp.hexnums)
20 octalNum = pp.Literal("0") + pp.Word("01234567")
21 integer = (hexNum | octalNum | intNum) + \
22     pp.Optional(pp.Literal("ULL") | pp.Literal("LL") | pp.Literal("L"))
23 floatNum = pp.Regex(r'\d+(\.\d*)?([eE]\d+)?') + pp.Optional(pp.Literal("f"))
24 char = pp.Literal("'") + pp.Word(pp.printables, exact=1) + pp.Literal("'")
25 arrayIndex = integer | ident
26
27 lbracket = pp.Literal("(").suppress()
28 rbracket = pp.Literal(")").suppress()
29 lbrace = pp.Literal("{").suppress()
30 rbrace = pp.Literal("}").suppress()
31 comma = pp.Literal(",").suppress()
32 equals = pp.Literal("=").suppress()
33 dot = pp.Literal(".").suppress()
34 semicolon = pp.Literal(";").suppress()
35
36 # initializer := { [member = ] (variable | expression | { initializer } ) }
37 typeName = ident
38 varName = ident
39 typeSpec = pp.Optional("unsigned") + \
40            pp.oneOf("int long short float double char u8 i8 void") + \
41            pp.Optional(pp.Word("*"), default="")
42 typeCast = pp.Combine( "(" + ( typeSpec | typeName ) + ")" ).suppress()
43
44 string = pp.Combine(pp.OneOrMore(pp.QuotedString(quoteChar='"',
45     escChar='\\', multiline=True)), adjacent=False)
46 literal = pp.Optional(typeCast) + (integer | floatNum | char | string)
47 var = pp.Combine(pp.Optional(typeCast) + varName +
48     pp.Optional("[" + arrayIndex + "]"))
49
50 # This could be more complete, but suffices for our uses
51 expr = (literal | var)
52
53 """Parse and render a block of text into a Python dictionary."""
54 class Parser(object):
55     """Compiled PyParsing BNF"""
56     _parser = None
57
58     def __init__(self):
59         super(Parser, self).__init__()
60         self._parser = self.BNF()
61
62     def BNF(self):
63         raise NotImplementedError
64
65     def item(self, item):
66         raise NotImplementedError
67
68     def parse(self, input):
69         item = self._parser.parseString(input).asList()
70         return self.item(item)
71
72
73 """Parser for function-like macros - without the closing semi-colon."""
74 class ParserFunctionMacro(Parser):
75     def BNF(self):
76         # VLIB_CONFIG_FUNCTION (unix_config, "unix")
77         macroName = ident
78         params = pp.Group(pp.ZeroOrMore(expr + comma) + expr)
79         macroParams = lbracket + params + rbracket
80
81         return macroName + macroParams
82
83     def item(self, item):
84         r = {
85             "macro": item[0],
86             "name": item[1][1],
87             "function": item[1][0],
88         }
89
90         return r
91
92
93 """Parser for function-like macros with a closing semi-colon."""
94 class ParseFunctionMacroStmt(ParserFunctionMacro):
95     def BNF(self):
96         # VLIB_CONFIG_FUNCTION (unix_config, "unix");
97         function_macro = super(ParseFunctionMacroStmt, self).BNF()
98         mi = function_macro + semicolon
99         mi.ignore(pp.cppStyleComment)
100
101         return mi
102
103
104 """
105 Parser for our struct initializers which are composed from a
106 function-like macro, equals sign, and then a normal C struct initializer
107 block.
108 """
109 class MacroInitializer(ParserFunctionMacro):
110     def BNF(self):
111         # VLIB_CLI_COMMAND (show_sr_tunnel_command, static) = {
112         #    .path = "show sr tunnel",
113         #    .short_help = "show sr tunnel [name <sr-tunnel-name>]",
114         #    .function = show_sr_tunnel_fn,
115         # };
116         cs = pp.Forward()
117
118
119         member = pp.Combine(dot + varName + pp.Optional("[" + arrayIndex + "]"),
120             adjacent=False)
121         value = (expr | cs)
122
123         entry = pp.Group(pp.Optional(member + equals, default="") + value)
124         entries = (pp.ZeroOrMore(entry + comma) + entry + pp.Optional(comma)) | \
125                   (pp.ZeroOrMore(entry + comma))
126
127         cs << (lbrace + entries + rbrace)
128
129         macroName = ident
130         params = pp.Group(pp.ZeroOrMore(expr + comma) + expr)
131         macroParams = lbracket + params + rbracket
132
133         function_macro = super(MacroInitializer, self).BNF()
134         mi = function_macro + equals + pp.Group(cs) + semicolon
135         mi.ignore(pp.cppStyleComment)
136
137         return mi
138
139     def item(self, item):
140         r = {
141             "macro": item[0],
142             "name": item[1][0],
143             "params": item[2],
144             "value": {},
145         }
146
147         for param in item[2]:
148             r["value"][param[0]] = html.escape(param[1])
149
150         return r