| OLD | NEW | 
 | (Empty) | 
|    1 #!/usr/bin/python |  | 
|    2 # Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file |  | 
|    3 # for details. All rights reserved. Use of this source code is governed by a |  | 
|    4 # BSD-style license that can be found in the LICENSE file. |  | 
|    5  |  | 
|    6 import re |  | 
|    7 import subprocess |  | 
|    8 import tempfile |  | 
|    9  |  | 
|   10 from pegparser import * |  | 
|   11  |  | 
|   12 # IDL grammar variants. |  | 
|   13 WEBIDL_SYNTAX = 0 |  | 
|   14 WEBKIT_SYNTAX = 1 |  | 
|   15 FREMONTCUT_SYNTAX = 2 |  | 
|   16  |  | 
|   17  |  | 
|   18 class IDLParser(object): |  | 
|   19   """IDLParser is a PEG based IDL files parser.""" |  | 
|   20  |  | 
|   21   def __init__(self, syntax=WEBIDL_SYNTAX): |  | 
|   22     """Constructor. |  | 
|   23  |  | 
|   24     Initializes the IDLParser by defining the grammar and initializing |  | 
|   25     a PEGParserinstance. |  | 
|   26  |  | 
|   27     Args: |  | 
|   28       syntax -- supports either WEBIDL_SYNTAX (0) or WEBKIT_SYNTAX (1) |  | 
|   29     """ |  | 
|   30     self._syntax = syntax |  | 
|   31     self._pegparser = PegParser(self._idl_grammar(), |  | 
|   32       self._whitespace_grammar(), |  | 
|   33       strings_are_tokens=True) |  | 
|   34  |  | 
|   35   def _idl_grammar(self): |  | 
|   36     """Returns the PEG grammar for IDL parsing.""" |  | 
|   37  |  | 
|   38     # utilities: |  | 
|   39     def syntax_switch(w3c_syntax, webkit_syntax, fremontcut_syntax=None): |  | 
|   40       """Returns w3c_syntax or web_syntax, depending on the current |  | 
|   41       configuration. |  | 
|   42       """ |  | 
|   43       if self._syntax == WEBIDL_SYNTAX: |  | 
|   44         return w3c_syntax |  | 
|   45       elif self._syntax == WEBKIT_SYNTAX: |  | 
|   46         return webkit_syntax |  | 
|   47       elif self._syntax == FREMONTCUT_SYNTAX: |  | 
|   48         if fremontcut_syntax is not None: |  | 
|   49           return fremontcut_syntax |  | 
|   50         return w3c_syntax |  | 
|   51       else: |  | 
|   52         raise RuntimeError('unsupported IDL syntax %s' % syntax) |  | 
|   53  |  | 
|   54     # The following grammar is based on the Web IDL's LL(1) grammar |  | 
|   55     # (specified in: http://dev.w3.org/2006/webapi/WebIDL/#idl-grammar). |  | 
|   56     # It is adjusted to PEG grammar, as well as to also support |  | 
|   57     # WebKit IDL and FremontCut grammar. |  | 
|   58  |  | 
|   59     ###################### BEGIN GRAMMAR ##################### |  | 
|   60  |  | 
|   61     def Id(): |  | 
|   62       return re.compile(r'[\w\_]+') |  | 
|   63  |  | 
|   64     def _Definitions(): |  | 
|   65       return MAYBE(MANY(_Definition)) |  | 
|   66  |  | 
|   67     def _Definition(): |  | 
|   68       return syntax_switch( |  | 
|   69         # Web IDL: |  | 
|   70         OR(Module, Interface, ExceptionDef, TypeDef, ImplStmt, |  | 
|   71            ValueTypeDef, Const), |  | 
|   72         # WebKit: |  | 
|   73         OR(Module, Interface)) |  | 
|   74  |  | 
|   75     def Module(): |  | 
|   76       return syntax_switch( |  | 
|   77         # Web IDL: |  | 
|   78         [MAYBE(ExtAttrs), 'module', Id, '{', _Definitions, '}', |  | 
|   79          MAYBE(';')], |  | 
|   80         # WebKit: |  | 
|   81         ['module', MAYBE(ExtAttrs), Id, '{', _Definitions, '}', |  | 
|   82          MAYBE(';')], |  | 
|   83         # FremontCut: |  | 
|   84         [MAYBE(_Annotations), MAYBE(ExtAttrs), 'module', Id, |  | 
|   85          '{', _Definitions, '}', MAYBE(';')]) |  | 
|   86  |  | 
|   87     def Interface(): |  | 
|   88       return syntax_switch( |  | 
|   89         # Web IDL: |  | 
|   90         [MAYBE(ExtAttrs), 'interface', Id, MAYBE(_ParentInterfaces), |  | 
|   91          MAYBE(['{', MAYBE(MANY(_Member)), '}']), ';'], |  | 
|   92         # WebKit: |  | 
|   93         ['interface', MAYBE(ExtAttrs), Id, MAYBE(_ParentInterfaces), |  | 
|   94          MAYBE(['{', MAYBE(MANY(_Member)), '}']), MAYBE(';')], |  | 
|   95         # FremontCut: |  | 
|   96         [MAYBE(_Annotations), MAYBE(ExtAttrs), 'interface', |  | 
|   97          Id, MAYBE(_ParentInterfaces), MAYBE(['{', MAYBE(MANY(_Member)), |  | 
|   98          '}']), ';']) |  | 
|   99  |  | 
|  100     def _Member(): |  | 
|  101       return syntax_switch( |  | 
|  102         # Web IDL: |  | 
|  103         OR(Const, Attribute, Operation, ExtAttrs), |  | 
|  104         # WebKit: |  | 
|  105         OR(Const, Attribute, Operation), |  | 
|  106         # FremontCut: |  | 
|  107         OR(Const, Attribute, Operation)) |  | 
|  108  |  | 
|  109     # Interface inheritance: |  | 
|  110     def _ParentInterfaces(): |  | 
|  111       return [':', MANY(ParentInterface, separator=',')] |  | 
|  112  |  | 
|  113     def ParentInterface(): |  | 
|  114       return syntax_switch( |  | 
|  115         # Web IDL: |  | 
|  116         [InterfaceType], |  | 
|  117         # WebKit: |  | 
|  118         [InterfaceType], |  | 
|  119         # FremontCut: |  | 
|  120         [MAYBE(_Annotations), InterfaceType]) |  | 
|  121  |  | 
|  122     # TypeDef (Web IDL): |  | 
|  123     def TypeDef(): |  | 
|  124       return ['typedef', Type, Id, ';'] |  | 
|  125  |  | 
|  126     # TypeDef (Old-school W3C IDLs) |  | 
|  127     def ValueTypeDef(): |  | 
|  128       return ['valuetype', Id, Type, ';'] |  | 
|  129  |  | 
|  130     # Implements Statement (Web IDL): |  | 
|  131     def ImplStmt(): |  | 
|  132       return [ImplStmtImplementor, 'implements', ImplStmtImplemented, |  | 
|  133           ';'] |  | 
|  134  |  | 
|  135     def ImplStmtImplementor(): |  | 
|  136       return ScopedName |  | 
|  137  |  | 
|  138     def ImplStmtImplemented(): |  | 
|  139       return ScopedName |  | 
|  140  |  | 
|  141     # Constants: |  | 
|  142     def Const(): |  | 
|  143       return syntax_switch( |  | 
|  144         # Web IDL: |  | 
|  145         [MAYBE(ExtAttrs), 'const', Type, Id, '=', ConstExpr, ';'], |  | 
|  146         # WebKit: |  | 
|  147         [MAYBE(ExtAttrs), 'const', Type, Id, '=', ConstExpr, ';'], |  | 
|  148         # FremontCut: |  | 
|  149         [MAYBE(_Annotations), MAYBE(ExtAttrs), 'const', Type, Id, '=', |  | 
|  150          ConstExpr, ';']) |  | 
|  151  |  | 
|  152     def ConstExpr(): |  | 
|  153       return OR(_BooleanLiteral, |  | 
|  154             _IntegerLiteral, |  | 
|  155             _FloatLiteral) |  | 
|  156  |  | 
|  157     def _BooleanLiteral(): |  | 
|  158       return re.compile(r'true|false') |  | 
|  159  |  | 
|  160     def _IntegerLiteral(): |  | 
|  161       return OR(re.compile(r'(0x)?[0-9ABCDEF]+'), |  | 
|  162             re.compile(r'[0-9]+')) |  | 
|  163  |  | 
|  164     def _FloatLiteral(): |  | 
|  165       return re.compile(r'[0-9]+\.[0-9]*') |  | 
|  166  |  | 
|  167     # Attributes: |  | 
|  168     def Attribute(): |  | 
|  169       return syntax_switch( |  | 
|  170         # Web IDL: |  | 
|  171         [MAYBE(ExtAttrs), MAYBE(Stringifier), MAYBE(ReadOnly), |  | 
|  172          'attribute', Type, Id, MAYBE(_AttrRaises), ';'], |  | 
|  173         # WebKit: |  | 
|  174         [MAYBE(Stringifier), MAYBE(ReadOnly), 'attribute', |  | 
|  175          MAYBE(ExtAttrs), Type, Id, MAYBE(_AttrRaises), ';'], |  | 
|  176         # FremontCut: |  | 
|  177         [MAYBE(_Annotations), MAYBE(ExtAttrs), |  | 
|  178          MAYBE(_AttrGetterSetter), MAYBE(Stringifier), MAYBE(ReadOnly), |  | 
|  179          'attribute', Type, Id, MAYBE(_AttrRaises), ';']) |  | 
|  180  |  | 
|  181     def _AttrRaises(): |  | 
|  182       return syntax_switch( |  | 
|  183         # Web IDL: |  | 
|  184         MANY(OR(GetRaises, SetRaises)), |  | 
|  185         # WebKit: |  | 
|  186         MANY(OR(GetRaises, SetRaises, Raises), separator=',')) |  | 
|  187  |  | 
|  188     # Special fremontcut feature: |  | 
|  189     def _AttrGetterSetter(): |  | 
|  190       return OR(AttrGetter, AttrSetter) |  | 
|  191  |  | 
|  192     def AttrGetter(): |  | 
|  193       return 'getter' |  | 
|  194  |  | 
|  195     def AttrSetter(): |  | 
|  196       return 'setter' |  | 
|  197  |  | 
|  198     def ReadOnly(): |  | 
|  199       return 'readonly' |  | 
|  200  |  | 
|  201     def GetRaises(): |  | 
|  202       return syntax_switch( |  | 
|  203         # Web IDL: |  | 
|  204         ['getraises', '(', _ScopedNames, ')'], |  | 
|  205         # WebKit: |  | 
|  206         ['getter', 'raises', '(', _ScopedNames, ')']) |  | 
|  207  |  | 
|  208     def SetRaises(): |  | 
|  209       return syntax_switch( |  | 
|  210         # Web IDL: |  | 
|  211         ['setraises', '(', _ScopedNames, ')'], |  | 
|  212         # WebKit: |  | 
|  213         ['setter', 'raises', '(', _ScopedNames, ')']) |  | 
|  214  |  | 
|  215     # Operation: |  | 
|  216     def Operation(): |  | 
|  217       return syntax_switch( |  | 
|  218         # Web IDL: |  | 
|  219         [MAYBE(ExtAttrs), MAYBE(Static), MAYBE(Stringifier), MAYBE(_Specials), |  | 
|  220          ReturnType, MAYBE(Id), '(', _Arguments, ')', MAYBE(Raises), |  | 
|  221          ';'], |  | 
|  222         # WebKit: |  | 
|  223         [MAYBE(ExtAttrs), MAYBE(Static), |  | 
|  224          ReturnType, MAYBE(Id), '(', _Arguments, ')', |  | 
|  225          MAYBE(Raises), ';'], |  | 
|  226         # FremontCut: |  | 
|  227         [MAYBE(_Annotations), MAYBE(ExtAttrs), MAYBE(Static), MAYBE(Stringifier)
     , |  | 
|  228          MAYBE(_Specials), ReturnType, MAYBE(Id), '(', _Arguments, ')', |  | 
|  229          MAYBE(Raises), ';']) |  | 
|  230  |  | 
|  231     def Static(): |  | 
|  232       return 'static' |  | 
|  233  |  | 
|  234     def _Specials(): |  | 
|  235       return MANY(Special) |  | 
|  236  |  | 
|  237     def Special(): |  | 
|  238       return re.compile(r'getter|setter|creator|deleter|caller') |  | 
|  239  |  | 
|  240     def Stringifier(): |  | 
|  241       return 'stringifier' |  | 
|  242  |  | 
|  243     def Raises(): |  | 
|  244       return ['raises', '(', _ScopedNames, ')'] |  | 
|  245  |  | 
|  246     # Operation arguments: |  | 
|  247     def _Arguments(): |  | 
|  248       return MAYBE(MANY(Argument, ',')) |  | 
|  249  |  | 
|  250     def Argument(): |  | 
|  251       return syntax_switch( |  | 
|  252         # Web IDL: |  | 
|  253         [MAYBE(ExtAttrs), MAYBE(Optional), MAYBE('in'), |  | 
|  254          MAYBE(Optional), Type, MAYBE(AnEllipsis), Id], |  | 
|  255         # WebKit: |  | 
|  256         [MAYBE(Optional), MAYBE('in'), MAYBE(Optional), |  | 
|  257          MAYBE(ExtAttrs), Type, Id]) |  | 
|  258  |  | 
|  259     def Optional(): |  | 
|  260       return 'optional' |  | 
|  261  |  | 
|  262     def AnEllipsis(): |  | 
|  263       return '...' |  | 
|  264  |  | 
|  265     # Exceptions (Web IDL). |  | 
|  266     def ExceptionDef(): |  | 
|  267       return ['exception', Id, '{', MAYBE(MANY(_ExceptionMember)), '}', |  | 
|  268           ';'] |  | 
|  269  |  | 
|  270     def _ExceptionMember(): |  | 
|  271       return OR(Const, ExceptionField, ExtAttrs) |  | 
|  272  |  | 
|  273     def ExceptionField(): |  | 
|  274       return [Type, Id, ';'] |  | 
|  275  |  | 
|  276     # Types: |  | 
|  277     def Type(): |  | 
|  278       return _Type |  | 
|  279  |  | 
|  280     def ReturnType(): |  | 
|  281       return OR(VoidType, _Type) |  | 
|  282  |  | 
|  283     def InterfaceType(): |  | 
|  284       return ScopedName |  | 
|  285  |  | 
|  286     def _Type(): |  | 
|  287       return OR(AnyArrayType, AnyType, ObjectType, _NullableType) |  | 
|  288  |  | 
|  289     def _NullableType(): |  | 
|  290       return [OR(_IntegerType, BooleanType, OctetType, FloatType, |  | 
|  291              DoubleType, SequenceType, DOMStringArrayType, ScopedName), |  | 
|  292           MAYBE(Nullable)] |  | 
|  293  |  | 
|  294     def Nullable(): |  | 
|  295       return '?' |  | 
|  296  |  | 
|  297     def SequenceType(): |  | 
|  298       return ['sequence', '<', Type, '>'] |  | 
|  299  |  | 
|  300     def AnyType(): |  | 
|  301       return 'any' |  | 
|  302  |  | 
|  303     def AnyArrayType(): |  | 
|  304       # TODO(sra): Do more general handling of array types. |  | 
|  305       return 'any[]' |  | 
|  306  |  | 
|  307     def ObjectType(): |  | 
|  308       return re.compile(r'(object|Object)\b')   # both spellings. |  | 
|  309  |  | 
|  310     def VoidType(): |  | 
|  311       return 'void' |  | 
|  312  |  | 
|  313     def _IntegerType(): |  | 
|  314       return [MAYBE(Unsigned), OR(ByteType, IntType, LongLongType, |  | 
|  315                     LongType, OctetType, ShortType)] |  | 
|  316  |  | 
|  317     def Unsigned(): |  | 
|  318       return 'unsigned' |  | 
|  319  |  | 
|  320     def ShortType(): |  | 
|  321       return 'short' |  | 
|  322  |  | 
|  323     def LongLongType(): |  | 
|  324       return ['long', 'long'] |  | 
|  325  |  | 
|  326     def LongType(): |  | 
|  327       return 'long' |  | 
|  328  |  | 
|  329     def IntType(): |  | 
|  330       return 'int' |  | 
|  331  |  | 
|  332     def ByteType(): |  | 
|  333       return 'byte' |  | 
|  334  |  | 
|  335     def OctetType(): |  | 
|  336       return 'octet' |  | 
|  337  |  | 
|  338     def BooleanType(): |  | 
|  339       return 'boolean' |  | 
|  340  |  | 
|  341     def FloatType(): |  | 
|  342       return 'float' |  | 
|  343  |  | 
|  344     def DoubleType(): |  | 
|  345       return 'double' |  | 
|  346  |  | 
|  347     def _ScopedNames(): |  | 
|  348       return MANY(ScopedName, separator=',') |  | 
|  349  |  | 
|  350     def ScopedName(): |  | 
|  351       return re.compile(r'[\w\_\:\.\<\>]+') |  | 
|  352  |  | 
|  353     def DOMStringArrayType(): |  | 
|  354       return 'DOMString[]' |  | 
|  355  |  | 
|  356     # Extended Attributes: |  | 
|  357     def ExtAttrs(): |  | 
|  358       return ['[', MAYBE(MANY(ExtAttr, ',')), ']'] |  | 
|  359  |  | 
|  360     def ExtAttr(): |  | 
|  361       return [Id, MAYBE(OR(['=', ExtAttrValue], ExtAttrArgList))] |  | 
|  362  |  | 
|  363     def ExtAttrValue(): |  | 
|  364       return OR(ExtAttrFunctionValue, re.compile(r'[\w&0-9:\-\|]+')) |  | 
|  365  |  | 
|  366     def ExtAttrFunctionValue(): |  | 
|  367       return [Id, ExtAttrArgList] |  | 
|  368  |  | 
|  369     def ExtAttrArgList(): |  | 
|  370       return ['(', MAYBE(MANY(Argument, ',')), ')'] |  | 
|  371  |  | 
|  372     # Annotations - used in the FremontCut IDL grammar: |  | 
|  373     def _Annotations(): |  | 
|  374       return MANY(Annotation) |  | 
|  375  |  | 
|  376     def Annotation(): |  | 
|  377       return ['@', Id, MAYBE(_AnnotationBody)] |  | 
|  378  |  | 
|  379     def _AnnotationBody(): |  | 
|  380       return ['(', MAYBE(MANY(AnnotationArg, ',')), ')'] |  | 
|  381  |  | 
|  382     def AnnotationArg(): |  | 
|  383       return [Id, MAYBE(['=', AnnotationArgValue])] |  | 
|  384  |  | 
|  385     def AnnotationArgValue(): |  | 
|  386       return re.compile(r'[\w&0-9:/\-\.]+') |  | 
|  387  |  | 
|  388     ###################### END GRAMMAR ##################### |  | 
|  389  |  | 
|  390     # Return the grammar's root rule: |  | 
|  391     return MANY(_Definition) |  | 
|  392  |  | 
|  393   def _whitespace_grammar(self): |  | 
|  394     return OR(re.compile(r'\s+'), |  | 
|  395           re.compile(r'//.*'), |  | 
|  396           re.compile(r'#.*'), |  | 
|  397           re.compile(r'/\*.*?\*/', re.S)) |  | 
|  398  |  | 
|  399   def _pre_process(self, content, defines, includePaths): |  | 
|  400     """Pre-processes the content using gcc. |  | 
|  401  |  | 
|  402     WebKit IDLs require pre-processing by gcc. This is done by invoking |  | 
|  403     gcc in a sub-process and capturing the results. |  | 
|  404  |  | 
|  405     Returns: |  | 
|  406       The result of running gcc on the content. |  | 
|  407  |  | 
|  408     Args: |  | 
|  409       content -- text to process. |  | 
|  410       defines -- an array of pre-processor defines. |  | 
|  411       includePaths -- an array of path strings. |  | 
|  412     """ |  | 
|  413     # FIXME: Handle gcc not found, or any other processing errors |  | 
|  414     gcc = 'gcc' |  | 
|  415     cmd = [gcc, '-E', '-P', '-C', '-x', 'c++']; |  | 
|  416     for define in defines: |  | 
|  417       cmd.append('-D%s' % define) |  | 
|  418     cmd.append('-') |  | 
|  419     pipe = subprocess.Popen(cmd, stdin=subprocess.PIPE, |  | 
|  420       stdout=subprocess.PIPE, stderr=subprocess.PIPE) |  | 
|  421     (content, stderr) = pipe.communicate(content) |  | 
|  422     return content |  | 
|  423  |  | 
|  424   def parse(self, content, defines=[], includePaths=[]): |  | 
|  425     """Parse the give content string. |  | 
|  426  |  | 
|  427     The WebKit IDL syntax also allows gcc pre-processing instructions. |  | 
|  428     Lists of defined variables and include paths can be provided. |  | 
|  429  |  | 
|  430     Returns: |  | 
|  431       An abstract syntax tree (AST). |  | 
|  432  |  | 
|  433     Args: |  | 
|  434       content -- text to parse. |  | 
|  435       defines -- an array of pre-processor defines. |  | 
|  436       includePaths -- an array of path strings used by the |  | 
|  437         gcc pre-processor. |  | 
|  438     """ |  | 
|  439     if self._syntax == WEBKIT_SYNTAX: |  | 
|  440       content = self._pre_process(content, defines, includePaths) |  | 
|  441  |  | 
|  442     return self._pegparser.parse(content) |  | 
| OLD | NEW |