| Index: mojo/public/bindings/parser/mojo_parser.py
|
| diff --git a/mojo/public/bindings/parser/mojo_parser.py b/mojo/public/bindings/parser/mojo_parser.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..a967fbcb528b7572dab62680b4d5764642efe9d5
|
| --- /dev/null
|
| +++ b/mojo/public/bindings/parser/mojo_parser.py
|
| @@ -0,0 +1,232 @@
|
| +#!/usr/bin/env python
|
| +# Copyright 2013 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +"""Generates a syntax tree from a Mojo IDL file."""
|
| +
|
| +
|
| +import sys
|
| +import os.path
|
| +
|
| +
|
| +# Try to load the ply module, if not, then assume it is in the third_party
|
| +# directory.
|
| +try:
|
| + # Disable lint check which fails to find the ply module.
|
| + # pylint: disable=F0401
|
| + from ply import lex
|
| + from ply import yacc
|
| +except ImportError:
|
| + module_path, module_name = os.path.split(__file__)
|
| + third_party = os.path.join(
|
| + module_path, os.pardir, os.pardir, os.pardir, os.pardir, 'third_party')
|
| + sys.path.append(third_party)
|
| + # pylint: disable=F0401
|
| + from ply import lex
|
| + from ply import yacc
|
| +
|
| +
|
| +def ListFromConcat(*items):
|
| + """Generate list by concatenating inputs"""
|
| + itemsout = []
|
| + for item in items:
|
| + if item is None:
|
| + continue
|
| + if type(item) is not type([]):
|
| + itemsout.append(item)
|
| + else:
|
| + itemsout.extend(item)
|
| +
|
| + return itemsout
|
| +
|
| +
|
| +class Lexer(object):
|
| +
|
| + # This field is required by lex to specify the complete list of valid tokens.
|
| + tokens = (
|
| + 'NAME',
|
| + 'NUMBER',
|
| +
|
| + 'ARRAY',
|
| + 'ORDINAL',
|
| +
|
| + 'MODULE',
|
| + 'STRUCT',
|
| + 'INTERFACE',
|
| + 'VOID',
|
| +
|
| + 'LCURLY',
|
| + 'RCURLY',
|
| + 'LPAREN',
|
| + 'RPAREN',
|
| + 'LBRACKET',
|
| + 'RBRACKET',
|
| + 'COMMA',
|
| + 'SEMICOLON',
|
| + 'EQUALS',
|
| + )
|
| +
|
| + t_LCURLY = r'{'
|
| + t_RCURLY = r'}'
|
| + t_LPAREN = r'\('
|
| + t_RPAREN = r'\)'
|
| + t_LBRACKET = r'\['
|
| + t_RBRACKET = r'\]'
|
| + t_COMMA = r','
|
| + t_SEMICOLON = r';'
|
| + t_EQUALS = r'='
|
| + t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
|
| + t_ARRAY = r'[a-zA-Z_][a-zA-Z0-9_]*\[\]'
|
| + t_NUMBER = r'\d+'
|
| + t_ORDINAL = r'@[0-9]*'
|
| +
|
| + def t_MODULE(self, t):
|
| + r'module'
|
| + return t
|
| +
|
| + def t_STRUCT(self, t):
|
| + r'struct'
|
| + return t
|
| +
|
| + def t_INTERFACE(self, t):
|
| + r'interface'
|
| + return t
|
| +
|
| + def t_VOID(self, t):
|
| + r'void'
|
| + return t
|
| +
|
| + # Ignore C and C++ style comments
|
| + def t_COMMENT(self, t):
|
| + r'(/\*(.|\n)*?\*/)|(//.*(\n[ \t]*//.*)*)'
|
| + pass
|
| +
|
| + # Ignored characters
|
| + t_ignore = " \t"
|
| +
|
| + def t_newline(self, t):
|
| + r'\n+'
|
| + t.lexer.lineno += t.value.count("\n")
|
| +
|
| + def t_error(self, t):
|
| + print("Illegal character '%s'" % t.value[0])
|
| + t.lexer.skip(1)
|
| +
|
| +
|
| +class Parser(object):
|
| +
|
| + def __init__(self, lexer):
|
| + self.tokens = lexer.tokens
|
| +
|
| + def p_module(self, p):
|
| + """module : MODULE NAME LCURLY definitions RCURLY"""
|
| + p[0] = ('MODULE', p[2], p[4])
|
| +
|
| + def p_definitions(self, p):
|
| + """definitions : definition definitions
|
| + |"""
|
| + if len(p) > 1:
|
| + p[0] = ListFromConcat(p[1], p[2])
|
| +
|
| + def p_definition(self, p):
|
| + """definition : struct
|
| + | interface"""
|
| + p[0] = p[1]
|
| +
|
| + def p_attribute_section(self, p):
|
| + """attribute_section : LBRACKET attributes RBRACKET
|
| + | """
|
| + if len(p) > 3:
|
| + p[0] = p[2]
|
| +
|
| + def p_attributes(self, p):
|
| + """attributes : attribute
|
| + | attribute COMMA attributes
|
| + | """
|
| + if len(p) == 2:
|
| + p[0] = ListFromConcat(p[1])
|
| + elif len(p) > 3:
|
| + p[0] = ListFromConcat(p[1], p[3])
|
| +
|
| + def p_attribute(self, p):
|
| + """attribute : NAME EQUALS NUMBER"""
|
| + p[0] = ('ATTRIBUTE', p[1], p[3])
|
| +
|
| + def p_struct(self, p):
|
| + """struct : attribute_section STRUCT NAME LCURLY fields RCURLY SEMICOLON"""
|
| + p[0] = ('STRUCT', p[3], p[1], p[5])
|
| +
|
| + def p_fields(self, p):
|
| + """fields : field fields
|
| + |"""
|
| + if len(p) > 1:
|
| + p[0] = ListFromConcat(p[1], p[2])
|
| +
|
| + def p_field(self, p):
|
| + """field : typename NAME ordinal SEMICOLON"""
|
| + p[0] = ('FIELD', p[1], p[2], p[3])
|
| +
|
| + def p_interface(self, p):
|
| + """interface : INTERFACE NAME LCURLY methods RCURLY SEMICOLON"""
|
| + p[0] = ('INTERFACE', p[2], p[4])
|
| +
|
| + def p_methods(self, p):
|
| + """methods : method methods
|
| + | """
|
| + if len(p) > 1:
|
| + p[0] = ListFromConcat(p[1], p[2])
|
| +
|
| + def p_method(self, p):
|
| + """method : VOID NAME LPAREN parameters RPAREN ordinal SEMICOLON"""
|
| + p[0] = ('METHOD', p[2], p[4], p[6])
|
| +
|
| + def p_parameters(self, p):
|
| + """parameters : parameter
|
| + | parameter COMMA parameters
|
| + | """
|
| + if len(p) == 2:
|
| + p[0] = p[1]
|
| + elif len(p) > 3:
|
| + p[0] = ListFromConcat(p[1], p[3])
|
| +
|
| + def p_parameter(self, p):
|
| + """parameter : typename NAME ordinal"""
|
| + p[0] = ('PARAM', p[1], p[2], p[3])
|
| +
|
| + def p_typename(self, p):
|
| + """typename : NAME
|
| + | ARRAY"""
|
| + p[0] = p[1]
|
| +
|
| + def p_ordinal(self, p):
|
| + """ordinal : ORDINAL
|
| + | """
|
| + if len(p) > 1:
|
| + p[0] = p[1]
|
| +
|
| + def p_error(self, e):
|
| + print('error: %s'%e)
|
| +
|
| +
|
| +def Parse(filename):
|
| + lexer = Lexer()
|
| + parser = Parser(lexer)
|
| +
|
| + lex.lex(object=lexer)
|
| + yacc.yacc(module=parser, debug=0, write_tables=0)
|
| +
|
| + tree = yacc.parse(open(filename).read())
|
| + return tree
|
| +
|
| +
|
| +def Main():
|
| + if len(sys.argv) < 2:
|
| + print("usage: %s filename" % (sys.argv[0]))
|
| + sys.exit(1)
|
| + tree = Parse(filename=sys.argv[1])
|
| + print(tree)
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + Main()
|
|
|