lib/webidl/parser/idl.treetop in webidl-0.1.3 vs lib/webidl/parser/idl.treetop in webidl-0.1.4

- old
+ new

@@ -9,27 +9,37 @@ end rule Definition Module / Interface - / PartialInterface / Dictionary + / Partial / Exception / TypeDef / ImplementsStatement + / Enum end rule Module "module" ws name:identifier ws "{" ws defs:Definitions ws "}" ws ";" <ParseTree::Module> end rule Interface "interface" ws name:identifier ws inherits:Inheritance ws "{" ws members:InterfaceMembers ws "}" ws ";" <ParseTree::Interface> end + rule Partial + "partial" ws defn:PartialDefinition { def build(parent) defn.build(parent) end } + end + + rule PartialDefinition + PartialInterface / PartialDictionary + end + + # like an interface, but no inheritance rule PartialInterface - "partial" ws "interface" ws name:identifier ws inherits:Inheritance ws "{" ws members:InterfaceMembers ws "}" ws ";" <ParseTree::PartialInterface> + "interface" ws name:identifier ws "{" ws members:InterfaceMembers ws "}" ws ";" <ParseTree::PartialInterface> end rule Inheritance (":" ws names:ScopedNameList <ParseTree::Inheritance>)? end @@ -46,25 +56,31 @@ # Dictionary → "dictionary" identifier Inheritance "{" DictionaryMembers "}" ";" rule Dictionary "dictionary" ws name:identifier ws inherits:Inheritance ws "{" ws members:DictionaryMembers ws "}" ws ";" <ParseTree::Dictionary> end + # Like a dictionary, but no inheritance + rule PartialDictionary + "dictionary" ws name:identifier ws "{" ws members:DictionaryMembers ws "}" ws ";" <ParseTree::PartialDictionary> + end + # [11] DictionaryMembers → ExtendedAttributeList DictionaryMember DictionaryMembers # | ε rule DictionaryMembers (eal:ExtendedAttributeList ws member:DictionaryMember ws members:DictionaryMembers <ParseTree::DictionaryMembers>)? end - # [12] DictionaryMember → Type identifier DefaultValue ";" rule DictionaryMember - type:Type ws name:identifier ws default:DefaultValue ws ";" <ParseTree::DictionaryMember> + type:Type ws name:identifier ws default:Default ws ";" <ParseTree::DictionaryMember> end - # [13] DefaultValue → "=" ConstValue - # | ε + rule Default + ("=" ws val:DefaultValue { def build() val.build end })? + end + rule DefaultValue - ("=" ws const:ConstValue { def build() const.build end })? + string / ConstValue end rule Exception "exception" ws name:identifier ws inherits:Inheritance ws "{" ws members:ExceptionMembers ws "}" ws ";" <ParseTree::Exception> end @@ -85,17 +101,56 @@ rule Const "const" ws type:Type ws name:identifier ws "=" ws const_expr:ConstValue ws ";" <ParseTree::Const> end rule ConstValue - BooleanLiteral / integer / float + "null" { def build() nil end } + / BooleanLiteral + / FloatLiteral + / integer end rule BooleanLiteral ("true" / "false") { def build() text_value == "true" end } end + rule FloatLiteral + float + / "-" "Infinity" { def build() -1.0/0 end } + / "Infinity" { def build() 1.0/0 end } + / "NaN" { def build() Float::NAN end } + end + + rule Enum + "enum" ws id:identifier ws "{" ws values:EnumValueList ws "}" ws ";" <ParseTree::Enum> + end + + rule EnumValueList + name:string ws + vals:EnumValues + ws ","? # trailing commas actually not allowed, but in use + { + def build() + res = [name.build] + res += vals.build if vals.any? + + res + end + } + end + + rule EnumValues + ("," ws name:string ws vals:EnumValues { + def build() + res = [name.build] + res += vals.build if vals.any? + + res + end + })? + end + rule AttributeOrOperation StringifierAttributeOrOperation / Attribute / Operation end rule StringifierAttributeOrOperation @@ -161,21 +216,45 @@ rule Arguments ("," ws arg:Argument ws args:Arguments <ParseTree::ArgumentList>)? end rule Argument - eal:ExtendedAttributeList ws In ws optional:Optional ws type:Type ws variadic:Ellipsis ws id:identifier <ParseTree::Argument> + eal:ExtendedAttributeList ws "in"? ws arg:OptionalOrRequiredArgument <ParseTree::Argument> end - rule In - "in"? + rule OptionalOrRequiredArgument + optional:"optional" ws type:Type ws name:ArgumentName ws default:Default + / type:Type ws variadic:Ellipsis ws name:ArgumentName end - rule Optional - "optional"? + + rule ArgumentName + ArgumentNameKeyword { def build() text_value end } / identifier end + rule ArgumentNameKeyword + "attribute" + / "callback" + / "const" + / "creator" + / "deleter" + / "dictionary" + / "enum" + / "exception" + / "getter" + / "implements" + / "inherit" + / "interface" + / "legacycaller" + / "partial" + / "setter" + / "static" + / "stringifier" + / "typedef" + / "unrestricted" + end + rule Ellipsis "..."? end rule ExceptionMember @@ -302,40 +381,65 @@ rule OtherOrComma Other / "," end rule Type - ("sequence" ws "<" ws type:Type ws ">" null:Null <ParseTree::SequenceType> / AttributeType) + SingleType + / type:UnionType suffix:TypeSuffix <ParseTree::Type> end - rule Null - "?"? + rule SingleType + NonAnyType + / type:"any" suffix:TypeSuffixStartingWithArray <ParseTree::Type> end - rule AttributeType - type:PrimitiveOrStringType suffix:TypeSuffix <ParseTree::Type> - / type:ScopedName suffix:TypeSuffix <ParseTree::Type> + rule UnionType + "(" ws UnionMemberType ws "or" ws UnionMemberType ws UnionMemberTypes ws ")" + end + + rule UnionMemberType + NonAnyType + / type:UnionType suffix:TypeSuffix <ParseTree::Type> + / type:"any" suffix:TypeSuffixStartingWithArray <ParseTree::Type> + end + + rule UnionMemberTypes + ("or" ws UnionMemberType ws UnionMemberTypes)? + end + + rule NonAnyType + type:PrimitiveType suffix:TypeSuffix <ParseTree::Type> + # added: cannot be followed by a NonSpace character, since e.g. DOMStringMap, DOMStringList or other identifiers would break parsing + / type:"DOMString" suffix:TypeSuffix !NonSpace <ParseTree::Type> + / "sequence" ws "<" ws type:Type ws ">" null:Null <ParseTree::SequenceType> / type:"object" suffix:TypeSuffix <ParseTree::Type> / type:"Date" suffix:TypeSuffix <ParseTree::Type> - / type:"any" suffix:TypeSuffixStartingWithArray <ParseTree::Type> + / type:identifier suffix:TypeSuffix <ParseTree::Type> end - # added: cannot be followed by a NonSpace character, since e.g. DOMStringMap, DOMStringList or other ScopedNames would break parsing - rule PrimitiveOrStringType + rule ConstType + PrimitiveType Null + / identifier Null + end + + # added: cannot be followed by a NonSpace character, since e.g. DOMStringMap, DOMStringList or other identifiers would break parsing + rule PrimitiveType (UnsignedIntegerType - / "boolean" !NonSpace - / "byte" !NonSpace - / "octet" !NonSpace - / "float" !NonSpace - / "double" !NonSpace - / "DOMString" !NonSpace) { + / UnrestrictedFloatType + / "boolean" !NonSpace + / "byte" !NonSpace + / "octet" !NonSpace) { def build(parent) Ast::Type.new(parent, text_value) end } end + rule Null + "?"? + end + rule TypeSuffix ( array:("[" ws "]") suffix:TypeSuffix <ParseTree::TypeSuffix> / null:"?" suffix:TypeSuffixStartingWithArray <ParseTree::TypeSuffix> )? @@ -347,22 +451,27 @@ rule UnsignedIntegerType "unsigned" ws IntegerType / IntegerType end + rule UnrestrictedFloatType + "unrestricted" ws FloatType + / FloatType + end + + rule FloatType + "float" / "double" + end + rule IntegerType ("short" / "long" ws OptionalLong) end rule OptionalLong "long"? end - rule Nullable - "?"? - end - rule Array ("[" ws "]")? end rule NonSpace @@ -416,14 +525,23 @@ rule float ("-"? ([0-9]+ "." [0-9]* / [0-9]* "." [0-9]+) ([Ee] [+-]? [0-9]+)? / [0-9]+ [Ee] [+-]? [0-9]+) { def build() Float(text_value) end} # TODO: check edge cases end rule identifier - [A-Z_a-z] [0-9A-Z_a-z]* { def build() text_value[/^_?(.+)/, 1] end } + [A-Z_a-z] [0-9A-Z_a-z]* { def build(parent = nil) text_value[/^_?(.+)/, 1] end } end rule string - "\"" [^"]* "\"" + # spec only allows double quotes, but single quotes are used in the HTML spec + double_quoted_string / single_quoted_string + end + + rule double_quoted_string + "\"" data:[^"]* "\"" { def build() data.text_value end } + end + + rule single_quoted_string + "'" data:[^']* "'" { def build() data.text_value end } end rule ws ([\t\n\r ]* ((line_comment / block_comment) [\t\n\r ]*)+ / [\t\n\r ]+)? end