File Coverage

blib/lib/MarpaX/Languages/IDL/AST.pm
Criterion Covered Total %
statement 114 119 95.8
branch 13 26 50.0
condition 16 37 43.2
subroutine 20 20 100.0
pod 5 5 100.0
total 168 207 81.1


line stmt bran cond sub pod time code
1 1     1   48313 use strict;
  1         2  
  1         24  
2 1     1   3 use warnings FATAL => 'all';
  1         1  
  1         35  
3              
4             package MarpaX::Languages::IDL::AST;
5 1     1   301 use MarpaX::Languages::IDL::AST::Value;
  1         1  
  1         22  
6 1     1   300 use MarpaX::Languages::IDL::AST::Util;
  1         2  
  1         22  
7 1     1   3 use Scalar::Util qw/blessed reftype refaddr/;
  1         1  
  1         40  
8 1     1   469 use Data::Dumper;
  1         6284  
  1         44  
9 1     1   428 use Template;
  1         13054  
  1         27  
10 1     1   6 use Template::Constants qw/:chomp :debug/;
  1         0  
  1         177  
11 1     1   416 use File::ShareDir qw/dist_dir/;
  1         4398  
  1         51  
12 1     1   4 use Config;
  1         1  
  1         32  
13 1     1   353 use Data::Scan;
  1         73999  
  1         55  
14              
15             # ABSTRACT: Translate an IDL source to an AST
16              
17             our $VERSION = '0.007'; # VERSION
18              
19              
20 1     1   6 use Carp qw/carp croak/;
  1         1  
  1         56  
21 1     1   399 use Marpa::R2 qw//;
  1         96275  
  1         33  
22 1     1   6 use File::Basename qw/basename fileparse/;
  1         2  
  1         66  
23 1     1   4 use File::Spec::Functions qw/case_tolerant rel2abs catdir/;
  1         1  
  1         746  
24              
25             our $BLESS_PACKAGE = 'IDL::AST';
26             our $DATA = do {local $/; <DATA>};
27             our $G = Marpa::R2::Scanless::G->new({source => \$DATA, bless_package => $BLESS_PACKAGE});
28             # Marpa follows Unicode recommendation, i.e. perl's \R, that cannot be in a character class
29             our $NEWLINE_REGEXP = qr/(?>\x0D\x0A|\v)/;
30              
31              
32             sub new {
33 1     1 1 99 my ($class) = @_;
34              
35 1         3 my $self = {
36             };
37              
38 1         2 bless($self, $class);
39              
40 1         2 return $self;
41             }
42              
43              
44             sub parse {
45 1     1 1 9 my ($self, $input, $hashOptPtr) = @_;
46             #
47             # Parameters check
48             #
49 1   50     6 $hashOptPtr //= {};
50 1 50       4 if (ref($hashOptPtr) ne 'HASH') {
51 0         0 croak '3rd argument must be a pointer to HASH containing any Marpa::R2::Scanles::R option, except the grammar option';
52             }
53 1         3 foreach (qw/grammar semantics_package/) {
54 2 50       7 if (exists($hashOptPtr->{$_})) {
55 0         0 delete($hashOptPtr->{$_});
56             }
57             }
58 1         1 my $datap;
59 1 50       3 if (! ref($input)) {
60             #
61             # Assume this is a filename
62             # IDL wants the filename to end with .idl
63             #
64 1         69 my ($filename, $directories, $suffix) = fileparse($input, qr/\.[^.]*/);
65 1 50       5 if (( case_tolerant() && (lc($suffix) ne '.idl')) ||
66             (! case_tolerant() && ( $suffix ne '.idl'))) {
67 0         0 carp "$input does not end with .idl";
68             }
69             #
70             # Load data
71             #
72 1 50       33 open(my $fh, '<', $input) || croak "Failed to open $input, $!";
73 1         2 my $data = do { local $/; <$fh> };
  1         3  
  1         23  
74 1 50       8 close($fh) || warn "Failed to close $input, $!";
75 1         4 $datap = \$data;
76             } else {
77             #
78             # Assume this is the data to parse
79             #
80 0         0 $datap = $input;
81             }
82             #
83             # Recognizer
84             #
85             my $recce = Marpa::R2::Scanless::R->new({grammar => $G,
86             # trace_terminals => 1,
87             semantics_package => 'MarpaX::Languages::IDL::AST::Value',
88 1         3 %{$hashOptPtr}});
  1         15  
89 1         296 $recce->read($datap);
90             #
91             # AST value
92             #
93 1         94173 my $value = $recce->value();
94 1 50 33     167 croak 'Undefined AST value' if (! defined($value) || ! defined(${$value}));
  1         4  
95             #
96             # We want a single value
97             #
98 1         5 my $nextValue = $recce->value();
99 1 50       175 croak 'Ambiguous AST' if (defined($nextValue));
100             #
101             # Let's remember the latest AST
102             #
103 1         1 $self->{_ast} = ${$value};
  1         9  
104              
105 1         450 return $self;
106             }
107              
108              
109             sub ast {
110 1     1 1 2 my ($self) = @_;
111              
112 1         6 return $self->{_ast};
113             }
114              
115              
116             sub output {
117 1     1 1 4038 my ($self) = @_;
118              
119 1         6 return $self->{_output};
120             }
121              
122              
123             sub generate {
124 1     1 1 9 my ($self, $ast, $template, $targetOptionHashp) = @_;
125              
126 1   33     10 $ast //= $self->ast();
127 1   50     8 $template //= 'perl5.tt2';
128 1   50     18 $targetOptionHashp //= {};
129             #
130             # We provide a default style only if this is a template we know about
131             #
132 1         2 my $style = $targetOptionHashp->{style};
133 1         2 my $addDefaultStyleInIncludePath = '';
134 1         2 my $packageDist = __PACKAGE__;
135 1         8 $packageDist =~ s/::/-/g;
136 1         8 my $distDir = dist_dir($packageDist);
137 1 50       160 if (! defined($style)) {
138 1 50       4 if ($template eq 'perl5.tt2') {
139 1         2 $style = 'Moose';
140 1         5 $addDefaultStyleInIncludePath = catdir($distDir, 'perl5', 'style', $style);
141             }
142             }
143              
144 1 50       4 if (ref($targetOptionHashp) ne 'HASH') {
145 0         0 croak '3rd argument must be a pointer to HASH';
146             }
147              
148 1         2 my $ttOptionHashp = $targetOptionHashp->{tt};
149 1   50     7 $ttOptionHashp->{STRICT} //= 1;
150 1   33     18 $ttOptionHashp->{DELIMITER} //= $Config{path_sep};
151 1   50     6 $ttOptionHashp->{INCLUDE_PATH} //= '';
152 1         4 $ttOptionHashp->{INCLUDE_PATH} .= $ttOptionHashp->{DELIMITER} . $distDir;
153 1 50       4 if ($addDefaultStyleInIncludePath) {
154 1         3 $ttOptionHashp->{INCLUDE_PATH} .= $ttOptionHashp->{DELIMITER} . $addDefaultStyleInIncludePath;
155             }
156 1   50     4 $ttOptionHashp->{INTERPOLATE} //= 1;
157 1   50     4 $ttOptionHashp->{EVAL_PERL} //= 1;
158 1   50     4 $ttOptionHashp->{PRE_CHOMP} //= CHOMP_NONE;
159 1   50     4 $ttOptionHashp->{POST_CHOMP} //= CHOMP_NONE;
160 1   50     6 $ttOptionHashp->{RELATIVE} //= 1;
161 1         1 local $Template::Directive::WHILE_MAX = 1000000000;
162 1   33     14 my $tt = Template->new($ttOptionHashp) || croak "$Template::ERROR";
163              
164             #
165             # The semantics for our TT templates is to provide a hash with
166             # a reference to a scratchpad hash (free to use) and the AST
167             #
168 1         15743 my $ttVarsHashp = $targetOptionHashp->{vars};
169             #
170             # Our hooks
171             #
172 1   33     8 $ttVarsHashp->{ast} //= $ast;
173 1   50     6 $ttVarsHashp->{nativeFloat} = $targetOptionHashp->{nativeFloat} // 1;
174 1         3 $ttVarsHashp->{style} = $style;
175              
176 1         3 $self->{_output} = '';
177 1 50       6 $tt->process($template, $ttVarsHashp, \$self->{_output}) || croak $tt->error();
178              
179 1         608 return $self;
180             }
181              
182              
183              
184             1;
185              
186             =pod
187              
188             =encoding UTF-8
189              
190             =head1 NAME
191              
192             MarpaX::Languages::IDL::AST - Translate an IDL source to an AST
193              
194             =head1 VERSION
195              
196             version 0.007
197              
198             =head1 SYNOPSIS
199              
200             use MarpaX::Languages::IDL::AST;
201              
202             my $idlPath = 'source.idl';
203             my $ast = MarpaX::Languages::IDL::AST->new()->parse($idlPath)->validate();
204              
205             =head2 $class->new()
206              
207             Instantiate a new object. Returns a reference to it, denoted $self hereafter.
208              
209             =head2 $self->parse($path, $hashOptPtr)
210              
211             Parse the IDL and produce an AST out of it, then a meta-AST that is more useful representation for further processing. Takes as parameters:
212              
213             =over
214              
215             =item $path
216              
217             A required IDL pathname.
218              
219             =item $hashOptPtr
220              
221             An optional reference to a hash containing Marpa::R2::Scanless::R() parameters, except the grammar and semantics_package options.
222              
223             =back
224              
225             The AST is an exact representation of the parse tree value of the IDL grammar contained in this package, except:
226              
227             =over
228              
229             =item scopedName
230              
231             Original grammar rule is:
232              
233             <scopedName> ::= <identifier> | '::' <identifier> | <scopedName> '::' <identifier>
234              
235             and has been rewriten to:
236              
237             <scopedName> ::= <identifier>+ separator => <coloncolon>
238              
239             A dedicated action rule will concatenate all identifiers into a single string, giving the impression that scopedName is a token (accurate terminology is a lexeme). I.e. the scopedName value in the AST is in the form:
240              
241             bless([start,totalLength,concatenatedValue], 'IDL::AST::scopedName')
242              
243             alike the identifier.
244              
245             =back
246              
247             This method returns $self.
248              
249             =head2 $self->ast()
250              
251             Returns the latest AST produced by $self->parse().
252              
253             =head2 $self->output()
254              
255             Returns the latest output produced by $self->generate().
256              
257             =head2 $self->generate($ast, $template, $targetOptionHashp)
258              
259             Generate files for the given AST $ast.
260              
261             =over
262              
263             =item $ast
264              
265             AST as produced by the method $self->parse(). Default to $self->ast().
266              
267             =item $template
268              
269             Template-Toolkit template name. Default to 'perl5.tt2', available in this distribution.
270              
271             =item $targetOptionHashp
272              
273             Hash reference of options specific to target $target.
274              
275             =back
276              
277             This method returns $self.
278              
279             =head1 DESCRIPTION
280              
281             This module provide and manage an AST of an IDL file, as per OMG's IDL 3.5 grammar specification.
282              
283             =head1 NOTES
284              
285             IDL version is 3.5 as of L<OMG IDL3.5 Specification|http://www.omg.org/spec/IDL35/3.5/>.
286              
287             This specification imposes input to come from a filename, with suffix '.idl'.
288              
289             Any preprocessing feature is ignored, and eventual multi-line proprocessing directives are likely to cause failure. Since the most expected preprocessing tokens are #include, #ifdef, and al., the user is expected to have already run a preprocessor before using this package.
290              
291             =head1 SEE ALSO
292              
293             L<Marpa::R2>
294              
295             =for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
296              
297             =head1 SUPPORT
298              
299             =head2 Bugs / Feature Requests
300              
301             Please report any bugs or feature requests through the issue tracker
302             at L<https://rt.cpan.org/Public/Dist/Display.html?Name=MarpaX-Languages-IDL-AST>.
303             You will be notified automatically of any progress on your issue.
304              
305             =head2 Source Code
306              
307             This is open source software. The code repository is available for
308             public review and contribution under the terms of the license.
309              
310             L<https://github.com/jddurand/marpax-languages-idl-ast>
311              
312             git clone git://github.com/jddurand/marpax-languages-idl-ast.git
313              
314             =head1 AUTHOR
315              
316             Jean-Damien Durand <jeandamiendurand@free.fr>
317              
318             =head1 COPYRIGHT AND LICENSE
319              
320             This software is copyright (c) 2014 by Jean-Damien Durand.
321              
322             This is free software; you can redistribute it and/or modify it under
323             the same terms as the Perl 5 programming language system itself.
324              
325             =cut
326              
327             __DATA__
328             :default ::= action => [values] bless => ::lhs
329             lexeme default = action => [ start, length, value ] latm => 1 bless => ::name
330              
331             :start ::= <specification>
332              
333             <specification> ::= <supportedCppCommandAny> <importAny> <definitionMany> <supportedCppCommandAny>
334             <supportedCppCommandAny> ::= <supportedCppCommand>*
335             <supportedCppCommand> ::= CPPSTYLEDIRECTIVE
336             <definition> ::= <typeDcl> SEMICOLON
337             | <constDcl> SEMICOLON
338             | <exceptDcl> SEMICOLON
339             | <interface> SEMICOLON
340             | <module> SEMICOLON
341             | <value> SEMICOLON
342             | <typeIdDcl> SEMICOLON
343             | <typePrefixDcl> SEMICOLON
344             | <event> SEMICOLON
345             | <component> SEMICOLON
346             | <homeDcl> SEMICOLON
347             <module> ::= MODULE <identifier> LCURLY <definitionMany> RCURLY
348             <interface> ::= <interfaceDcl>
349             | <forwardDcl>
350             <interfaceDcl> ::= <interfaceHeader> LCURLY <interfaceBody> RCURLY
351             <forwardDcl> ::= <abstractOrLocalMaybe> INTERFACE <identifier>
352             <interfaceHeader> ::= <abstractOrLocalMaybe> INTERFACE <identifier> <interfaceInheritanceSpecMaybe>
353             <interfaceBody> ::= <export>*
354             <export> ::= <typeDcl> SEMICOLON
355             | <constDcl> SEMICOLON
356             | <exceptDcl> SEMICOLON
357             | <attrDcl> SEMICOLON
358             | <opDcl> SEMICOLON
359             | <typeIdDcl> SEMICOLON
360             | <typePrefixDcl> SEMICOLON
361             <interfaceInheritanceSpec> ::= COLON <interfaceNameListMany>
362             <interfaceName> ::= <scopedName>
363             #<scopedName> ::= <identifier>
364             # | COLONCOLON <identifier>
365             # | <scopedName> COLONCOLON <identifier>
366             <scopedName> ::= <identifier>+ separator => <coloncolon> action => _scopedName
367             <value> ::= <valueDcl>
368             | <valueAbsDcl>
369             | <valueBoxDcl>
370             | <valueForwardDcl>
371             <valueForwardDcl> ::= <abstractMaybe> VALUETYPE <identifier>
372             <valueBoxDcl> ::= VALUETYPE <identifier> <typeSpec>
373             <valueAbsDcl> ::= ABSTRACT VALUETYPE <identifier> <valueInheritanceSpecMaybe> LCURLY <exportAny> RCURLY
374             <valueDcl> ::= <valueHeader> LCURLY <valueElementAny> RCURLY
375             <valueHeader> ::= <customMaybe> VALUETYPE <identifier> <valueInheritanceSpecMaybe>
376             <valueInheritanceSpec> ::= <valueInheritanceSpec1ValuesMaybe> <valueInheritanceSpec2InterfacesMaybe>
377             <valueName> ::= <scopedName>
378             <valueElement> ::= <export>
379             | <stateMember>
380             | <initDcl>
381             <stateMember> ::= <publicOrPrivate> <typeSpec> <declarators> SEMICOLON
382             <initDcl> ::= FACTORY <identifier> LPAREN <initParamDeclsMaybe> RPAREN <raisesExprMaybe> SEMICOLON
383             <initParamDecls> ::= <initParamDeclListMany>
384             <initParamDecl> ::= <initParamAttribute> <paramTypeSpec> <simpleDeclarator>
385             <initParamAttribute> ::= IN
386             <constDcl> ::= CONST <constType> <identifier> EQUAL <constExp>
387             <constType> ::= <integerType>
388             | <charType>
389             | <wideCharType>
390             | <booleanType>
391             | <floatingPtType>
392             | <stringType>
393             | <wideStringType>
394             | <fixedPtConstType>
395             | <scopedName>
396             | <octetType>
397             <constExp> ::= <orExpr>
398             <orExpr> ::= <xorExpr>
399             | <orExpr> OR <xorExpr>
400             <xorExpr> ::= <andExpr>
401             | <xorExpr> XOR <andExpr>
402             <andExpr> ::= <shiftExpr>
403             | <andExpr> AND <shiftExpr>
404             <shiftExpr> ::= <addExpr>
405             | <shiftExpr> RSHIFT <addExpr>
406             | <shiftExpr> LSHIFT <addExpr>
407             <addExpr> ::= <multExpr>
408             | <addExpr> PLUS <multExpr>
409             | <addExpr> MINUS <multExpr>
410             <multExpr> ::= <unaryExpr>
411             | <multExpr> MUL <unaryExpr>
412             | <multExpr> DIV <unaryExpr>
413             | <multExpr> MOD <unaryExpr>
414             <unaryExpr> ::= <unaryOperator> <primaryExpr>
415             | <primaryExpr>
416             <unaryOperator> ::= MINUS
417             | PLUS
418             | TILDE
419             <primaryExpr> ::= <scopedName>
420             | <literal>
421             | LPAREN <constExp> RPAREN
422             <literal> ::= <integerLiteral>
423             | <stringLiteral>
424             | <wideStringLiteral>
425             | <characterLiteral>
426             | <wideCharacterLiteral>
427             | <fixedPtLiteral>
428             | <floatingPtLiteral>
429             | <booleanLiteral>
430             <booleanLiteral> ::= TRUE
431             | FALSE
432             <positiveIntConst> ::= <constExp>
433             <typeDcl> ::= TYPEDEF <typeDeclarator>
434             | <structType>
435             | <unionType>
436             | <enumType>
437             | NATIVE <simpleDeclarator>
438             | <constrForwardDecl>
439             <typeDeclarator> ::= <typeSpec> <declarators>
440             <typeSpec> ::= <simpleTypeSpec>
441             | <constrTypeSpec>
442             <simpleTypeSpec> ::= <baseTypeSpec>
443             | <templateTypeSpec>
444             | <scopedName>
445             <baseTypeSpec> ::= <floatingPtType>
446             | <integerType>
447             | <charType>
448             | <wideCharType>
449             | <booleanType>
450             | <octetType>
451             | <anyType>
452             | <objectType>
453             | <valueBaseType>
454             <templateTypeSpec> ::= <sequenceType>
455             | <stringType>
456             | <wideStringType>
457             | <fixedPtType>
458             <constrTypeSpec> ::= <structType>
459             | <unionType>
460             | <enumType>
461             <declarators> ::= <declaratorListMany>
462             <declarator> ::= <simpleDeclarator>
463             | <complexDeclarator>
464             <simpleDeclarator> ::= <identifier>
465             <complexDeclarator> ::= <arrayDeclarator>
466             <floatingPtType> ::= FLOAT
467             | DOUBLE
468             | LONG DOUBLE
469             <integerType> ::= <signedInt>
470             | <unsignedInt>
471             <signedInt> ::= <signedShortInt>
472             | <signedLongInt>
473             | <signedLonglongInt>
474             <signedShortInt> ::= SHORT
475             <signedLongInt> ::= LONG
476             <signedLonglongInt> ::= LONG LONG
477             <unsignedInt> ::= <unsignedShortInt>
478             | <unsignedLongInt>
479             | <unsignedLonglongInt>
480             <unsignedShortInt> ::= UNSIGNED SHORT
481             <unsignedLongInt> ::= UNSIGNED LONG
482             <unsignedLonglongInt> ::= UNSIGNED LONG LONG
483             <charType> ::= CHAR
484             <wideCharType> ::= WCHAR
485             <booleanType> ::= BOOLEAN
486             <octetType> ::= OCTET
487             <anyType> ::= ANY
488             <objectType> ::= OBJECT
489             <structType> ::= STRUCT <identifier> LCURLY <memberList> RCURLY
490             <memberList> ::= <member>+
491             <member> ::= <typeSpec> <declarators> SEMICOLON
492             <unionType> ::= UNION <identifier> SWITCH LPAREN <switchTypeSpec> RPAREN LCURLY <switchBody> RCURLY
493             <switchTypeSpec> ::= <integerType>
494             | <charType>
495             | <booleanType>
496             | <enumType>
497             | <scopedName>
498             <switchBody> ::= <case>+
499             <case> ::= <caseLabelMany> <elementSpec> SEMICOLON
500             <caseLabel> ::= CASE <constExp> COLON
501             | DEFAULT COLON
502             <elementSpec> ::= <typeSpec> <declarator>
503             <enumType> ::= ENUM <identifier> LCURLY <enumeratorListMany> RCURLY
504             <enumerator> ::= <identifier>
505             <sequenceType> ::= SEQUENCE LT <simpleTypeSpec> COMMA <positiveIntConst> GT
506             | SEQUENCE LT <simpleTypeSpec> GT
507             <stringType> ::= STRING LT <positiveIntConst> GT
508             | STRING
509             <wideStringType> ::= WSTRING LT <positiveIntConst> GT
510             | WSTRING
511             <arrayDeclarator> ::= <identifier> <fixedArraySizeMany>
512             <fixedArraySize> ::= LBRACKET <positiveIntConst> RBRACKET
513             <attrDcl> ::= <readonlyAttrSpec>
514             | <attrSpec>
515             <exceptDcl> ::= EXCEPTION <identifier> LCURLY <memberAny> RCURLY
516             <opDcl> ::= <opAttributeMaybe> <opTypeSpec> <identifier> <parameterDcls> <raisesExprMaybe> <contextExprMaybe>
517             <opAttribute> ::= ONEWAY
518             <opTypeSpec> ::= <paramTypeSpec>
519             | VOID
520             <parameterDcls> ::= LPAREN <paramDclListMany> RPAREN
521             | LPAREN RPAREN
522             <paramDcl> ::= <paramAttribute> <paramTypeSpec> <simpleDeclarator>
523             <paramAttribute> ::= IN
524             | OUT
525             | INOUT
526             <raisesExpr> ::= RAISES LPAREN <scopedNameListMany> RPAREN
527             <contextExpr> ::= CONTEXT LPAREN <stringLiteralListMany> RPAREN
528             <paramTypeSpec> ::= <baseTypeSpec>
529             | <stringType>
530             | <wideStringType>
531             | <scopedName>
532             <fixedPtType> ::= FIXED LT <positiveIntConst> COMMA <positiveIntConst> GT
533             <fixedPtConstType> ::= FIXED
534             <valueBaseType> ::= VALUEBASE
535             <constrForwardDecl> ::= STRUCT <identifier>
536             | UNION <identifier>
537             <import> ::= IMPORT <importedScope> SEMICOLON
538             <importedScope> ::= <scopedName>
539             | <stringLiteral>
540             <typeIdDcl> ::= TYPEID <scopedName> <stringLiteral>
541             <typePrefixDcl> ::= TYPEPREFIX <scopedName> <stringLiteral>
542             <readonlyAttrSpec> ::= READONLY ATTRIBUTE <paramTypeSpec> <readonlyAttrDeclarator>
543             <readonlyAttrDeclarator> ::= <simpleDeclarator> <raisesExpr>
544             | <simpleDeclaratorListMany>
545             <attrSpec> ::= ATTRIBUTE <paramTypeSpec> <attrDeclarator>
546             <attrDeclarator> ::= <simpleDeclarator> <attrRaisesExpr>
547             | <simpleDeclaratorListMany>
548             <attrRaisesExpr> ::= <getExcepExpr> <setExcepExprMaybe>
549             | <setExcepExpr>
550             <getExcepExpr> ::= GETRAISES <exceptionList>
551             <setExcepExpr> ::= SETRAISES <exceptionList>
552             <exceptionList> ::= LPAREN <scopedNameListMany> RPAREN
553              
554             # NOTE: Grammar rules 1 through 111 with the exception of the last three lines of rule 2 constitutes the portion of IDL that
555             # is not related to components.
556              
557             <component> ::= <componentDcl>
558             | <componentForwardDcl>
559             <componentForwardDcl> ::= COMPONENT <identifier>
560             <componentDcl> ::= <componentHeader> LCURLY <componentBody> RCURLY
561             <componentHeader> ::= COMPONENT <identifier> <componentInheritanceSpecMaybe> <supportedInterfaceSpecMaybe>
562             <supportedInterfaceSpec> ::= SUPPORTS <scopedNameListMany>
563             <componentInheritanceSpec> ::= COLON <scopedName>
564             <componentBody> ::= <componentExport>*
565             <componentExport> ::= <providesDcl> SEMICOLON
566             | <usesDcl> SEMICOLON
567             | <emitsDcl> SEMICOLON
568             | <publishesDcl> SEMICOLON
569             | <consumesDcl> SEMICOLON
570             | <attrDcl> SEMICOLON
571             <providesDcl> ::= PROVIDES <interfaceType> <identifier>
572             <interfaceType> ::= <scopedName>
573             | OBJECT
574             <usesDcl> ::= USES <multipleMaybe> <interfaceType> <identifier>
575             <emitsDcl> ::= EMITS <scopedName> <identifier>
576             <publishesDcl> ::= PUBLISHES <scopedName> <identifier>
577             <consumesDcl> ::= CONSUMES <scopedName> <identifier>
578             <homeDcl> ::= <homeHeader> <homeBody>
579             <homeHeader> ::= HOME <identifier> <homeInheritanceSpecMaybe> <supportedInterfaceSpecMaybe> MANAGES <scopedName> <primaryKeySpecMaybe>
580             <homeIinheritanceSpec> ::= COLON <scopedName>
581             <primaryKeySpec> ::= PRIMARYKEY <scopedName>
582             <homeBody> ::= LCURLY <homeExportAny> RCURLY
583             <homeExport> ::= <export>
584             | <factoryDcl> SEMICOLON
585             | <finderDcl> SEMICOLON
586             <factoryDcl> ::= FACTORY <identifier> LPAREN [ <initParamDecls> ] RPAREN <raisesExprMaybe>
587             <finderDcl> ::= FINDER <identifier> LPAREN [ <initParamDecls> ] RPAREN <raisesExprMaybe>
588             <event> ::= <eventDcl>
589             | <eventAbsDcl>
590             | <eventForwardDcl>
591             <eventForwardDcl> ::= <abstractMaybe> EVENTTYPE <identifier>
592             <eventAbsDcl> ::= ABSTRACT EVENTTYPE <identifier> <valueInheritanceSpecMaybe> LCURLY <exportAny> RCURLY
593             <eventDcl> ::= <eventHeader> LCURLY <valueElementAny> RCURLY
594             <eventHeader> ::= <customMaybe> EVENTTYPE <identifier> <valueInheritanceSpecMaybe>
595              
596             <importAny> ::= <import>*
597             <definitionMany> ::= <definition>+
598             <abstractOrLocal> ::= ABSTRACT | LOCAL
599             <abstractOrLocalMaybe> ::= <abstractOrLocal>
600             <abstractOrLocalMaybe> ::=
601             <interfaceInheritanceSpecMaybe> ::= <interfaceInheritanceSpec>
602             <interfaceInheritanceSpecMaybe> ::=
603             <interfaceNameListMany> ::= <interfaceName>+ separator => <comma>
604             <abstractMaybe> ::= ABSTRACT
605             <abstractMaybe> ::=
606             <valueInheritanceSpecMaybe> ::= <valueInheritanceSpec>
607             <valueInheritanceSpecMaybe> ::=
608             <exportAny> ::= <export>*
609             <valueElementAny> ::= <valueElement>*
610             <customMaybe> ::= CUSTOM
611             <customMaybe> ::=
612             <valueNameListMany> ::= <valueName>+ separator => <comma>
613             <truncatableMaybe> ::= TRUNCATABLE
614             <truncatableMaybe> ::=
615             <valueInheritanceSpec1Values> ::= COLON <truncatableMaybe> <valueNameListMany>
616             <valueInheritanceSpec1ValuesMaybe> ::= <valueInheritanceSpec1Values>
617             <valueInheritanceSpec1ValuesMaybe> ::=
618             <valueInheritanceSpec2Interfaces> ::= SUPPORTS <interfaceNameListMany>
619             <valueInheritanceSpec2InterfacesMaybe> ::= <valueInheritanceSpec2Interfaces>
620             <valueInheritanceSpec2InterfacesMaybe> ::=
621             <publicOrPrivate> ::= PUBLIC | PRIVATE
622             <initParamDeclsMaybe> ::= <initParamDecls>
623             <initParamDeclsMaybe> ::=
624             <raisesExprMaybe> ::= <raisesExpr>
625             <raisesExprMaybe> ::=
626             <initParamDeclListMany> ::= <initParamDecl>+ separator => <comma>
627             <declaratorListMany> ::= <declarator>+ separator => <comma>
628             <caseLabelMany> ::= <caseLabel>+
629             <enumeratorListMany> ::= <enumerator>+ separator => <comma>
630             <fixedArraySizeMany> ::= <fixedArraySize>+
631             <memberAny> ::= <member>*
632             <opAttributeMaybe> ::= <opAttribute>
633             <opAttributeMaybe> ::=
634             <contextExprMaybe> ::= <contextExpr>
635             <contextExprMaybe> ::=
636             <paramDclListMany> ::= <paramDcl>+ separator => <comma>
637             <scopedNameListMany> ::= <scopedName>+ separator => <comma>
638             <stringLiteralListMany> ::= <stringLiteral>+ separator => <comma>
639             <simpleDeclaratorListMany> ::= <simpleDeclarator>+ separator => <comma>
640             <setExcepExprMaybe> ::= <setExcepExpr>
641             <setExcepExprMaybe> ::=
642             <componentInheritanceSpecMaybe> ::= <componentInheritanceSpec>
643             <componentInheritanceSpecMaybe> ::=
644             <supportedInterfaceSpecMaybe> ::= <supportedInterfaceSpec>
645             <supportedInterfaceSpecMaybe> ::=
646             <multipleMaybe> ::= MULTIPLE
647             <multipleMaybe> ::=
648             <homeInheritanceSpecMaybe> ::= <homeIinheritanceSpec>
649             <homeInheritanceSpecMaybe> ::=
650             <primaryKeySpecMaybe> ::= <primaryKeySpec>
651             <primaryKeySpecMaybe> ::=
652             <homeExportAny> ::= <homeExport>*
653             <comma> ::= COMMA
654             <coloncolon> ::= COLONCOLON
655              
656             #
657             # Everything hardcoded is a lexeme, we want to have it blessed into an array
658             # The following is an exhaustive list of all IDL 3.5 keywords
659             #
660             SEMICOLON ~ ';'
661             MODULE ~ 'module'
662             LCURLY ~ '{'
663             RCURLY ~ '}'
664             INTERFACE ~ 'interface'
665             COLON ~ ':'
666             COLONCOLON ~ '::'
667             VALUETYPE ~ 'valuetype'
668             ABSTRACT ~ 'abstract'
669             FACTORY ~ 'factory'
670             LPAREN ~ '('
671             RPAREN ~ ')'
672             IN ~ 'in'
673             CONST ~ 'const'
674             EQUAL ~ '='
675             OR ~ '|'
676             XOR ~ '^'
677             AND ~ '&'
678             RSHIFT ~ '>>'
679             LSHIFT ~ '<<'
680             PLUS ~ '+'
681             MINUS ~ '-'
682             TILDE ~ '~'
683             MUL ~ '*'
684             DIV ~ '/'
685             MOD ~ '%'
686             TRUE ~ 'TRUE'
687             FALSE ~ 'FALSE'
688             TYPEDEF ~ 'typedef'
689             NATIVE ~ 'native'
690             FLOAT ~ 'float'
691             DOUBLE ~ 'double'
692             LONG ~ 'long'
693             SHORT ~ 'short'
694             UNSIGNED ~ 'unsigned'
695             CHAR ~ 'char'
696             WCHAR ~ 'wchar'
697             BOOLEAN ~ 'boolean'
698             OCTET ~ 'octet'
699             ANY ~ 'any'
700             OBJECT ~ 'Object'
701             STRUCT ~ 'struct'
702             UNION ~ 'union'
703             CASE ~ 'case'
704             DEFAULT ~ 'default'
705             ENUM ~ 'enum'
706             SEQUENCE ~ 'sequence'
707             LT ~ '<'
708             GT ~ '>'
709             SWITCH ~ 'switch'
710             COMMA ~ ','
711             STRING ~ 'string'
712             WSTRING ~ 'wstring'
713             LBRACKET ~ '['
714             RBRACKET ~ ']'
715             EXCEPTION ~ 'exception'
716             ONEWAY ~ 'oneway'
717             VOID ~ 'void'
718             OUT ~ 'out'
719             INOUT ~ 'inout'
720             RAISES ~ 'raises'
721             CONTEXT ~ 'context'
722             FIXED ~ 'fixed'
723             VALUEBASE ~ 'ValueBase'
724             IMPORT ~ 'import'
725             TYPEID ~ 'typeid'
726             TYPEPREFIX ~ 'typeprefix'
727             READONLY ~ 'readonly'
728             ATTRIBUTE ~ 'attribute'
729             GETRAISES ~ 'getraises'
730             SETRAISES ~ 'setraises'
731             COMPONENT ~ 'component'
732             SUPPORTS ~ 'supports'
733             PROVIDES ~ 'provides'
734             USES ~ 'uses'
735             EMITS ~ 'emits'
736             PUBLISHES ~ 'publishes'
737             CONSUMES ~ 'consumes'
738             HOME ~ 'home'
739             MANAGES ~ 'manages'
740             PRIMARYKEY ~ 'primarykey'
741             FINDER ~ 'finder'
742             EVENTTYPE ~ 'eventtype'
743             LOCAL ~ 'local'
744             CUSTOM ~ 'custom'
745             TRUNCATABLE ~ 'truncatable'
746             PUBLIC ~ 'public'
747             PRIVATE ~ 'private'
748             MULTIPLE ~ 'multiple'
749             #
750             # Copied from C language
751             #
752             <stringLiteral> ::= STRINGLITERALUNIT+
753             :lexeme ~ <STRINGLITERALUNIT>
754             STRING_LITERAL_INSIDE ~ [^"\\\n]
755             STRING_LITERAL_INSIDE ~ ES
756             STRING_LITERAL_INSIDE_any ~ STRING_LITERAL_INSIDE*
757             STRINGLITERALUNIT ~ SP_maybe '"' STRING_LITERAL_INSIDE_any '"' WS_any
758              
759             <wideStringLiteral> ::= WIDESTRINGLITERALUNIT+
760             :lexeme ~ <WIDESTRINGLITERALUNIT>
761             WIDESTRINGLITERALUNIT ~ SP_maybe 'L"' STRING_LITERAL_INSIDE_any '"' WS_any
762              
763             <integerLiteral> ::= ICONSTANT
764             :lexeme ~ <ICONSTANT>
765             ICONSTANT ~ HP H_many IS_maybe
766             | BP B_many IS_maybe # Gcc extension: binary constants
767             | NZ D_any IS_maybe
768             | '0' O_any IS_maybe
769             I_CONSTANT_INSIDE ~ [^'\\\n]
770             I_CONSTANT_INSIDE ~ ES
771             I_CONSTANT_INSIDE_many ~ I_CONSTANT_INSIDE+
772              
773             <identifier> ::= IDENTIFIER
774             :lexeme ~ <IDENTIFIER> priority => -1
775              
776             IDENTIFIER ~ L A_any
777              
778             #
779             # Original C includes this definition in ICONSTANT
780             #
781             <characterLiteral> ::= CHARACTERLITERAL
782             :lexeme ~ <CHARACTERLITERAL>
783             CHARACTERLITERAL ~ CP_maybe QUOTE I_CONSTANT_INSIDE_many QUOTE
784              
785             <wideCharacterLiteral> ::= WIDECHARACTERLITERAL
786             :lexeme ~ <WIDECHARACTERLITERAL>
787             WIDECHARACTERLITERAL ~ 'L' QUOTE I_CONSTANT_INSIDE_many QUOTE
788              
789             dD ~ [dD]
790             <fixedPtLiteral> ::= FIXEDPTLITERAL
791             :lexeme ~ <FIXEDPTLITERAL>
792             FIXEDPTLITERAL ~ D_many '.' D_many dD
793             | '.' D_many dD
794             | D_many '.' dD
795              
796             <floatingPtLiteral> ::= FCONSTANT
797             :lexeme ~ <FCONSTANT>
798             FCONSTANT ~ D_many E FS_maybe
799             | D_any '.' D_many E_maybe FS_maybe
800             | D_many '.' E_maybe FS_maybe
801             | HP H_many P FS_maybe
802             | HP H_any '.' H_many P FS_maybe
803             | HP H_many '.' P FS_maybe
804              
805             #
806             # G0 helpers
807             #
808             O ~ [0-7]
809             O_any ~ O*
810             D ~ [0-9]
811             D_any ~ D*
812             D_many ~ D+
813             NZ ~ [1-9]
814             L ~ [a-zA-Z_]
815             A ~ [a-zA-Z_0-9]
816             A_any ~ A*
817             H ~ [a-fA-F0-9]
818             H_any ~ H*
819             H_many ~ H+
820             HP ~ '0' [xX]
821             B ~ [0-1]
822             B_many ~ B+
823             BP ~ '0' [bB]
824             SIGN_maybe ~ [+-]
825             SIGN_maybe ~
826             E ~ [Ee] SIGN_maybe D_many
827             E_maybe ~ E
828             E_maybe ~
829             P ~ [Pp] SIGN_maybe D_many
830             FS ~ [fFlL]
831             FS_maybe ~ FS
832             FS_maybe ~
833             LL ~ 'll' | 'LL' | [lL]
834             LL_maybe ~ LL
835             LL_maybe ~
836             U ~ [uU]
837             U_maybe ~ U
838             U_maybe ~
839             IS ~ U LL_maybe | LL U_maybe
840             IS_maybe ~ IS
841             IS_maybe ~
842             CP ~ [uU] # L extracted - c.f. WIDECHARACTERLITERAL
843             CP_maybe ~ CP
844             CP_maybe ~
845             SP ~ 'u8' | [uUL]
846             SP_maybe ~ SP
847             SP_maybe ~
848             ES_AFTERBS ~ [\'\"\?\\abfnrtv]
849             | O
850             | O O
851             | O O O
852             | 'x' H_many
853             ES ~ BS ES_AFTERBS
854             WS ~ [ \t\v\n\f]
855             WS_any ~ WS*
856             WS_many ~ WS+
857             QUOTE ~ [']
858             BS ~ '\'
859              
860             #
861             # discards of the C language
862             #
863             ############################################################################
864             # Discard of a C comment, c.f. https://gist.github.com/jeffreykegler/5015057
865             ############################################################################
866             <C style comment> ~ '/*' <comment interior> '*/'
867             <comment interior> ~
868             <optional non stars>
869             <optional star prefixed segments>
870             <optional pre final stars>
871             <optional non stars> ~ [^*]*
872             <optional star prefixed segments> ~ <star prefixed segment>*
873             <star prefixed segment> ~ <stars> [^/*] <optional star free text>
874             <stars> ~ [*]+
875             <optional star free text> ~ [^*]*
876             <optional pre final stars> ~ [*]*
877             :discard ~ <C style comment>
878              
879             ##########################
880             # Discard of a C++ comment
881             ##########################
882             <Cplusplus style comment> ~ '//' <Cplusplus comment interior>
883             <Cplusplus comment interior> ~ [^\n]*
884             :discard ~ <Cplusplus style comment>
885              
886             ###########################
887             # TAKE CARE: preprocessor commands are IGNORED in this version
888             # Discard of a Perl comment
889             ###########################
890             <_Cpp style directive> ~ '#' <_Cpp style directive interior>
891             <_Cpp style directive interior> ~ [^\n]*
892             CPPSTYLEDIRECTIVE ~ <_Cpp style directive>
893             :discard ~ <_Cpp style directive>
894              
895             ####################
896             # WhiteSpace discard
897             ####################
898             :discard ~ WS_many # whitespace separates tokens
899