| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # Copyright 2013 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 """Generates a syntax tree from a Mojo IDL file.""" | |
| 7 | |
| 8 | |
| 9 import sys | |
| 10 import os.path | |
| 11 | |
| 12 | |
| 13 # Try to load the ply module, if not, then assume it is in the third_party | |
| 14 # directory. | |
| 15 try: | |
| 16 # Disable lint check which fails to find the ply module. | |
| 17 # pylint: disable=F0401 | |
| 18 from ply import lex | |
| 19 from ply import yacc | |
| 20 except ImportError: | |
| 21 module_path, module_name = os.path.split(__file__) | |
| 22 third_party = os.path.join( | |
| 23 module_path, os.pardir, os.pardir, os.pardir, os.pardir, 'third_party') | |
| 24 sys.path.append(third_party) | |
| 25 # pylint: disable=F0401 | |
| 26 from ply import lex | |
| 27 from ply import yacc | |
| 28 | |
| 29 | |
| 30 def ListFromConcat(*items): | |
| 31 """Generate list by concatenating inputs""" | |
| 32 itemsout = [] | |
| 33 for item in items: | |
| 34 if item is None: | |
| 35 continue | |
| 36 if type(item) is not type([]): | |
| 37 itemsout.append(item) | |
| 38 else: | |
| 39 itemsout.extend(item) | |
| 40 | |
| 41 return itemsout | |
| 42 | |
| 43 | |
| 44 class Lexer(object): | |
| 45 | |
| 46 # This field is required by lex to specify the complete list of valid tokens. | |
| 47 tokens = ( | |
| 48 'NAME', | |
| 49 'NUMBER', | |
| 50 | |
| 51 'ARRAY', | |
| 52 'ORDINAL', | |
| 53 | |
| 54 'MODULE', | |
| 55 'STRUCT', | |
| 56 'INTERFACE', | |
| 57 'VOID', | |
| 58 | |
| 59 'LCURLY', | |
| 60 'RCURLY', | |
| 61 'LPAREN', | |
| 62 'RPAREN', | |
| 63 'LBRACKET', | |
| 64 'RBRACKET', | |
| 65 'COMMA', | |
| 66 'SEMICOLON', | |
| 67 'EQUALS', | |
| 68 ) | |
| 69 | |
| 70 t_LCURLY = r'{' | |
| 71 t_RCURLY = r'}' | |
| 72 t_LPAREN = r'\(' | |
| 73 t_RPAREN = r'\)' | |
| 74 t_LBRACKET = r'\[' | |
| 75 t_RBRACKET = r'\]' | |
| 76 t_COMMA = r',' | |
| 77 t_SEMICOLON = r';' | |
| 78 t_EQUALS = r'=' | |
| 79 t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' | |
| 80 t_ARRAY = r'[a-zA-Z_][a-zA-Z0-9_]*\[\]' | |
| 81 t_NUMBER = r'\d+' | |
| 82 t_ORDINAL = r'@[0-9]*' | |
| 83 | |
| 84 def t_MODULE(self, t): | |
| 85 r'module' | |
| 86 return t | |
| 87 | |
| 88 def t_STRUCT(self, t): | |
| 89 r'struct' | |
| 90 return t | |
| 91 | |
| 92 def t_INTERFACE(self, t): | |
| 93 r'interface' | |
| 94 return t | |
| 95 | |
| 96 def t_VOID(self, t): | |
| 97 r'void' | |
| 98 return t | |
| 99 | |
| 100 # Ignore C and C++ style comments | |
| 101 def t_COMMENT(self, t): | |
| 102 r'(/\*(.|\n)*?\*/)|(//.*(\n[ \t]*//.*)*)' | |
| 103 pass | |
| 104 | |
| 105 # Ignored characters | |
| 106 t_ignore = " \t" | |
| 107 | |
| 108 def t_newline(self, t): | |
| 109 r'\n+' | |
| 110 t.lexer.lineno += t.value.count("\n") | |
| 111 | |
| 112 def t_error(self, t): | |
| 113 print("Illegal character '%s'" % t.value[0]) | |
| 114 t.lexer.skip(1) | |
| 115 | |
| 116 | |
| 117 class Parser(object): | |
| 118 | |
| 119 def __init__(self, lexer): | |
| 120 self.tokens = lexer.tokens | |
| 121 | |
| 122 def p_module(self, p): | |
| 123 """module : MODULE NAME LCURLY definitions RCURLY""" | |
| 124 p[0] = ('MODULE', p[2], p[4]) | |
| 125 | |
| 126 def p_definitions(self, p): | |
| 127 """definitions : definition definitions | |
| 128 |""" | |
| 129 if len(p) > 1: | |
| 130 p[0] = ListFromConcat(p[1], p[2]) | |
| 131 | |
| 132 def p_definition(self, p): | |
| 133 """definition : struct | |
| 134 | interface""" | |
| 135 p[0] = p[1] | |
| 136 | |
| 137 def p_attribute_section(self, p): | |
| 138 """attribute_section : LBRACKET attributes RBRACKET | |
| 139 | """ | |
| 140 if len(p) > 3: | |
| 141 p[0] = p[2] | |
| 142 | |
| 143 def p_attributes(self, p): | |
| 144 """attributes : attribute | |
| 145 | attribute COMMA attributes | |
| 146 | """ | |
| 147 if len(p) == 2: | |
| 148 p[0] = ListFromConcat(p[1]) | |
| 149 elif len(p) > 3: | |
| 150 p[0] = ListFromConcat(p[1], p[3]) | |
| 151 | |
| 152 def p_attribute(self, p): | |
| 153 """attribute : NAME EQUALS NUMBER | |
| 154 | NAME EQUALS NAME""" | |
| 155 p[0] = ('ATTRIBUTE', p[1], p[3]) | |
| 156 | |
| 157 def p_struct(self, p): | |
| 158 """struct : attribute_section STRUCT NAME LCURLY fields RCURLY SEMICOLON""" | |
| 159 p[0] = ('STRUCT', p[3], p[1], p[5]) | |
| 160 | |
| 161 def p_fields(self, p): | |
| 162 """fields : field fields | |
| 163 |""" | |
| 164 if len(p) > 1: | |
| 165 p[0] = ListFromConcat(p[1], p[2]) | |
| 166 | |
| 167 def p_field(self, p): | |
| 168 """field : typename NAME ordinal SEMICOLON""" | |
| 169 p[0] = ('FIELD', p[1], p[2], p[3]) | |
| 170 | |
| 171 def p_interface(self, p): | |
| 172 """interface : attribute_section INTERFACE NAME LCURLY methods RCURLY SEMICO
LON""" | |
| 173 p[0] = ('INTERFACE', p[3], p[1], p[5]) | |
| 174 | |
| 175 def p_methods(self, p): | |
| 176 """methods : method methods | |
| 177 | """ | |
| 178 if len(p) > 1: | |
| 179 p[0] = ListFromConcat(p[1], p[2]) | |
| 180 | |
| 181 def p_method(self, p): | |
| 182 """method : VOID NAME LPAREN parameters RPAREN ordinal SEMICOLON""" | |
| 183 p[0] = ('METHOD', p[2], p[4], p[6]) | |
| 184 | |
| 185 def p_parameters(self, p): | |
| 186 """parameters : parameter | |
| 187 | parameter COMMA parameters | |
| 188 | """ | |
| 189 if len(p) == 1: | |
| 190 p[0] = [] | |
| 191 elif len(p) == 2: | |
| 192 p[0] = ListFromConcat(p[1]) | |
| 193 elif len(p) > 3: | |
| 194 p[0] = ListFromConcat(p[1], p[3]) | |
| 195 | |
| 196 def p_parameter(self, p): | |
| 197 """parameter : typename NAME ordinal""" | |
| 198 p[0] = ('PARAM', p[1], p[2], p[3]) | |
| 199 | |
| 200 def p_typename(self, p): | |
| 201 """typename : NAME | |
| 202 | ARRAY""" | |
| 203 p[0] = p[1] | |
| 204 | |
| 205 def p_ordinal(self, p): | |
| 206 """ordinal : ORDINAL | |
| 207 | """ | |
| 208 if len(p) > 1: | |
| 209 p[0] = p[1] | |
| 210 | |
| 211 def p_error(self, e): | |
| 212 print('error: %s'%e) | |
| 213 | |
| 214 | |
| 215 def Parse(filename): | |
| 216 lexer = Lexer() | |
| 217 parser = Parser(lexer) | |
| 218 | |
| 219 lex.lex(object=lexer) | |
| 220 yacc.yacc(module=parser, debug=0, write_tables=0) | |
| 221 | |
| 222 tree = yacc.parse(open(filename).read()) | |
| 223 return tree | |
| 224 | |
| 225 | |
| 226 def Main(): | |
| 227 if len(sys.argv) < 2: | |
| 228 print("usage: %s filename" % (sys.argv[0])) | |
| 229 sys.exit(1) | |
| 230 tree = Parse(filename=sys.argv[1]) | |
| 231 print(tree) | |
| 232 | |
| 233 | |
| 234 if __name__ == '__main__': | |
| 235 Main() | |
| OLD | NEW |