{ use util; } idl: cpp_prefix(s?) module_header interface { [$item{module_header}, $item{interface}] } | module_header: '[' module_param(s /,/) ']' {{ "TYPE" => "MODULEHEADER", "DATA" => util::FlattenHash($item[3]) }} | module_param: identifier '(' text ')' {{ "$item{identifier}" => "$item{text}" }} | interface: 'interface' identifier '{' definition(s?) '}' {{ "TYPE" => "INTERFACE", "NAME" => $item{identifier}, "DATA" => $item[5] }} | definition : cpp_prefix | typedef { $item[1] } | function { $item[1] } typedef : 'typedef' type identifier array_len(?) ';' {{ "TYPE" => "TYPEDEF", "NAME" => $item{identifier}, "DATA" => $item{type}, "ARRAY_LEN" => $item[5][0] }} | struct: property_list(s?) 'struct' '{' element_list1(?) '}' {{ "TYPE" => "STRUCT", "PROPERTIES" => util::FlattenArray($item[1]), "ELEMENTS" => util::FlattenArray2($item[5]) }} | union: property_list(s?) 'union' '{' union_element(s?) '}' {{ "TYPE" => "UNION", "PROPERTIES" => util::FlattenArray($item[1]), "DATA" => $item[5] }} | union_element: '[' 'case' '(' constant ')' ']' base_element ';' {{ "TYPE" => "UNION_ELEMENT", "CASE" => $item{constant}, "DATA" => $item{base_element} }} | 'case' '(' constant ')' base_element ';' {{ "TYPE" => "UNION_ELEMENT", "CASE" => $item{constant}, "DATA" => $item{base_element} }} base_element: property_list(s?) type pointer(s?) identifier array_len(?) {{ "NAME" => $item{identifier}, "TYPE" => $item{type}, "PROPERTIES" => util::FlattenArray($item[1]), "POINTERS" => $#{$item[3]}==-1?undef:$#{$item[3]}+1, "ARRAY_LEN" => $item[5][0] }} | array_len: '[' ']' { "*" } | '[' '*' ']' { "*" } | '[' text ']' { "$item{text}" } | element_list1: base_element(s? /;/) ';' { $item[1] } element_list2: 'void' | base_element(s? /,/) { $item[1] } pointer: '*' property_list: '[' property(s /,/) ']' { $item[3] } | property: 'unique' | 'in' | 'out' | 'ref' | 'struct_len' | 'context_handle' | 'string' | 'public' | 'noprint' | 'relative' | 'nodiscriminant' | 'subcontext' | 'byte_count_pointer' '(' expression ')' {{ "$item[1]" => "$item{expression}" }} | 'size_is' '(' expression ')' {{ "$item[1]" => "$item{expression}" }} | 'length_is' '(' expression ')' {{ "$item[1]" => "$item{expression}" }} | 'switch_is' '(' expression ')' {{ "$item[1]" => "$item{expression}" }} | 'value' '(' anytext ')' {{ "$item[1]" => "$item{anytext}" }} | 'switch_type' '(' type ')' {{ "$item[1]" => $item{type} }} identifier: /[\w?]+/ expression: /[\w.?\/+*-_]+/ function : type identifier '(' element_list2 ');' {{ "TYPE" => "FUNCTION", "NAME" => $item{identifier}, "RETURN_TYPE" => $item{type}, "DATA" => $item{element_list2} }} | type : 'unsigned' type { "$item[1] $item[2]" } | 'long' { $item[1] } | 'string' { $item[1] } | 'wchar_t' { $item[1] } | struct { $item[1] } | union { $item[1] } | identifier { $item[1] } | text: /[\w\s\..?-]*/ text2: /[\w\s\*\>\/\..?-]*/ anytext: text2 '(' anytext ')' anytext {{ "$item[1]($item[4])$item[6]" }} | text2 '+' anytext {{ "$item[1]+$item[3]" }} | text2 call: expression '(' expression ')' {{ "$item[1]($item[4])" }} constant: /-?\d+/ | '*' cpp_prefix: '#' /.*/