{ use util; } idl: cpp_prefix(s?) module_header interface { [$item{module_header}, $item{interface}] } | module_header: '[' module_param(s? /,/) ']' {{ "TYPE" => "MODULEHEADER", "PROPERTIES" => 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] } | const { $item[1] } const : 'const' identifier identifier '=' constant ';' {{ "TYPE" => "CONST", "DTYPE" => $item[3], "NAME" => $item[4], "VALUE" => $item{constant} }} | typedef : 'typedef' type identifier array_len(?) ';' {{ "TYPE" => "TYPEDEF", "NAME" => $item{identifier}, "DATA" => $item{type}, "ARRAY_LEN" => $item[5][0] }} | enum: 'enum' '{' enum_element(s? /,/) '}' {{ "TYPE" => "ENUM", "ELEMENTS" => $item[4] }} | enum_element: /[\w\s=]+/ 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' '(' identifier ')' ']' base_element ';' {{ "TYPE" => "UNION_ELEMENT", "CASE" => $item{identifier}, "DATA" => $item{base_element} }} | '[' 'case' '(' identifier ')' ']' ';' {{ "TYPE" => "EMPTY", "CASE" => $item{identifier}, }} | '[' 'default' ']' base_element ';' {{ "TYPE" => "UNION_ELEMENT", "CASE" => "default", "DATA" => $item{base_element} }} | '[' 'default' ']' ';' {{ "TYPE" => "EMPTY", "CASE" => "default", }} 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: '[' ']' { "*" } | '[' '*' ']' { "*" } | '[' anytext ']' { "$item{anytext}" } | 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' | 'public' | 'noprint' | 'relative' | 'nodiscriminant' | 'subcontext' '(' constant ')' {{ "$item[1]" => "$item{constant}" }} | 'flag' '(' anytext ')' {{ "$item[1]" => "$item{anytext}" }} | '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}" }} identifier: /[\w?]+/ expression: /[\w.?\/+*-_]+/ function : type identifier '(' element_list2 ');' {{ "TYPE" => "FUNCTION", "NAME" => $item{identifier}, "RETURN_TYPE" => $item{type}, "DATA" => $item{element_list2} }} | type : struct { $item[1] } | union { $item[1] } | enum { $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 constant: /-?[\dx]+/ | '*' cpp_prefix: '#' /.*/