# Copyright 2013, Big Switch Networks, Inc.
#
# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
# the following special exception:
#
# LOXI Exception
#
# As a special exception to the terms of the EPL, you may distribute libraries
# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
# that copyright and licensing notices generated by LoxiGen are not altered or removed
# from the LoxiGen Libraries and the notice provided below is (i) included in
# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
# documentation for the LoxiGen Libraries, if distributed in binary form.
#
# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
#
# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
# a copy of the EPL at:
#
# http://www.eclipse.org/legal/epl-v10.html
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# EPL for the specific language governing permissions and limitations
# under the EPL.

import pyparsing as P

kw = P.Keyword
s = P.Suppress
lit = P.Literal

# Useful for marking the type of a parse result (matches the empty string, but
# shows up in the result)
tag = lambda name: P.Empty().setParseAction(P.replaceWith(name))

word = P.Word(P.alphanums + '_')
integer = (
            P.Combine('0x' - P.Word('0123456789abcdefABCDEF') |
            P.Word('0123456789'))
          ).setParseAction(lambda x: int(x[0], 0))

identifier = word.copy().setName("identifier")

# Type names
scalar_type = word
array_type = P.Combine(word + lit('[') - P.Word(P.alphanums + '_') - lit(']'))
list_type = P.Combine(kw('list') - lit('(') - identifier - lit(')'))
any_type = (array_type | list_type | scalar_type).setName("type name")

# Structs
pad_member = P.Group(kw('pad') - s('(') - integer - s(')'))
type_member = P.Group(tag('type') + any_type + identifier + s('==') + integer)
data_member = P.Group(tag('data') + any_type - identifier)
struct_member = pad_member | type_member | data_member;
struct = kw('struct') - identifier - s('{') + \
         P.Group(P.ZeroOrMore(struct_member - s(';'))) + \
         s('}') - s(';')

# Enums
enum_member = P.Group(identifier + s('=') + integer)
enum_list = P.Forward()
enum_list << enum_member + P.Optional(s(',') + P.Optional(enum_list))
enum = kw('enum') - identifier - s('{') + \
         P.Group(P.Optional(enum_list)) + \
         s('}') - s(';')

# Metadata
metadata_key = P.Or(kw("version")).setName("metadata key")
metadata = tag('metadata') + s('#') - metadata_key - word

grammar = P.ZeroOrMore(P.Group(struct) | P.Group(enum) | P.Group(metadata))
grammar.ignore(P.cppStyleComment)

def parse(src):
    """
    Given an input string, return the AST.

    The AST is a low-level representation of the input. It changes frequently
    with the input file syntax. The frontend.py module transforms the AST
    into the OFInput represntation.
    """
    return grammar.parseString(src, parseAll=True).asList()
