Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F20064500
xpidl.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
45 KB
Subscribers
None
xpidl.py
View Options
#!/usr/bin/env python
# xpidl.py - A parser for cross-platform IDL (XPIDL) files.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""A parser for cross-platform IDL (XPIDL) files."""
import
sys
,
os.path
,
re
from
ply
import
lex
,
yacc
"""A type conforms to the following pattern:
def isScriptable(self):
'returns True or False'
def nativeType(self, calltype):
'returns a string representation of the native type
calltype must be 'in', 'out', or 'inout'
Interface members const/method/attribute conform to the following pattern:
name = 'string'
def toIDL(self):
'returns the member signature as IDL'
"""
def
attlistToIDL
(
attlist
):
if
len
(
attlist
)
==
0
:
return
''
attlist
=
list
(
attlist
)
attlist
.
sort
(
cmp
=
lambda
a
,
b
:
cmp
(
a
[
0
],
b
[
0
]))
return
'[
%s
] '
%
','
.
join
([
"
%s%s
"
%
(
name
,
value
is
not
None
and
'(
%s
)'
%
value
or
''
)
for
name
,
value
,
aloc
in
attlist
])
_paramsHardcode
=
{
2
:
(
'array'
,
'shared'
,
'iid_is'
,
'size_is'
,
'retval'
),
3
:
(
'array'
,
'size_is'
,
'const'
),
}
def
paramAttlistToIDL
(
attlist
):
if
len
(
attlist
)
==
0
:
return
''
# Hack alert: g_hash_table_foreach is pretty much unimitatable... hardcode
# quirk
attlist
=
list
(
attlist
)
sorted
=
[]
if
len
(
attlist
)
in
_paramsHardcode
:
for
p
in
_paramsHardcode
[
len
(
attlist
)]:
i
=
0
while
i
<
len
(
attlist
):
if
attlist
[
i
][
0
]
==
p
:
sorted
.
append
(
attlist
[
i
])
del
attlist
[
i
]
continue
i
+=
1
sorted
.
extend
(
attlist
)
return
'[
%s
] '
%
', '
.
join
([
"
%s%s
"
%
(
name
,
value
is
not
None
and
' (
%s
)'
%
value
or
''
)
for
name
,
value
,
aloc
in
sorted
])
def
unaliasType
(
t
):
while
t
.
kind
==
'typedef'
:
t
=
t
.
realtype
assert
t
is
not
None
return
t
def
getBuiltinOrNativeTypeName
(
t
):
t
=
unaliasType
(
t
)
if
t
.
kind
==
'builtin'
:
return
t
.
name
elif
t
.
kind
==
'native'
:
assert
t
.
specialtype
is
not
None
return
'[
%s
]'
%
t
.
specialtype
else
:
return
None
class
BuiltinLocation
(
object
):
def
get
(
self
):
return
"<builtin type>"
def
__str__
(
self
):
return
self
.
get
()
class
Builtin
(
object
):
kind
=
'builtin'
location
=
BuiltinLocation
def
__init__
(
self
,
name
,
nativename
,
signed
=
False
,
maybeConst
=
False
):
self
.
name
=
name
self
.
nativename
=
nativename
self
.
signed
=
signed
self
.
maybeConst
=
maybeConst
def
isScriptable
(
self
):
return
True
def
nativeType
(
self
,
calltype
,
shared
=
False
,
const
=
False
):
if
const
:
print
>>
sys
.
stderr
,
IDLError
(
"[const] doesn't make sense on builtin types."
,
self
.
location
,
warning
=
True
)
const
=
'const '
elif
calltype
==
'in'
and
self
.
nativename
.
endswith
(
'*'
):
const
=
'const '
elif
shared
:
if
not
self
.
nativename
.
endswith
(
'*'
):
raise
IDLError
(
"[shared] not applicable to non-pointer types."
,
self
.
location
)
const
=
'const '
else
:
const
=
''
return
"
%s%s
%s
"
%
(
const
,
self
.
nativename
,
calltype
!=
'in'
and
'*'
or
''
)
builtinNames
=
[
Builtin
(
'boolean'
,
'bool'
),
Builtin
(
'void'
,
'void'
),
Builtin
(
'octet'
,
'uint8_t'
),
Builtin
(
'short'
,
'int16_t'
,
True
,
True
),
Builtin
(
'long'
,
'int32_t'
,
True
,
True
),
Builtin
(
'long long'
,
'int64_t'
,
True
,
False
),
Builtin
(
'unsigned short'
,
'uint16_t'
,
False
,
True
),
Builtin
(
'unsigned long'
,
'uint32_t'
,
False
,
True
),
Builtin
(
'unsigned long long'
,
'uint64_t'
,
False
,
False
),
Builtin
(
'float'
,
'float'
,
True
,
False
),
Builtin
(
'double'
,
'double'
,
True
,
False
),
Builtin
(
'char'
,
'char'
,
True
,
False
),
Builtin
(
'string'
,
'char *'
,
False
,
False
),
Builtin
(
'wchar'
,
'char16_t'
,
False
,
False
),
Builtin
(
'wstring'
,
'char16_t *'
,
False
,
False
),
]
builtinMap
=
{}
for
b
in
builtinNames
:
builtinMap
[
b
.
name
]
=
b
class
Location
(
object
):
_line
=
None
def
__init__
(
self
,
lexer
,
lineno
,
lexpos
):
self
.
_lineno
=
lineno
self
.
_lexpos
=
lexpos
self
.
_lexdata
=
lexer
.
lexdata
self
.
_file
=
getattr
(
lexer
,
'filename'
,
"<unknown>"
)
def
__eq__
(
self
,
other
):
return
self
.
_lexpos
==
other
.
_lexpos
and
\
self
.
_file
==
other
.
_file
def
resolve
(
self
):
if
self
.
_line
:
return
startofline
=
self
.
_lexdata
.
rfind
(
'
\n
'
,
0
,
self
.
_lexpos
)
+
1
endofline
=
self
.
_lexdata
.
find
(
'
\n
'
,
self
.
_lexpos
,
self
.
_lexpos
+
80
)
self
.
_line
=
self
.
_lexdata
[
startofline
:
endofline
]
self
.
_colno
=
self
.
_lexpos
-
startofline
def
pointerline
(
self
):
def
i
():
for
i
in
xrange
(
0
,
self
.
_colno
):
yield
" "
yield
"^"
return
""
.
join
(
i
())
def
get
(
self
):
self
.
resolve
()
return
"
%s
line
%s
:
%s
"
%
(
self
.
_file
,
self
.
_lineno
,
self
.
_colno
)
def
__str__
(
self
):
self
.
resolve
()
return
"
%s
line
%s
:
%s
\n
%s
\n
%s
"
%
(
self
.
_file
,
self
.
_lineno
,
self
.
_colno
,
self
.
_line
,
self
.
pointerline
())
class
NameMap
(
object
):
"""Map of name -> object. Each object must have a .name and .location property.
Setting the same name twice throws an error."""
def
__init__
(
self
):
self
.
_d
=
{}
def
__getitem__
(
self
,
key
):
if
key
in
builtinMap
:
return
builtinMap
[
key
]
return
self
.
_d
[
key
]
def
__iter__
(
self
):
return
self
.
_d
.
itervalues
()
def
__contains__
(
self
,
key
):
return
key
in
builtinMap
or
key
in
self
.
_d
def
set
(
self
,
object
):
if
object
.
name
in
builtinMap
:
raise
IDLError
(
"name '
%s
' is a builtin and cannot be redeclared"
%
(
object
.
name
),
object
.
location
)
if
object
.
name
.
startswith
(
"_"
):
object
.
name
=
object
.
name
[
1
:]
if
object
.
name
in
self
.
_d
:
old
=
self
.
_d
[
object
.
name
]
if
old
==
object
:
return
if
isinstance
(
old
,
Forward
)
and
isinstance
(
object
,
Interface
):
self
.
_d
[
object
.
name
]
=
object
elif
isinstance
(
old
,
Interface
)
and
isinstance
(
object
,
Forward
):
pass
else
:
raise
IDLError
(
"name '
%s
' specified twice. Previous location:
%s
"
%
(
object
.
name
,
self
.
_d
[
object
.
name
]
.
location
),
object
.
location
)
else
:
self
.
_d
[
object
.
name
]
=
object
def
get
(
self
,
id
,
location
):
try
:
return
self
[
id
]
except
KeyError
:
raise
IDLError
(
"Name '
%s
' not found"
,
location
)
class
IDLError
(
Exception
):
def
__init__
(
self
,
message
,
location
,
warning
=
False
):
self
.
message
=
message
self
.
location
=
location
self
.
warning
=
warning
def
__str__
(
self
):
return
"
%s
:
%s
,
%s
"
%
(
self
.
warning
and
'warning'
or
'error'
,
self
.
message
,
self
.
location
)
class
Include
(
object
):
kind
=
'include'
def
__init__
(
self
,
filename
,
location
):
self
.
filename
=
filename
self
.
location
=
location
def
__str__
(
self
):
return
""
.
join
([
"include '
%s
'
\n
"
%
self
.
filename
])
def
resolve
(
self
,
parent
):
def
incfiles
():
yield
self
.
filename
for
dir
in
parent
.
incdirs
:
yield
os
.
path
.
join
(
dir
,
self
.
filename
)
for
file
in
incfiles
():
if
not
os
.
path
.
exists
(
file
):
continue
self
.
IDL
=
parent
.
parser
.
parse
(
open
(
file
)
.
read
(),
filename
=
file
)
self
.
IDL
.
resolve
(
parent
.
incdirs
,
parent
.
parser
)
for
type
in
self
.
IDL
.
getNames
():
parent
.
setName
(
type
)
parent
.
deps
.
extend
(
self
.
IDL
.
deps
)
return
raise
IDLError
(
"File '
%s
' not found"
%
self
.
filename
,
self
.
location
)
class
IDL
(
object
):
def
__init__
(
self
,
productions
):
self
.
productions
=
productions
self
.
deps
=
[]
def
setName
(
self
,
object
):
self
.
namemap
.
set
(
object
)
def
getName
(
self
,
id
,
location
):
try
:
return
self
.
namemap
[
id
]
except
KeyError
:
raise
IDLError
(
"type '
%s
' not found"
%
id
,
location
)
def
hasName
(
self
,
id
):
return
id
in
self
.
namemap
def
getNames
(
self
):
return
iter
(
self
.
namemap
)
def
__str__
(
self
):
return
""
.
join
([
str
(
p
)
for
p
in
self
.
productions
])
def
resolve
(
self
,
incdirs
,
parser
):
self
.
namemap
=
NameMap
()
self
.
incdirs
=
incdirs
self
.
parser
=
parser
for
p
in
self
.
productions
:
p
.
resolve
(
self
)
def
includes
(
self
):
for
p
in
self
.
productions
:
if
p
.
kind
==
'include'
:
yield
p
def
needsJSTypes
(
self
):
for
p
in
self
.
productions
:
if
p
.
kind
==
'interface'
and
p
.
needsJSTypes
():
return
True
return
False
class
CDATA
(
object
):
kind
=
'cdata'
_re
=
re
.
compile
(
r'\n+'
)
def
__init__
(
self
,
data
,
location
):
self
.
data
=
self
.
_re
.
sub
(
'
\n
'
,
data
)
self
.
location
=
location
def
resolve
(
self
,
parent
):
pass
def
__str__
(
self
):
return
"cdata:
%s
\n\t
%r
\n
"
%
(
self
.
location
.
get
(),
self
.
data
)
def
count
(
self
):
return
0
class
Typedef
(
object
):
kind
=
'typedef'
def
__init__
(
self
,
type
,
name
,
location
,
doccomments
):
self
.
type
=
type
self
.
name
=
name
self
.
location
=
location
self
.
doccomments
=
doccomments
def
__eq__
(
self
,
other
):
return
self
.
name
==
other
.
name
and
self
.
type
==
other
.
type
def
resolve
(
self
,
parent
):
parent
.
setName
(
self
)
self
.
realtype
=
parent
.
getName
(
self
.
type
,
self
.
location
)
def
isScriptable
(
self
):
return
self
.
realtype
.
isScriptable
()
def
nativeType
(
self
,
calltype
):
return
"
%s
%s
"
%
(
self
.
name
,
calltype
!=
'in'
and
'*'
or
''
)
def
__str__
(
self
):
return
"typedef
%s
%s
\n
"
%
(
self
.
type
,
self
.
name
)
class
Forward
(
object
):
kind
=
'forward'
def
__init__
(
self
,
name
,
location
,
doccomments
):
self
.
name
=
name
self
.
location
=
location
self
.
doccomments
=
doccomments
def
__eq__
(
self
,
other
):
return
other
.
kind
==
'forward'
and
other
.
name
==
self
.
name
def
resolve
(
self
,
parent
):
# Hack alert: if an identifier is already present, move the doccomments
# forward.
if
parent
.
hasName
(
self
.
name
):
for
i
in
xrange
(
0
,
len
(
parent
.
productions
)):
if
parent
.
productions
[
i
]
is
self
:
break
for
i
in
xrange
(
i
+
1
,
len
(
parent
.
productions
)):
if
hasattr
(
parent
.
productions
[
i
],
'doccomments'
):
parent
.
productions
[
i
]
.
doccomments
[
0
:
0
]
=
self
.
doccomments
break
parent
.
setName
(
self
)
def
isScriptable
(
self
):
return
True
def
nativeType
(
self
,
calltype
):
return
"
%s
%s
"
%
(
self
.
name
,
calltype
!=
'in'
and
'* *'
or
'*'
)
def
__str__
(
self
):
return
"forward-declared
%s
\n
"
%
self
.
name
class
Native
(
object
):
kind
=
'native'
modifier
=
None
specialtype
=
None
specialtypes
=
{
'nsid'
:
None
,
'domstring'
:
'nsAString'
,
'utf8string'
:
'nsACString'
,
'cstring'
:
'nsACString'
,
'astring'
:
'nsAString'
,
'jsval'
:
'JS::Value'
}
def
__init__
(
self
,
name
,
nativename
,
attlist
,
location
):
self
.
name
=
name
self
.
nativename
=
nativename
self
.
location
=
location
for
name
,
value
,
aloc
in
attlist
:
if
value
is
not
None
:
raise
IDLError
(
"Unexpected attribute value"
,
aloc
)
if
name
in
(
'ptr'
,
'ref'
):
if
self
.
modifier
is
not
None
:
raise
IDLError
(
"More than one ptr/ref modifier"
,
aloc
)
self
.
modifier
=
name
elif
name
in
self
.
specialtypes
.
keys
():
if
self
.
specialtype
is
not
None
:
raise
IDLError
(
"More than one special type"
,
aloc
)
self
.
specialtype
=
name
if
self
.
specialtypes
[
name
]
is
not
None
:
self
.
nativename
=
self
.
specialtypes
[
name
]
else
:
raise
IDLError
(
"Unexpected attribute"
,
aloc
)
def
__eq__
(
self
,
other
):
return
self
.
name
==
other
.
name
and
\
self
.
nativename
==
other
.
nativename
and
\
self
.
modifier
==
other
.
modifier
and
\
self
.
specialtype
==
other
.
specialtype
def
resolve
(
self
,
parent
):
parent
.
setName
(
self
)
def
isScriptable
(
self
):
if
self
.
specialtype
is
None
:
return
False
if
self
.
specialtype
==
'nsid'
:
return
self
.
modifier
is
not
None
return
self
.
modifier
==
'ref'
def
isPtr
(
self
,
calltype
):
return
self
.
modifier
==
'ptr'
def
isRef
(
self
,
calltype
):
return
self
.
modifier
==
'ref'
def
nativeType
(
self
,
calltype
,
const
=
False
,
shared
=
False
):
if
shared
:
if
calltype
!=
'out'
:
raise
IDLError
(
"[shared] only applies to out parameters."
)
const
=
True
if
self
.
specialtype
is
not
None
and
calltype
==
'in'
:
const
=
True
if
self
.
specialtype
==
'jsval'
:
if
calltype
==
'out'
or
calltype
==
'inout'
:
return
"JS::MutableHandleValue "
return
"JS::HandleValue "
if
self
.
isRef
(
calltype
):
m
=
'& '
elif
self
.
isPtr
(
calltype
):
m
=
'*'
+
((
self
.
modifier
==
'ptr'
and
calltype
!=
'in'
)
and
'*'
or
''
)
else
:
m
=
calltype
!=
'in'
and
'*'
or
''
return
"
%s%s
%s
"
%
(
const
and
'const '
or
''
,
self
.
nativename
,
m
)
def
__str__
(
self
):
return
"native
%s
(
%s
)
\n
"
%
(
self
.
name
,
self
.
nativename
)
class
Interface
(
object
):
kind
=
'interface'
def
__init__
(
self
,
name
,
attlist
,
base
,
members
,
location
,
doccomments
):
self
.
name
=
name
self
.
attributes
=
InterfaceAttributes
(
attlist
,
location
)
self
.
base
=
base
self
.
members
=
members
self
.
location
=
location
self
.
namemap
=
NameMap
()
self
.
doccomments
=
doccomments
self
.
nativename
=
name
for
m
in
members
:
if
not
isinstance
(
m
,
CDATA
):
self
.
namemap
.
set
(
m
)
def
__eq__
(
self
,
other
):
return
self
.
name
==
other
.
name
and
self
.
location
==
other
.
location
def
resolve
(
self
,
parent
):
self
.
idl
=
parent
# Hack alert: if an identifier is already present, libIDL assigns
# doc comments incorrectly. This is quirks-mode extraordinaire!
if
parent
.
hasName
(
self
.
name
):
for
member
in
self
.
members
:
if
hasattr
(
member
,
'doccomments'
):
member
.
doccomments
[
0
:
0
]
=
self
.
doccomments
break
self
.
doccomments
=
parent
.
getName
(
self
.
name
,
None
)
.
doccomments
if
self
.
attributes
.
function
:
has_method
=
False
for
member
in
self
.
members
:
if
member
.
kind
is
'method'
:
if
has_method
:
raise
IDLError
(
"interface '
%s
' has multiple methods, but marked 'function'"
%
self
.
name
,
self
.
location
)
else
:
has_method
=
True
parent
.
setName
(
self
)
if
self
.
base
is
not
None
:
realbase
=
parent
.
getName
(
self
.
base
,
self
.
location
)
if
realbase
.
kind
!=
'interface'
:
raise
IDLError
(
"interface '
%s
' inherits from non-interface type '
%s
'"
%
(
self
.
name
,
self
.
base
),
self
.
location
)
if
self
.
attributes
.
scriptable
and
not
realbase
.
attributes
.
scriptable
:
print
>>
sys
.
stderr
,
IDLError
(
"interface '
%s
' is scriptable but derives from non-scriptable '
%s
'"
%
(
self
.
name
,
self
.
base
),
self
.
location
,
warning
=
True
)
if
self
.
attributes
.
scriptable
and
realbase
.
attributes
.
builtinclass
and
not
self
.
attributes
.
builtinclass
:
raise
IDLError
(
"interface '
%s
' is not builtinclass but derives from builtinclass '
%s
'"
%
(
self
.
name
,
self
.
base
),
self
.
location
)
for
member
in
self
.
members
:
member
.
resolve
(
self
)
# The number 250 is NOT arbitrary; this number is the maximum number of
# stub entries defined in xpcom/reflect/xptcall/public/genstubs.pl
# Do not increase this value without increasing the number in that
# location, or you WILL cause otherwise unknown problems!
if
self
.
countEntries
()
>
250
and
not
self
.
attributes
.
builtinclass
:
raise
IDLError
(
"interface '
%s
' has too many entries"
%
self
.
name
,
self
.
location
)
def
isScriptable
(
self
):
# NOTE: this is not whether *this* interface is scriptable... it's
# whether, when used as a type, it's scriptable, which is true of all
# interfaces.
return
True
def
nativeType
(
self
,
calltype
,
const
=
False
):
return
"
%s%s
%s
"
%
(
const
and
'const '
or
''
,
self
.
name
,
calltype
!=
'in'
and
'* *'
or
'*'
)
def
__str__
(
self
):
l
=
[
"interface
%s
\n
"
%
self
.
name
]
if
self
.
base
is
not
None
:
l
.
append
(
"
\t
base
%s
\n
"
%
self
.
base
)
l
.
append
(
str
(
self
.
attributes
))
if
self
.
members
is
None
:
l
.
append
(
"
\t
incomplete type
\n
"
)
else
:
for
m
in
self
.
members
:
l
.
append
(
str
(
m
))
return
""
.
join
(
l
)
def
getConst
(
self
,
name
,
location
):
# The constant may be in a base class
iface
=
self
while
name
not
in
iface
.
namemap
and
iface
is
not
None
:
iface
=
self
.
idl
.
getName
(
self
.
base
,
self
.
location
)
if
iface
is
None
:
raise
IDLError
(
"cannot find symbol '
%s
'"
%
name
,
c
.
location
)
c
=
iface
.
namemap
.
get
(
name
,
location
)
if
c
.
kind
!=
'const'
:
raise
IDLError
(
"symbol '
%s
' is not a constant"
,
c
.
location
)
return
c
.
getValue
()
def
needsJSTypes
(
self
):
for
m
in
self
.
members
:
if
m
.
kind
==
"attribute"
and
m
.
type
==
"jsval"
:
return
True
if
m
.
kind
==
"method"
and
m
.
needsJSTypes
():
return
True
return
False
def
countEntries
(
self
):
''' Returns the number of entries in the vtable for this interface. '''
total
=
sum
(
member
.
count
()
for
member
in
self
.
members
)
if
self
.
base
is
not
None
:
realbase
=
self
.
idl
.
getName
(
self
.
base
,
self
.
location
)
total
+=
realbase
.
countEntries
()
return
total
class
InterfaceAttributes
(
object
):
uuid
=
None
scriptable
=
False
builtinclass
=
False
function
=
False
deprecated
=
False
noscript
=
False
def
setuuid
(
self
,
value
):
self
.
uuid
=
value
.
lower
()
def
setscriptable
(
self
):
self
.
scriptable
=
True
def
setfunction
(
self
):
self
.
function
=
True
def
setnoscript
(
self
):
self
.
noscript
=
True
def
setbuiltinclass
(
self
):
self
.
builtinclass
=
True
def
setdeprecated
(
self
):
self
.
deprecated
=
True
actions
=
{
'uuid'
:
(
True
,
setuuid
),
'scriptable'
:
(
False
,
setscriptable
),
'builtinclass'
:
(
False
,
setbuiltinclass
),
'function'
:
(
False
,
setfunction
),
'noscript'
:
(
False
,
setnoscript
),
'deprecated'
:
(
False
,
setdeprecated
),
'object'
:
(
False
,
lambda
self
:
True
),
}
def
__init__
(
self
,
attlist
,
location
):
def
badattribute
(
self
):
raise
IDLError
(
"Unexpected interface attribute '
%s
'"
%
name
,
location
)
for
name
,
val
,
aloc
in
attlist
:
hasval
,
action
=
self
.
actions
.
get
(
name
,
(
False
,
badattribute
))
if
hasval
:
if
val
is
None
:
raise
IDLError
(
"Expected value for attribute '
%s
'"
%
name
,
aloc
)
action
(
self
,
val
)
else
:
if
val
is
not
None
:
raise
IDLError
(
"Unexpected value for attribute '
%s
'"
%
name
,
aloc
)
action
(
self
)
if
self
.
uuid
is
None
:
raise
IDLError
(
"interface has no uuid"
,
location
)
def
__str__
(
self
):
l
=
[]
if
self
.
uuid
:
l
.
append
(
"
\t
uuid:
%s
\n
"
%
self
.
uuid
)
if
self
.
scriptable
:
l
.
append
(
"
\t
scriptable
\n
"
)
if
self
.
builtinclass
:
l
.
append
(
"
\t
builtinclass
\n
"
)
if
self
.
function
:
l
.
append
(
"
\t
function
\n
"
)
return
""
.
join
(
l
)
class
ConstMember
(
object
):
kind
=
'const'
def
__init__
(
self
,
type
,
name
,
value
,
location
,
doccomments
):
self
.
type
=
type
self
.
name
=
name
self
.
value
=
value
self
.
location
=
location
self
.
doccomments
=
doccomments
def
resolve
(
self
,
parent
):
self
.
realtype
=
parent
.
idl
.
getName
(
self
.
type
,
self
.
location
)
self
.
iface
=
parent
basetype
=
self
.
realtype
while
isinstance
(
basetype
,
Typedef
):
basetype
=
basetype
.
realtype
if
not
isinstance
(
basetype
,
Builtin
)
or
not
basetype
.
maybeConst
:
raise
IDLError
(
"const may only be a short or long type, not
%s
"
%
self
.
type
,
self
.
location
)
self
.
basetype
=
basetype
def
getValue
(
self
):
return
self
.
value
(
self
.
iface
)
def
__str__
(
self
):
return
"
\t
const
%s
%s
=
%s
\n
"
%
(
self
.
type
,
self
.
name
,
self
.
getValue
())
def
count
(
self
):
return
0
class
Attribute
(
object
):
kind
=
'attribute'
noscript
=
False
readonly
=
False
implicit_jscontext
=
False
nostdcall
=
False
binaryname
=
None
null
=
None
undefined
=
None
deprecated
=
False
infallible
=
False
def
__init__
(
self
,
type
,
name
,
attlist
,
readonly
,
location
,
doccomments
):
self
.
type
=
type
self
.
name
=
name
self
.
attlist
=
attlist
self
.
readonly
=
readonly
self
.
location
=
location
self
.
doccomments
=
doccomments
for
name
,
value
,
aloc
in
attlist
:
if
name
==
'binaryname'
:
if
value
is
None
:
raise
IDLError
(
"binaryname attribute requires a value"
,
aloc
)
self
.
binaryname
=
value
continue
if
name
==
'Null'
:
if
value
is
None
:
raise
IDLError
(
"'Null' attribute requires a value"
,
aloc
)
if
readonly
:
raise
IDLError
(
"'Null' attribute only makes sense for setters"
,
aloc
);
if
value
not
in
(
'Empty'
,
'Null'
,
'Stringify'
):
raise
IDLError
(
"'Null' attribute value must be 'Empty', 'Null' or 'Stringify'"
,
aloc
);
self
.
null
=
value
elif
name
==
'Undefined'
:
if
value
is
None
:
raise
IDLError
(
"'Undefined' attribute requires a value"
,
aloc
)
if
readonly
:
raise
IDLError
(
"'Undefined' attribute only makes sense for setters"
,
aloc
);
if
value
not
in
(
'Empty'
,
'Null'
):
raise
IDLError
(
"'Undefined' attribute value must be 'Empty' or 'Null'"
,
aloc
);
self
.
undefined
=
value
else
:
if
value
is
not
None
:
raise
IDLError
(
"Unexpected attribute value"
,
aloc
)
if
name
==
'noscript'
:
self
.
noscript
=
True
elif
name
==
'implicit_jscontext'
:
self
.
implicit_jscontext
=
True
elif
name
==
'deprecated'
:
self
.
deprecated
=
True
elif
name
==
'nostdcall'
:
self
.
nostdcall
=
True
elif
name
==
'infallible'
:
self
.
infallible
=
True
else
:
raise
IDLError
(
"Unexpected attribute '
%s
'"
%
name
,
aloc
)
def
resolve
(
self
,
iface
):
self
.
iface
=
iface
self
.
realtype
=
iface
.
idl
.
getName
(
self
.
type
,
self
.
location
)
if
(
self
.
null
is
not
None
and
getBuiltinOrNativeTypeName
(
self
.
realtype
)
!=
'[domstring]'
):
raise
IDLError
(
"'Null' attribute can only be used on DOMString"
,
self
.
location
)
if
(
self
.
undefined
is
not
None
and
getBuiltinOrNativeTypeName
(
self
.
realtype
)
!=
'[domstring]'
):
raise
IDLError
(
"'Undefined' attribute can only be used on DOMString"
,
self
.
location
)
if
self
.
infallible
and
not
self
.
realtype
.
kind
==
'builtin'
:
raise
IDLError
(
'[infallible] only works on builtin types '
'(numbers, booleans, and raw char types)'
,
self
.
location
)
if
self
.
infallible
and
not
iface
.
attributes
.
builtinclass
:
raise
IDLError
(
'[infallible] attributes are only allowed on '
'[builtinclass] interfaces'
,
self
.
location
)
def
toIDL
(
self
):
attribs
=
attlistToIDL
(
self
.
attlist
)
readonly
=
self
.
readonly
and
'readonly '
or
''
return
"
%s%s
attribute
%s
%s
;"
%
(
attribs
,
readonly
,
self
.
type
,
self
.
name
)
def
isScriptable
(
self
):
if
not
self
.
iface
.
attributes
.
scriptable
:
return
False
return
not
self
.
noscript
def
__str__
(
self
):
return
"
\t
%s
attribute
%s
%s
\n
"
%
(
self
.
readonly
and
'readonly '
or
''
,
self
.
type
,
self
.
name
)
def
count
(
self
):
return
self
.
readonly
and
1
or
2
class
Method
(
object
):
kind
=
'method'
noscript
=
False
notxpcom
=
False
binaryname
=
None
implicit_jscontext
=
False
nostdcall
=
False
optional_argc
=
False
deprecated
=
False
def
__init__
(
self
,
type
,
name
,
attlist
,
paramlist
,
location
,
doccomments
,
raises
):
self
.
type
=
type
self
.
name
=
name
self
.
attlist
=
attlist
self
.
params
=
paramlist
self
.
location
=
location
self
.
doccomments
=
doccomments
self
.
raises
=
raises
for
name
,
value
,
aloc
in
attlist
:
if
name
==
'binaryname'
:
if
value
is
None
:
raise
IDLError
(
"binaryname attribute requires a value"
,
aloc
)
self
.
binaryname
=
value
continue
if
value
is
not
None
:
raise
IDLError
(
"Unexpected attribute value"
,
aloc
)
if
name
==
'noscript'
:
self
.
noscript
=
True
elif
name
==
'notxpcom'
:
self
.
notxpcom
=
True
elif
name
==
'implicit_jscontext'
:
self
.
implicit_jscontext
=
True
elif
name
==
'optional_argc'
:
self
.
optional_argc
=
True
elif
name
==
'deprecated'
:
self
.
deprecated
=
True
elif
name
==
'nostdcall'
:
self
.
nostdcall
=
True
else
:
raise
IDLError
(
"Unexpected attribute '
%s
'"
%
name
,
aloc
)
self
.
namemap
=
NameMap
()
for
p
in
paramlist
:
self
.
namemap
.
set
(
p
)
def
resolve
(
self
,
iface
):
self
.
iface
=
iface
self
.
realtype
=
self
.
iface
.
idl
.
getName
(
self
.
type
,
self
.
location
)
for
p
in
self
.
params
:
p
.
resolve
(
self
)
for
p
in
self
.
params
:
if
p
.
retval
and
p
!=
self
.
params
[
-
1
]:
raise
IDLError
(
"'retval' parameter '
%s
' is not the last parameter"
%
p
.
name
,
self
.
location
)
if
p
.
size_is
:
found_size_param
=
False
for
size_param
in
self
.
params
:
if
p
.
size_is
==
size_param
.
name
:
found_size_param
=
True
if
getBuiltinOrNativeTypeName
(
size_param
.
realtype
)
!=
'unsigned long'
:
raise
IDLError
(
"is_size parameter must have type 'unsigned long'"
,
self
.
location
)
if
not
found_size_param
:
raise
IDLError
(
"could not find is_size parameter '
%s
'"
%
p
.
size_is
,
self
.
location
)
def
isScriptable
(
self
):
if
not
self
.
iface
.
attributes
.
scriptable
:
return
False
return
not
(
self
.
noscript
or
self
.
notxpcom
)
def
__str__
(
self
):
return
"
\t
%s
%s
(
%s
)
\n
"
%
(
self
.
type
,
self
.
name
,
", "
.
join
([
p
.
name
for
p
in
self
.
params
]))
def
toIDL
(
self
):
if
len
(
self
.
raises
):
raises
=
' raises (
%s
)'
%
','
.
join
(
self
.
raises
)
else
:
raises
=
''
return
"
%s%s
%s
(
%s
)
%s
;"
%
(
attlistToIDL
(
self
.
attlist
),
self
.
type
,
self
.
name
,
", "
.
join
([
p
.
toIDL
()
for
p
in
self
.
params
]),
raises
)
def
needsJSTypes
(
self
):
if
self
.
implicit_jscontext
:
return
True
if
self
.
type
==
"jsval"
:
return
True
for
p
in
self
.
params
:
t
=
p
.
realtype
if
isinstance
(
t
,
Native
)
and
t
.
specialtype
==
"jsval"
:
return
True
return
False
def
count
(
self
):
return
1
class
Param
(
object
):
size_is
=
None
iid_is
=
None
const
=
False
array
=
False
retval
=
False
shared
=
False
optional
=
False
null
=
None
undefined
=
None
def
__init__
(
self
,
paramtype
,
type
,
name
,
attlist
,
location
,
realtype
=
None
):
self
.
paramtype
=
paramtype
self
.
type
=
type
self
.
name
=
name
self
.
attlist
=
attlist
self
.
location
=
location
self
.
realtype
=
realtype
for
name
,
value
,
aloc
in
attlist
:
# Put the value-taking attributes first!
if
name
==
'size_is'
:
if
value
is
None
:
raise
IDLError
(
"'size_is' must specify a parameter"
,
aloc
)
self
.
size_is
=
value
elif
name
==
'iid_is'
:
if
value
is
None
:
raise
IDLError
(
"'iid_is' must specify a parameter"
,
aloc
)
self
.
iid_is
=
value
elif
name
==
'Null'
:
if
value
is
None
:
raise
IDLError
(
"'Null' must specify a parameter"
,
aloc
)
if
value
not
in
(
'Empty'
,
'Null'
,
'Stringify'
):
raise
IDLError
(
"'Null' parameter value must be 'Empty', 'Null', or 'Stringify'"
,
aloc
);
self
.
null
=
value
elif
name
==
'Undefined'
:
if
value
is
None
:
raise
IDLError
(
"'Undefined' must specify a parameter"
,
aloc
)
if
value
not
in
(
'Empty'
,
'Null'
):
raise
IDLError
(
"'Undefined' parameter value must be 'Empty' or 'Null'"
,
aloc
);
self
.
undefined
=
value
else
:
if
value
is
not
None
:
raise
IDLError
(
"Unexpected value for attribute '
%s
'"
%
name
,
aloc
)
if
name
==
'const'
:
self
.
const
=
True
elif
name
==
'array'
:
self
.
array
=
True
elif
name
==
'retval'
:
self
.
retval
=
True
elif
name
==
'shared'
:
self
.
shared
=
True
elif
name
==
'optional'
:
self
.
optional
=
True
else
:
raise
IDLError
(
"Unexpected attribute '
%s
'"
%
name
,
aloc
)
def
resolve
(
self
,
method
):
self
.
realtype
=
method
.
iface
.
idl
.
getName
(
self
.
type
,
self
.
location
)
if
self
.
array
:
self
.
realtype
=
Array
(
self
.
realtype
)
if
(
self
.
null
is
not
None
and
getBuiltinOrNativeTypeName
(
self
.
realtype
)
!=
'[domstring]'
):
raise
IDLError
(
"'Null' attribute can only be used on DOMString"
,
self
.
location
)
if
(
self
.
undefined
is
not
None
and
getBuiltinOrNativeTypeName
(
self
.
realtype
)
!=
'[domstring]'
):
raise
IDLError
(
"'Undefined' attribute can only be used on DOMString"
,
self
.
location
)
def
nativeType
(
self
):
kwargs
=
{}
if
self
.
shared
:
kwargs
[
'shared'
]
=
True
if
self
.
const
:
kwargs
[
'const'
]
=
True
try
:
return
self
.
realtype
.
nativeType
(
self
.
paramtype
,
**
kwargs
)
except
IDLError
,
e
:
raise
IDLError
(
e
.
message
,
self
.
location
)
except
TypeError
,
e
:
raise
IDLError
(
"Unexpected parameter attribute"
,
self
.
location
)
def
toIDL
(
self
):
return
"
%s%s
%s
%s
"
%
(
paramAttlistToIDL
(
self
.
attlist
),
self
.
paramtype
,
self
.
type
,
self
.
name
)
class
Array
(
object
):
def
__init__
(
self
,
basetype
):
self
.
type
=
basetype
def
isScriptable
(
self
):
return
self
.
type
.
isScriptable
()
def
nativeType
(
self
,
calltype
,
const
=
False
):
return
"
%s%s
*"
%
(
const
and
'const '
or
''
,
self
.
type
.
nativeType
(
calltype
))
class
IDLParser
(
object
):
keywords
=
{
'const'
:
'CONST'
,
'interface'
:
'INTERFACE'
,
'in'
:
'IN'
,
'inout'
:
'INOUT'
,
'out'
:
'OUT'
,
'attribute'
:
'ATTRIBUTE'
,
'raises'
:
'RAISES'
,
'readonly'
:
'READONLY'
,
'native'
:
'NATIVE'
,
'typedef'
:
'TYPEDEF'
,
'Infinity'
:
'INFINITY'
}
tokens
=
[
'IDENTIFIER'
,
'CDATA'
,
'INCLUDE'
,
'IID'
,
'NUMBER'
,
'HEXNUM'
,
'LSHIFT'
,
'RSHIFT'
,
'NATIVEID'
,
]
tokens
.
extend
(
keywords
.
values
())
states
=
(
(
'nativeid'
,
'exclusive'
),
)
hexchar
=
r'[a-fA-F0-9]'
t_NUMBER
=
r'-?\d+'
t_HEXNUM
=
r'0x
%s
+'
%
hexchar
t_LSHIFT
=
r'<<'
t_RSHIFT
=
r'>>'
literals
=
'"(){}[],;:=|+-*'
t_ignore
=
'
\t
'
def
t_multilinecomment
(
self
,
t
):
r'/\*(?s).*?\*/'
t
.
lexer
.
lineno
+=
t
.
value
.
count
(
'
\n
'
)
if
t
.
value
.
startswith
(
"/**"
):
self
.
_doccomments
.
append
(
t
.
value
)
def
t_singlelinecomment
(
self
,
t
):
r'(?m)//.*?$'
def
t_IID
(
self
,
t
):
return
t
t_IID
.
__doc__
=
r'
%(c)s
{8}-
%(c)s
{4}-
%(c)s
{4}-
%(c)s
{4}-
%(c)s
{12}'
%
{
'c'
:
hexchar
}
def
t_IDENTIFIER
(
self
,
t
):
r'(unsigned\ long\ long|unsigned\ short|unsigned\ long|long\ long)(?!_?[A-Za-z][A-Za-z_0-9])|_?[A-Za-z][A-Za-z_0-9]*'
t
.
type
=
self
.
keywords
.
get
(
t
.
value
,
'IDENTIFIER'
)
return
t
def
t_LCDATA
(
self
,
t
):
r'(?s)%\{[ ]*C\+\+[ ]*\n(?P<cdata>.*?\n?)%\}[ ]*(C\+\+)?'
t
.
type
=
'CDATA'
t
.
value
=
t
.
lexer
.
lexmatch
.
group
(
'cdata'
)
t
.
lexer
.
lineno
+=
t
.
value
.
count
(
'
\n
'
)
return
t
def
t_INCLUDE
(
self
,
t
):
r'\#include[ \t]+"[^"\n]+"'
inc
,
value
,
end
=
t
.
value
.
split
(
'"'
)
t
.
value
=
value
return
t
def
t_directive
(
self
,
t
):
r'\#(?P<directive>[a-zA-Z]+)[^\n]+'
raise
IDLError
(
"Unrecognized directive
%s
"
%
t
.
lexer
.
lexmatch
.
group
(
'directive'
),
Location
(
lexer
=
self
.
lexer
,
lineno
=
self
.
lexer
.
lineno
,
lexpos
=
self
.
lexer
.
lexpos
))
def
t_newline
(
self
,
t
):
r'\n+'
t
.
lexer
.
lineno
+=
len
(
t
.
value
)
def
t_nativeid_NATIVEID
(
self
,
t
):
r'[^()\n]+(?=\))'
t
.
lexer
.
begin
(
'INITIAL'
)
return
t
t_nativeid_ignore
=
''
def
t_ANY_error
(
self
,
t
):
raise
IDLError
(
"unrecognized input"
,
Location
(
lexer
=
self
.
lexer
,
lineno
=
self
.
lexer
.
lineno
,
lexpos
=
self
.
lexer
.
lexpos
))
precedence
=
(
(
'left'
,
'|'
),
(
'left'
,
'LSHIFT'
,
'RSHIFT'
),
(
'left'
,
'+'
,
'-'
),
(
'left'
,
'*'
),
(
'left'
,
'UMINUS'
),
)
def
p_idlfile
(
self
,
p
):
"""idlfile : productions"""
p
[
0
]
=
IDL
(
p
[
1
])
def
p_productions_start
(
self
,
p
):
"""productions : """
p
[
0
]
=
[]
def
p_productions_cdata
(
self
,
p
):
"""productions : CDATA productions"""
p
[
0
]
=
list
(
p
[
2
])
p
[
0
]
.
insert
(
0
,
CDATA
(
p
[
1
],
self
.
getLocation
(
p
,
1
)))
def
p_productions_include
(
self
,
p
):
"""productions : INCLUDE productions"""
p
[
0
]
=
list
(
p
[
2
])
p
[
0
]
.
insert
(
0
,
Include
(
p
[
1
],
self
.
getLocation
(
p
,
1
)))
def
p_productions_interface
(
self
,
p
):
"""productions : interface productions
| typedef productions
| native productions"""
p
[
0
]
=
list
(
p
[
2
])
p
[
0
]
.
insert
(
0
,
p
[
1
])
def
p_typedef
(
self
,
p
):
"""typedef : TYPEDEF IDENTIFIER IDENTIFIER ';'"""
p
[
0
]
=
Typedef
(
type
=
p
[
2
],
name
=
p
[
3
],
location
=
self
.
getLocation
(
p
,
1
),
doccomments
=
p
.
slice
[
1
]
.
doccomments
)
def
p_native
(
self
,
p
):
"""native : attributes NATIVE IDENTIFIER afternativeid '(' NATIVEID ')' ';'"""
p
[
0
]
=
Native
(
name
=
p
[
3
],
nativename
=
p
[
6
],
attlist
=
p
[
1
][
'attlist'
],
location
=
self
.
getLocation
(
p
,
2
))
def
p_afternativeid
(
self
,
p
):
"""afternativeid : """
# this is a place marker: we switch the lexer into literal identifier
# mode here, to slurp up everything until the closeparen
self
.
lexer
.
begin
(
'nativeid'
)
def
p_anyident
(
self
,
p
):
"""anyident : IDENTIFIER
| CONST"""
p
[
0
]
=
{
'value'
:
p
[
1
],
'location'
:
self
.
getLocation
(
p
,
1
)}
def
p_attributes
(
self
,
p
):
"""attributes : '[' attlist ']'
| """
if
len
(
p
)
==
1
:
p
[
0
]
=
{
'attlist'
:
[]}
else
:
p
[
0
]
=
{
'attlist'
:
p
[
2
],
'doccomments'
:
p
.
slice
[
1
]
.
doccomments
}
def
p_attlist_start
(
self
,
p
):
"""attlist : attribute"""
p
[
0
]
=
[
p
[
1
]]
def
p_attlist_continue
(
self
,
p
):
"""attlist : attribute ',' attlist"""
p
[
0
]
=
list
(
p
[
3
])
p
[
0
]
.
insert
(
0
,
p
[
1
])
def
p_attribute
(
self
,
p
):
"""attribute : anyident attributeval"""
p
[
0
]
=
(
p
[
1
][
'value'
],
p
[
2
],
p
[
1
][
'location'
])
def
p_attributeval
(
self
,
p
):
"""attributeval : '(' IDENTIFIER ')'
| '(' IID ')'
| """
if
len
(
p
)
>
1
:
p
[
0
]
=
p
[
2
]
def
p_interface
(
self
,
p
):
"""interface : attributes INTERFACE IDENTIFIER ifacebase ifacebody ';'"""
atts
,
INTERFACE
,
name
,
base
,
body
,
SEMI
=
p
[
1
:]
attlist
=
atts
[
'attlist'
]
doccomments
=
[]
if
'doccomments'
in
atts
:
doccomments
.
extend
(
atts
[
'doccomments'
])
doccomments
.
extend
(
p
.
slice
[
2
]
.
doccomments
)
l
=
lambda
:
self
.
getLocation
(
p
,
2
)
if
body
is
None
:
# forward-declared interface... must not have attributes!
if
len
(
attlist
)
!=
0
:
raise
IDLError
(
"Forward-declared interface must not have attributes"
,
list
[
0
][
3
])
if
base
is
not
None
:
raise
IDLError
(
"Forward-declared interface must not have a base"
,
l
())
p
[
0
]
=
Forward
(
name
=
name
,
location
=
l
(),
doccomments
=
doccomments
)
else
:
p
[
0
]
=
Interface
(
name
=
name
,
attlist
=
attlist
,
base
=
base
,
members
=
body
,
location
=
l
(),
doccomments
=
doccomments
)
def
p_ifacebody
(
self
,
p
):
"""ifacebody : '{' members '}'
| """
if
len
(
p
)
>
1
:
p
[
0
]
=
p
[
2
]
def
p_ifacebase
(
self
,
p
):
"""ifacebase : ':' IDENTIFIER
| """
if
len
(
p
)
==
3
:
p
[
0
]
=
p
[
2
]
def
p_members_start
(
self
,
p
):
"""members : """
p
[
0
]
=
[]
def
p_members_continue
(
self
,
p
):
"""members : member members"""
p
[
0
]
=
list
(
p
[
2
])
p
[
0
]
.
insert
(
0
,
p
[
1
])
def
p_member_cdata
(
self
,
p
):
"""member : CDATA"""
p
[
0
]
=
CDATA
(
p
[
1
],
self
.
getLocation
(
p
,
1
))
def
p_member_const
(
self
,
p
):
"""member : CONST IDENTIFIER IDENTIFIER '=' number ';' """
p
[
0
]
=
ConstMember
(
type
=
p
[
2
],
name
=
p
[
3
],
value
=
p
[
5
],
location
=
self
.
getLocation
(
p
,
1
),
doccomments
=
p
.
slice
[
1
]
.
doccomments
)
# All "number" products return a function(interface)
def
p_number_decimal
(
self
,
p
):
"""number : NUMBER"""
n
=
int
(
p
[
1
])
p
[
0
]
=
lambda
i
:
n
def
p_number_hex
(
self
,
p
):
"""number : HEXNUM"""
n
=
int
(
p
[
1
],
16
)
p
[
0
]
=
lambda
i
:
n
def
p_number_identifier
(
self
,
p
):
"""number : IDENTIFIER"""
id
=
p
[
1
]
loc
=
self
.
getLocation
(
p
,
1
)
p
[
0
]
=
lambda
i
:
i
.
getConst
(
id
,
loc
)
def
p_number_paren
(
self
,
p
):
"""number : '(' number ')'"""
p
[
0
]
=
p
[
2
]
def
p_number_neg
(
self
,
p
):
"""number : '-' number %prec UMINUS"""
n
=
p
[
2
]
p
[
0
]
=
lambda
i
:
-
n
(
i
)
def
p_number_add
(
self
,
p
):
"""number : number '+' number
| number '-' number
| number '*' number"""
n1
=
p
[
1
]
n2
=
p
[
3
]
if
p
[
2
]
==
'+'
:
p
[
0
]
=
lambda
i
:
n1
(
i
)
+
n2
(
i
)
elif
p
[
2
]
==
'-'
:
p
[
0
]
=
lambda
i
:
n1
(
i
)
-
n2
(
i
)
else
:
p
[
0
]
=
lambda
i
:
n1
(
i
)
*
n2
(
i
)
def
p_number_shift
(
self
,
p
):
"""number : number LSHIFT number
| number RSHIFT number"""
n1
=
p
[
1
]
n2
=
p
[
3
]
if
p
[
2
]
==
'<<'
:
p
[
0
]
=
lambda
i
:
n1
(
i
)
<<
n2
(
i
)
else
:
p
[
0
]
=
lambda
i
:
n1
(
i
)
>>
n2
(
i
)
def
p_number_bitor
(
self
,
p
):
"""number : number '|' number"""
n1
=
p
[
1
]
n2
=
p
[
3
]
p
[
0
]
=
lambda
i
:
n1
(
i
)
|
n2
(
i
)
def
p_member_att
(
self
,
p
):
"""member : attributes optreadonly ATTRIBUTE IDENTIFIER IDENTIFIER ';'"""
if
'doccomments'
in
p
[
1
]:
doccomments
=
p
[
1
][
'doccomments'
]
elif
p
[
2
]
is
not
None
:
doccomments
=
p
[
2
]
else
:
doccomments
=
p
.
slice
[
3
]
.
doccomments
p
[
0
]
=
Attribute
(
type
=
p
[
4
],
name
=
p
[
5
],
attlist
=
p
[
1
][
'attlist'
],
readonly
=
p
[
2
]
is
not
None
,
location
=
self
.
getLocation
(
p
,
3
),
doccomments
=
doccomments
)
def
p_member_method
(
self
,
p
):
"""member : attributes IDENTIFIER IDENTIFIER '(' paramlist ')' raises ';'"""
if
'doccomments'
in
p
[
1
]:
doccomments
=
p
[
1
][
'doccomments'
]
else
:
doccomments
=
p
.
slice
[
2
]
.
doccomments
p
[
0
]
=
Method
(
type
=
p
[
2
],
name
=
p
[
3
],
attlist
=
p
[
1
][
'attlist'
],
paramlist
=
p
[
5
],
location
=
self
.
getLocation
(
p
,
3
),
doccomments
=
doccomments
,
raises
=
p
[
7
])
def
p_paramlist
(
self
,
p
):
"""paramlist : param moreparams
| """
if
len
(
p
)
==
1
:
p
[
0
]
=
[]
else
:
p
[
0
]
=
list
(
p
[
2
])
p
[
0
]
.
insert
(
0
,
p
[
1
])
def
p_moreparams_start
(
self
,
p
):
"""moreparams :"""
p
[
0
]
=
[]
def
p_moreparams_continue
(
self
,
p
):
"""moreparams : ',' param moreparams"""
p
[
0
]
=
list
(
p
[
3
])
p
[
0
]
.
insert
(
0
,
p
[
2
])
def
p_param
(
self
,
p
):
"""param : attributes paramtype IDENTIFIER IDENTIFIER"""
p
[
0
]
=
Param
(
paramtype
=
p
[
2
],
type
=
p
[
3
],
name
=
p
[
4
],
attlist
=
p
[
1
][
'attlist'
],
location
=
self
.
getLocation
(
p
,
3
))
def
p_paramtype
(
self
,
p
):
"""paramtype : IN
| INOUT
| OUT"""
p
[
0
]
=
p
[
1
]
def
p_optreadonly
(
self
,
p
):
"""optreadonly : READONLY
| """
if
len
(
p
)
>
1
:
p
[
0
]
=
p
.
slice
[
1
]
.
doccomments
else
:
p
[
0
]
=
None
def
p_raises
(
self
,
p
):
"""raises : RAISES '(' idlist ')'
| """
if
len
(
p
)
==
1
:
p
[
0
]
=
[]
else
:
p
[
0
]
=
p
[
3
]
def
p_idlist
(
self
,
p
):
"""idlist : IDENTIFIER"""
p
[
0
]
=
[
p
[
1
]]
def
p_idlist_continue
(
self
,
p
):
"""idlist : IDENTIFIER ',' idlist"""
p
[
0
]
=
list
(
p
[
3
])
p
[
0
]
.
insert
(
0
,
p
[
1
])
def
p_error
(
self
,
t
):
if
not
t
:
raise
IDLError
(
"Syntax Error at end of file. Possibly due to missing semicolon(;), braces(}) or both"
,
None
)
else
:
location
=
Location
(
self
.
lexer
,
t
.
lineno
,
t
.
lexpos
)
raise
IDLError
(
"invalid syntax"
,
location
)
def
__init__
(
self
,
outputdir
=
''
):
self
.
_doccomments
=
[]
self
.
lexer
=
lex
.
lex
(
object
=
self
,
outputdir
=
outputdir
,
lextab
=
'xpidllex'
,
optimize
=
1
)
self
.
parser
=
yacc
.
yacc
(
module
=
self
,
outputdir
=
outputdir
,
debug
=
0
,
tabmodule
=
'xpidlyacc'
,
optimize
=
1
)
def
clearComments
(
self
):
self
.
_doccomments
=
[]
def
token
(
self
):
t
=
self
.
lexer
.
token
()
if
t
is
not
None
and
t
.
type
!=
'CDATA'
:
t
.
doccomments
=
self
.
_doccomments
self
.
_doccomments
=
[]
return
t
def
parse
(
self
,
data
,
filename
=
None
):
if
filename
is
not
None
:
self
.
lexer
.
filename
=
filename
self
.
lexer
.
lineno
=
1
self
.
lexer
.
input
(
data
)
idl
=
self
.
parser
.
parse
(
lexer
=
self
)
if
filename
is
not
None
:
idl
.
deps
.
append
(
filename
)
return
idl
def
getLocation
(
self
,
p
,
i
):
return
Location
(
self
.
lexer
,
p
.
lineno
(
i
),
p
.
lexpos
(
i
))
if
__name__
==
'__main__'
:
p
=
IDLParser
()
for
f
in
sys
.
argv
[
1
:]:
print
"Parsing
%s
"
%
f
p
.
parse
(
open
(
f
)
.
read
(),
filename
=
f
)
File Metadata
Details
Attached
Mime Type
text/x-python
Expires
Sun, Feb 23, 7:16 PM (5 h, 50 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
78/b8/815c6d4df6d48298afc535ae1cac
Attached To
rENIG Enigmail
Event Timeline
Log In to Comment