File Coverage

blib/lib/Baal/Parser.pm
Criterion Covered Total %
statement 17 17 100.0
branch n/a
condition n/a
subroutine 6 6 100.0
pod 0 1 0.0
total 23 24 95.8


line stmt bran cond sub pod time code
1             package Baal::Parser;
2 2     2   13421 use 5.008001;
  2         5  
3 2     2   974 use utf8;
  2         16  
  2         8  
4 2     2   800 use Mouse;
  2         37675  
  2         8  
5 2     2   2525 use Parse::RecDescent;
  2         55911  
  2         12  
6              
7             our $VERSION = "0.01";
8              
9             our $grammer = <<'GRAMMER';
10             Document: Namespace(s?) END_OF_FILE
11             {
12             $return => {
13             Document => $item{"Namespace(s?)"},
14             }
15             }
16              
17             Namespace:
18             KEYWORD_NAMESPACE
19             QualifiedName
20             ImportClause(s?)
21             KEYWORD_BEGIN
22             Declaration(s?)
23             KEYWORD_END
24             {
25             $return = {
26             Name => $item{QualifiedName},
27             Imports => $item{"ImportClause(s?)"},
28             Declarations => $item{"Declaration(s?)"},
29             };
30             }
31              
32             ImportClause:
33             (KEYWORD_IMPORT | KEYWORD_APPEND) QualifiedNameWithWildcard
34              
35             Declaration:
36             EntityDeclaration | ServiceDeclaration
37              
38             EntityDeclaration:
39             DOCUMENT_COMMENT(?)
40             KEYWORD_ABSTRACT(?)
41             KEYWORD_ENTITY
42             IDENTIFIER
43             IncludeClause(s?)
44             KEYWORD_BEGIN
45             FieldDefinition(s?)
46             KEYWORD_END
47             {
48             my $comment = $item{"DOCUMENT_COMMENT(?)"};
49             $return = {
50             Entity => {
51             Name => $item{IDENTIFIER},
52             IsAbstract => scalar(@{$item{"KEYWORD_ABSTRACT(?)"}})!= 0,
53             DocumentComment => $comment ? $comment->[0] : undef,
54             Includes => $item{"IncludeClause(s?)"},
55             Fields => $item{"FieldDefinition(s?)"},
56             },
57             };
58             }
59              
60             IncludeClause:
61             (KEYWORD_INCLUDES | KEYWORD_APPEND) ReferenceType
62              
63             FieldDefinition:
64             DOCUMENT_COMMENT(?)
65             IDENTIFIER
66             KEYWORD_AS
67             ModifieredType
68             KEYWORD_CLOSE
69             {
70             my $comment = $item{"DOCUMENT_COMMENT(?)"};
71             $return = {
72             Name => $item{IDENTIFIER},
73             DocumentComment => $comment ? $comment->[0] : undef,
74             %{$item{ModifieredType}},
75             };
76             } |
77              
78             ServiceDeclaration:
79             DOCUMENT_COMMENT(?)
80             KEYWORD_SERVICE
81             IDENTIFIER
82             KEYWORD_BEGIN
83             MethodDefinition(s?)
84             KEYWORD_END
85             {
86             my $comment = $item{"DOCUMENT_COMMENT(?)"};
87             $return = {
88             Service => {
89             Name => $item{IDENTIFIER},
90             DocumentComment => $comment ? $comment->[0] : undef,
91             Methods => $item{"MethodDefinition(s?)"},
92             },
93             };
94             }
95              
96             MethodDefinition:
97             DOCUMENT_COMMENT(?)
98             IDENTIFIER
99             KEYWORD_AS
100             (KEYWORD_ACCEPTS ModifieredType)(?)
101             (KEYWORD_RETURNS ModifieredType)(?)
102             KEYWORD_CLOSE
103             {
104             my $comment = $item{"DOCUMENT_COMMENT(?)"};
105             $return = {
106             Name => $item{IDENTIFIER},
107             DocumentComment => $comment ? $comment->[0] : undef,
108             Accepts => $item[4]->[0],
109             Returns => $item[5]->[0],
110             };
111             } |
112              
113             ModifieredType: Occurrence Iteration(s?) Type
114             {
115             $return = {
116             Occurrence => $item{Occurrence},
117             Iteration => $item{'Iteration(s?)'}->[0],
118             Type => $item{Type},
119             };
120             }
121              
122             # OCCURRENCES
123              
124             Occurrence: Required | Nullable
125             Required: KEYWORD_REQUIRED
126             { $return = $item[0] }
127             Nullable: KEYWORD_NULLABLE
128             { $return = $item[0] }
129              
130             # ITERATIONS
131              
132             Iteration: ListOf | DictionaryOf
133             ListOf: KEYWORD_LIST_OF
134             { $return = $item[0] }
135             DictionaryOf: KEYWORD_DICTIONARY_OF
136             { $return = $item[0] }
137              
138             # TYPES
139              
140             Type: PrimitiveType | PseudoType | ReferenceType |
141             ReferenceType:
142             EntityDeclaration { $return = {EntityDeclaration => $item[1]} } |
143             QualifiedName { $return = {QualifiedName => $item[1]} }
144             PseudoType: QUOTED_STRING
145             { $return = { PseudoType => $item[1] } }
146              
147              
148             # NAMES
149              
150             QualifiedNameWithWildcard: (IDENTIFIER '.' {$return = $item[1]} )(s?) (IDENTIFIER | '*')
151             { [ @{$item[1]} , $item[2] ] }
152             QualifiedName: (IDENTIFIER '.' {$return = $item[1]} )(s?) IDENTIFIER
153             { [ @{$item[1]} , $item[2] ] }
154              
155             # PRIMITIVE TYPES
156              
157             PrimitiveType:
158             TypeBoolean |
159             TypeInteger8 | TypeInteger16 | TypeInteger32 | TypeInteger64 |
160             TypeFloatBinary32 | TypeFloatBinary64 |
161             TypeFloatDecimal32 | TypeFloatDecimal64 |
162             TypeTimestamp | TypeDate | TypeTime |
163             TypeString | TypeBinary
164              
165             TypeBoolean: TYPE_BOOLEAN
166             { $return = { PrimitiveType => $item[0] } }
167             TYPE_BOOLEAN: 'boolean' | 'bool'
168              
169             TypeInteger8: TYPE_INTEGER_8
170             { $return = { PrimitiveType => $item[0] } }
171             TYPE_INTEGER_8:
172             'integer(' WHITE_SPACE(s?) '8' WHITE_SPACE(s?) ')' |
173             'int8' | 'sbyte' | 'byte'
174              
175             TypeInteger16: TYPE_INTEGER_16
176             { $return = { PrimitiveType => $item[0] } }
177             TYPE_INTEGER_16: 'integer(' WHITE_SPACE(s?) '16' WHITE_SPACE(s?) ')' |
178             'int16' | 'short'
179              
180             TypeInteger32: TYPE_INTEGER_32
181             { $return = { PrimitiveType => $item[0] } }
182             TYPE_INTEGER_32:
183             'integer(' WHITE_SPACE(s?) '32' WHITE_SPACE(s?) ')' |
184             'int32' | 'integer' | 'int'
185              
186             TypeInteger64: TYPE_INTEGER_64
187             { $return = { PrimitiveType => $item[0] } }
188             TYPE_INTEGER_64:
189             'integer(' WHITE_SPACE(s?) '64' WHITE_SPACE(s?) ')' |
190             'int64' | 'long'
191              
192             TypeFloatBinary32: TYPE_FLOAT_BINARY_32
193             { $return = { PrimitiveType => $item[0] } }
194             TYPE_FLOAT_BINARY_32:
195             'float(' WHITE_SPACE(s?) 'binary' WHITE_SPACE(s?) '32' WHITE_SPACE(s?) ')' |
196             'float32' | 'float'
197              
198             TypeFloatBinary64: TYPE_FLOAT_BINARY_64
199             { $return = { PrimitiveType => $item[0] } }
200             TYPE_FLOAT_BINARY_64:
201             'float(' WHITE_SPACE(s?) 'binary' WHITE_SPACE(s?) '64' WHITE_SPACE(s?) ')' |
202             'float64' | 'double' | 'real' | 'number'
203              
204             TypeFloatDecimal32: TYPE_FLOAT_DECIMAL_32
205             { $return = { PrimitiveType => $item[0] } }
206             TYPE_FLOAT_DECIMAL_32:
207             'float(' WHITE_SPACE(s?) 'decimal' WHITE_SPACE(s?) '32' WHITE_SPACE(s?) ')' |
208             'decimal32'
209              
210             TypeFloatDecimal64: TYPE_FLOAT_DECIMAL_64
211             { $return = { PrimitiveType => $item[0] } }
212             TYPE_FLOAT_DECIMAL_64:
213             'float(' WHITE_SPACE(s?) 'decimal' WHITE_SPACE(s?) '64' WHITE_SPACE(s?) ')' |
214             'decimal64' | 'decimal' | 'numeric' | 'money'
215              
216             TypeDate: TYPE_DATE
217             { $return = { PrimitiveType => $item[0] } }
218             TYPE_DATE: 'date'
219              
220             TypeTime: TYPE_TIME
221             { $return = { PrimitiveType => $item[0] } }
222             TYPE_TIME: 'time'
223              
224             TypeTimestamp: TYPE_TIMESTAMP
225             { $return = { PrimitiveType => $item[0] } }
226             TYPE_TIMESTAMP: 'timestamp' | 'datetime'
227              
228             TypeString: TYPE_STRING
229             { $return = { PrimitiveType => $item[0] } }
230             TYPE_STRING: 'string' | 'str'
231              
232             TypeBinary: TYPE_BINARY
233             { $return = { PrimitiveType => $item[0] } }
234             TYPE_BINARY: 'binary' | 'bin'
235              
236              
237             # KEYWORDS AND SYMBOLIC ALIASES
238              
239             KEYWORD_NAMESPACE: 'namespace'
240             KEYWORD_IMPORT: 'import'
241             KEYWORD_ABSTRACT: 'abstract'
242             KEYWORD_ENTITY: 'entity'
243             KEYWORD_SERVICE: 'service'
244             KEYWORD_INCLUDES: 'includes'
245             KEYWORD_REQUIRED: 'required' | '!'
246             KEYWORD_NULLABLE: 'nullable' | '?'
247             KEYWORD_LIST_OF: ('list' WHITE_SPACE(s?) 'of') | '@'
248             KEYWORD_DICTIONARY_OF: (('dictionary' | 'hash' | 'map') WHITE_SPACE(s?) 'of') | '%'
249             KEYWORD_APPEND: "+="
250             KEYWORD_REMOVE: "-="
251             KEYWORD_ACCEPTS: "accepts" | "<="
252             KEYWORD_RETURNS: "returns" | "=>"
253             KEYWORD_AS: "as" | ":"
254             KEYWORD_BEGIN: "{"
255             KEYWORD_END: "}"
256             KEYWORD_CLOSE: ";"
257              
258              
259             # FRAGMENTS
260              
261             IDENTIFIER: IDENTIFIER_FIRST_CHARACTOR IDENTIFIER_FILLING_CHARACTOR(s?)
262             { $item[1] . join '', @{$item[2]} }
263             IDENTIFIER_FIRST_CHARACTOR: UPPER_ALPHABET_CHARACTOR
264             IDENTIFIER_FILLING_CHARACTOR: ALPHABET_NUMERIC_CHARACTOR
265             QUOTED_STRING: "\"" (ESCAPE_STRING | /[^\\"\r\n']/)(s) "\""
266             { $return = join '', @{$item[2]} }
267             ESCAPE_STRING: /\\(?:[bfnrt\\'"]|x[0-9a-fA-F][0-9a-fA-F]|u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])/
268             DOCUMENT_COMMENT: /\/#(.*?)#\//s
269             { $return = $1 }
270             MULTI_LINE_COMMENT: /\/\*(.*?)\*\//
271             { $return = $1 }
272             SINGLE_LINE_COMMENT: "//" LINE_CONTENT(s) END_OF_LINE(?)
273             { $return = join '', @{$item[2]} }
274             BLANK: WHITE_SPACE(s)
275             HEXADECIMAL_CHARACTOR: /[0-9a-fA-F]/
276             ALPHABET_NUMERIC_CHARACTOR: ALPHABET_CHARACTOR | NUMERIC_CHARACTOR
277             ALPHABET_CHARACTOR: LOWER_ALPHABET_CHARACTOR | UPPER_ALPHABET_CHARACTOR
278             LOWER_ALPHABET_CHARACTOR: /[a-z]/
279             UPPER_ALPHABET_CHARACTOR: /[A-Z]/
280             NUMERIC_CHARACTOR: /[0-9]/
281             WHITE_SPACE: /[ \t\r\n]/
282             LINE_CONTENT: /[^\r\n]/
283             END_OF_LINE: /\r?\n/
284             END_OF_FILE: /^\Z/
285             GRAMMER
286              
287             has parser => (
288             is => 'ro',
289             isa => 'Parse::RecDescent',
290             default => sub {
291             local $Parse::RecDescent::skip = '([ \t\r\n]|//.*?\r?\n|/\*(.|\r|\n)*?\*/)*';
292             return Parse::RecDescent->new($grammer);
293             },
294             );
295              
296 2     2   310 no Mouse;
  2         4  
  2         13  
297              
298             sub parse {
299 1     1 0 294805 my ($self, $text) = @_;
300 1         13 my $result = $self->parser->Document($text);
301 1         62083 return $result;
302             }
303              
304             1;
305             __END__