blob: f2cf4b008de7626ea8b86085b89397a74135e82f [file] [log] [blame]
Rich Lanea06d0c32013-03-25 08:52:03 -07001# Copyright 2013, Big Switch Networks, Inc.
2#
3# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
4# the following special exception:
5#
6# LOXI Exception
7#
8# As a special exception to the terms of the EPL, you may distribute libraries
9# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
10# that copyright and licensing notices generated by LoxiGen are not altered or removed
11# from the LoxiGen Libraries and the notice provided below is (i) included in
12# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
13# documentation for the LoxiGen Libraries, if distributed in binary form.
14#
15# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
16#
17# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
18# a copy of the EPL at:
19#
20# http://www.eclipse.org/legal/epl-v10.html
21#
22# Unless required by applicable law or agreed to in writing, software
23# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
24# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
25# EPL for the specific language governing permissions and limitations
26# under the EPL.
27
28import pyparsing as P
29
30kw = P.Keyword
31s = P.Suppress
32lit = P.Literal
33
34# Useful for marking the type of a parse result (matches the empty string, but
35# shows up in the result)
36tag = lambda name: P.Empty().setParseAction(P.replaceWith(name))
37
38word = P.Word(P.alphanums + '_')
Rich Lanefe735bc2013-04-08 16:58:49 -070039integer = (
40 P.Combine('0x' - P.Word('0123456789abcdefABCDEF') |
41 P.Word('0123456789'))
42 ).setParseAction(lambda x: int(x[0], 0))
Rich Lanea06d0c32013-03-25 08:52:03 -070043
44identifier = word.copy().setName("identifier")
45
46# Type names
Andreas Wundsamdfeb5942013-09-19 13:07:49 -070047enum_type = kw("enum") - word
48scalar_type = tag("scalar") + word
49array_type = tag("array") + P.Combine(word + lit('[') - P.Word(P.alphanums + '_') - lit(']'))
50list_type = tag("list") + P.Combine(kw('list') - lit('(') - identifier - lit(')'))
51any_type = P.Group(enum_type | array_type | list_type | scalar_type).setName("type name")
Rich Lanea06d0c32013-03-25 08:52:03 -070052
53# Structs
Rich Lanee4d04ea2013-05-09 11:27:06 -070054pad_member = P.Group(kw('pad') - s('(') - integer - s(')'))
Andreas Wundsam780e0c92013-08-02 17:48:27 -070055discriminator_member = P.Group(tag('discriminator') + any_type + identifier + s('==') + s('?'))
Rich Lane32142872013-05-09 21:16:47 -070056type_member = P.Group(tag('type') + any_type + identifier + s('==') + integer)
Rich Lanef424e972013-05-09 21:00:13 -070057data_member = P.Group(tag('data') + any_type - identifier)
Andreas Wundsamfef7d5f2013-08-01 22:15:44 -070058
59struct_param_name = kw("align")
Andreas Wundsamdfeb5942013-09-19 13:07:49 -070060struct_param = P.Group(struct_param_name - s('=') - word)
Andreas Wundsamfef7d5f2013-08-01 22:15:44 -070061struct_param_list = P.Forward()
62struct_param_list << struct_param + P.Optional(s(',') - P.Optional(struct_param_list))
63
Andreas Wundsam780e0c92013-08-02 17:48:27 -070064struct_member = pad_member | type_member | discriminator_member | data_member;
Rich Lanebd431502013-06-21 16:30:20 -070065parent = (s(':') - identifier) | tag(None)
Andreas Wundsamcd2d5252013-08-02 13:35:57 -070066struct = kw('struct') - identifier - P.Group(P.Optional(s('(') - struct_param_list - s(')'))) - parent - s('{') + \
Rich Lanee4d04ea2013-05-09 11:27:06 -070067 P.Group(P.ZeroOrMore(struct_member - s(';'))) + \
Rich Lanea06d0c32013-03-25 08:52:03 -070068 s('}') - s(';')
69
Rich Lane517506c2013-04-08 14:08:31 -070070# Enums
Andreas Wundsam4ee51462013-07-30 11:00:37 -070071enum_param_name = kw("wire_type") | kw("bitmask") | kw("complete")
Andreas Wundsamdfeb5942013-09-19 13:07:49 -070072enum_param = P.Group(enum_param_name - s('=') - word)
Andreas Wundsam4ee51462013-07-30 11:00:37 -070073enum_param_list = P.Forward()
74enum_param_list << enum_param + P.Optional(s(',') + P.Optional(enum_param_list))
75
76enum_member_param_name = kw("virtual")
Andreas Wundsamdfeb5942013-09-19 13:07:49 -070077enum_member_param = P.Group(enum_member_param_name - s('=') - word)
Andreas Wundsam4ee51462013-07-30 11:00:37 -070078enum_member_param_list = P.Forward()
79enum_member_param_list << enum_member_param + P.Optional(s(',') + P.Optional(enum_member_param_list))
80
81enum_member = P.Group(identifier - P.Group(P.Optional(s('(') - enum_member_param_list - s(')'))) - s('=') + integer)
Rich Lane517506c2013-04-08 14:08:31 -070082enum_list = P.Forward()
83enum_list << enum_member + P.Optional(s(',') + P.Optional(enum_list))
Andreas Wundsam4ee51462013-07-30 11:00:37 -070084enum = kw('enum') - identifier - P.Group(P.Optional(s('(') - enum_param_list - s(')'))) - s('{') + \
Rich Lane517506c2013-04-08 14:08:31 -070085 P.Group(P.Optional(enum_list)) + \
86 s('}') - s(';')
87
Rich Lanea06d0c32013-03-25 08:52:03 -070088# Metadata
89metadata_key = P.Or(kw("version")).setName("metadata key")
90metadata = tag('metadata') + s('#') - metadata_key - word
91
Rich Lane517506c2013-04-08 14:08:31 -070092grammar = P.ZeroOrMore(P.Group(struct) | P.Group(enum) | P.Group(metadata))
Rich Lanea06d0c32013-03-25 08:52:03 -070093grammar.ignore(P.cppStyleComment)
94
95def parse(src):
Rich Lane43b2a902013-05-09 13:47:07 -070096 """
97 Given an input string, return the AST.
98
99 The AST is a low-level representation of the input. It changes frequently
100 with the input file syntax. The frontend.py module transforms the AST
101 into the OFInput represntation.
102 """
103 return grammar.parseString(src, parseAll=True).asList()