]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.graph.compiler/src/org/simantics/graph/compiler/internal/parsing/Graph.g
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.graph.compiler / src / org / simantics / graph / compiler / internal / parsing / Graph.g
1 grammar Graph;
2
3 options {
4   language = Java;
5   output = AST;
6   ASTLabelType=CommonTree;
7 }
8
9 tokens {
10     // lexer
11     INDENT;
12     DEDENT;
13     
14     // graph
15     FILE;
16     RESOURCE;
17     PROPERTY;
18     VARIABLE;
19     EMBEDDED_VALUE;
20     EMBEDDED_TYPE;
21     TEMPLATE_INSTANCE;
22     TEMPLATE_DEFINITION;
23     
24     BLANK;
25     REF;
26     
27     EQUALS;
28     INSTANCE_OF;
29     INHERITS;
30     SUBRELATION_OF;
31     HAS_DOMAIN;
32     HAS_RANGE;
33     DOMAIN_OF;
34     REQUIRES_VALUE_TYPE;
35
36     // data
37     TYPE_DEFINITIONS;
38     TYPE_DEFINITION;    
39
40     UNION_TYPE;    
41     RECORD_TYPE;
42     TUPLE_TYPE;
43     ARRAY_TYPE;
44     TYPE_REFERENCE;
45     TYPE_ANNOTATION;    
46     TYPE_COMPONENT;
47     
48     VALUE_DEFINITIONS;
49     VALUE_DEFINITION;
50
51     NO_VALUE;    
52     VARIANT;
53     ARRAY;
54     TUPLE;
55     TAGGED_VALUE;
56     RECORD;
57     MAP;
58     ASSIGNMENT;
59     TRUE;
60     FALSE;
61 }
62
63 @parser::header { package org.simantics.graph.compiler.internal.parsing; }
64 @lexer::header { package org.simantics.graph.compiler.internal.parsing; 
65
66 import gnu.trove.list.array.*;
67 }
68
69 @lexer::members {
70 int inParen = 0;
71
72 TIntArrayList iStack = new TIntArrayList();
73 { iStack.add(0); }
74
75 List tokens = new ArrayList();
76 public void emit(Token token) {
77     state.token = token;
78     tokens.add(token);
79 }
80 public Token nextToken() {
81     if(tokens.isEmpty()) {
82         super.nextToken();
83         if ( tokens.isEmpty() ) {
84             /* When end-of-file is encountered, we 
85                emit balancing number of DEDENT tokens.
86             */
87             if(iStack.size() <= 1)
88                 return getEOFToken();
89             else {                
90                 while(iStack.size() > 1) {
91                     iStack.removeAt(iStack.size()-1);
92                     state.type = DEDENT;
93                     emit();
94                 }
95                 iStack.clear();
96             }
97         } 
98     }
99     return (Token)tokens.remove(0);
100 }
101
102 }
103
104 // ------------------------------------------------------------------
105 // LEXER
106 // ------------------------------------------------------------------
107
108 ID  : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
109     ;
110
111 COMMENT
112     :   '//' ~('\n')* {$channel=HIDDEN;}
113     |   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
114     ;
115
116 WS  : ( ' '
117       | '\t'
118       | '\r'
119       ) {$channel=HIDDEN;}
120     ;
121     
122 LPAREN    : '(' { ++ inParen; } ;
123 RPAREN    : ')' { -- inParen; } ;    
124 LBRACKET  : '[' { ++ inParen; } ;
125 RBRACKET  : ']' { -- inParen; } ;
126 LCURLY    : '{' { ++ inParen; } ;
127 RCURLY    : '}' { -- inParen; } ;
128
129 INT_RANGE : INT '..' INT?
130           | '..' INT
131           ;
132 RANGE     : FLOAT '..' (FLOAT | INT)?
133           | '..' FLOAT
134           | INT '..' FLOAT
135           ;
136
137 NEWLINE
138 @init { int spaces = 0; } 
139     : '\n'
140       ( ' ' { ++spaces; } 
141       | '//' ~('\n')* '\n' { spaces = 0; } 
142       | '/*' ( options {greedy=false;} : . )* '*/'
143       | '\r'
144       | '\n' { spaces = 0; }
145       )*
146       { 
147           int c = input.LA(1);
148           
149           if(inParen > 0) {
150               $channel = HIDDEN;
151           }
152           else if(c == EOF) {
153               while(iStack.size() > 1) {
154                   iStack.removeAt(iStack.size()-1);
155                   state.type = DEDENT;
156                   emit();
157               }
158               $channel = HIDDEN;
159               iStack.clear();
160           }
161           else {
162               int stackTop = iStack.get(iStack.size()-1);
163               if(spaces > stackTop) {
164                   iStack.add(spaces);
165                   $type = INDENT;
166               }
167               else if(spaces < stackTop) {
168                   while(spaces < iStack.get(iStack.size()-1)) {
169                       iStack.removeAt(iStack.size()-1);
170                       state.type = DEDENT;
171                       emit();
172                   }
173                   state.type = NEWLINE;
174                   emit();
175                   // TODO check that spaces == iStack.get(iStack.size()-1)
176               }
177           }
178       }
179     ;
180   
181 INDENT: { false }?=> 'INDENT' ;
182 DEDENT: { false }?=> 'DEDENT' ;  
183     
184 INT : '-'? '0'..'9'+
185     ;
186
187 FLOAT
188     : '-'? 
189     ( ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
190     | ('0'..'9')+ EXPONENT
191     )
192     ;
193   
194 STRING
195     :  '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
196     |  '"""' ( ~('"') | '"' ~('"') | '""' ~('"') )* '"""'
197     ;
198
199 URI
200     :  '<http:' ( ~('>') )* '>'
201     ;
202
203 fragment
204 EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;
205
206 fragment
207 HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
208
209 fragment
210 ESC_SEQ
211     :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
212     |   UNICODE_ESC
213     ;
214
215 fragment
216 UNICODE_ESC
217     :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
218     ;
219
220 // ------------------------------------------------------------------
221 // STATEMENTS    
222 // ------------------------------------------------------------------
223
224 file : NEWLINE? resourceDefinitions? EOF -> ^(FILE resourceDefinitions?) ;
225
226 resourceDefinitions 
227      : resourceDefinition (NEWLINE! resourceDefinition)*
228      ;
229              
230 resourceDefinition 
231     : resource
232       localProperty*
233       (INDENT property (NEWLINE property)* DEDENT)?
234     -> ^(RESOURCE resource localProperty* property*) 
235     | template -> ^(RESOURCE ^(BLANK template) template)
236     ;
237     
238 localProperty
239     : relation resource
240     -> ^(PROPERTY relation ^(RESOURCE resource))
241     ;    
242
243 property
244     : relation
245       ( resourceDefinition -> ^(PROPERTY relation resourceDefinition)
246       | INDENT resourceDefinitions DEDENT -> ^(PROPERTY relation resourceDefinitions)
247       )
248     | template
249     ;
250     
251 template
252     : '@' 
253     ( {input.LT(1).getText().equals("template")}?=>
254       ID resource+ 
255       INDENT resourceDefinitions DEDENT
256       -> ^(TEMPLATE_DEFINITION resource+ resourceDefinitions)
257     | resource+ 
258       (INDENT resourceDefinitions DEDENT)?
259       -> ^(TEMPLATE_INSTANCE resource+ resourceDefinitions?)
260     )
261     ;    
262
263 // ------------------------------------------------------------------
264 // RESOURCES
265 // ------------------------------------------------------------------
266
267 relation 
268     : ( ID -> ID) 
269       ('.' ID -> ^(REF $relation ID))*
270     | URI
271     | '<T' -> INHERITS
272     | '<R' -> SUBRELATION_OF
273     | '<--' -> HAS_DOMAIN
274     | '-->' -> HAS_RANGE
275     | '==>' -> REQUIRES_VALUE_TYPE
276     | '>--' -> DOMAIN_OF    
277     | ':' -> INSTANCE_OF
278     | '=' -> EQUALS
279     | '%' ID -> ^(VARIABLE ID)
280     ;
281
282 resource
283     : ( {input.LT(1).getText().equals("_")}?=> ID -> ^(BLANK ID) 
284       | ID -> ID) 
285       ('.' (ID -> ^(REF $resource ID)
286            |STRING -> ^(REF $resource STRING)
287            )
288       )*
289     | URI
290     | simpleValue -> ^(EMBEDDED_VALUE simpleValue)
291     | '$' basicType -> ^(EMBEDDED_TYPE basicType)
292     | '%' ID -> ^(VARIABLE ID)
293     ;
294
295 // ------------------------------------------------------------------
296 // TYPE DEFINITIONS    
297 // ------------------------------------------------------------------
298  
299 /*typeDefinitions : typeDefinition* -> ^(TYPE_DEFINITIONS typeDefinition*);
300
301 typeDefinition 
302     : 'type' ID '=' type -> ^(TYPE_DEFINITION ID type)
303     ;
304 */
305   
306 type 
307     : arrayType
308     | unionType
309     ;      
310
311 unionType
312     :
313      ('|' unionComponent)+
314     -> ^(UNION_TYPE unionComponent+)
315     ;
316
317 unionComponent : ID ((arrayType) => arrayType)? -> ^(TYPE_COMPONENT ID arrayType?) ;
318
319 arrayType 
320     : (basicType -> basicType)
321       (LBRACKET arrayLength? RBRACKET -> ^(ARRAY_TYPE $arrayType arrayLength?))* ;
322
323 arrayLength 
324     : INT
325     | INT_RANGE
326     ;
327
328 basicType 
329     : tupleType
330     | recordType
331     | typeReference
332     ;
333     
334 tupleType 
335     : LPAREN (type (',' type)*)? RPAREN 
336     -> ^(TUPLE_TYPE type*) 
337     ;
338
339 recordType 
340     : LCURLY (component (',' component)*)? RCURLY 
341     -> ^(RECORD_TYPE component*)
342     ;
343
344 component 
345     : ID ':' type 
346     -> ^(TYPE_COMPONENT ID type) 
347     ;
348
349 typeReference 
350     : ID ((LPAREN)=> LPAREN parameter (',' parameter)* RPAREN)? 
351     -> ^(TYPE_REFERENCE ID parameter*)
352     ;
353
354 parameter 
355     : ID '=' parameterValue -> ^(TYPE_ANNOTATION ID parameterValue)
356     | type 
357     ;
358
359 parameterValue 
360     : string
361     | boolean_
362     | number
363     | rangePar -> ^(RANGE rangePar)    
364     ;
365     
366 rangePar : (LBRACKET | LPAREN) range (RBRACKET | RPAREN) ;    
367     
368 range
369     : number
370     | RANGE
371     | INT_RANGE    
372     ;    
373     
374 number
375     : INT
376     | FLOAT
377     ;
378
379 string
380     : STRING
381     ;
382     
383 boolean_
384     : 'true' -> TRUE
385     | 'false' -> FALSE
386     ;
387
388 // ------------------------------------------------------------------
389 // VALUE DEFINITIONS    
390 // ------------------------------------------------------------------
391
392 valueDefinitions : valueDefinition* -> ^(VALUE_DEFINITIONS valueDefinition*);
393
394 valueDefinition 
395     : ID ':' type '=' value
396     -> ^(VALUE_DEFINITION ID type value) 
397     ;
398
399 value 
400     : (basicValue -> basicValue)
401       (':' type -> ^(VARIANT type $value))* 
402     ;
403
404 basicValue 
405     : simpleValue
406     | map
407     | {input.LT(1).getText().equals("null")}? ID -> NO_VALUE
408     | taggedValue    
409     ;
410     
411 simpleValue
412     : string
413     | number
414     | boolean_
415     | array
416     | tuple
417     | record
418     ;   
419
420 array 
421     : LBRACKET (value (',' value)*)? RBRACKET
422     -> ^(ARRAY value*) 
423     ;
424
425 tuple 
426     : LPAREN (value (',' value)*)? RPAREN
427     -> ^(TUPLE value*) 
428     ;
429
430 taggedValue 
431     : ID simpleValue?
432     -> ^(TAGGED_VALUE ID simpleValue?) 
433     ;
434
435 record 
436     : LCURLY (recordAssignment (',' recordAssignment)*)? RCURLY
437     -> ^(RECORD recordAssignment*) 
438     ;
439
440 recordAssignment 
441     : ID '=' value
442     -> ^(ASSIGNMENT ID value)
443     ;
444
445 map : {input.LT(1).getText().equals("map")}?=> ID LCURLY (mapAssignment (',' mapAssignment)*)? RCURLY
446     -> ^(MAP mapAssignment*) 
447     ;
448
449 mapAssignment 
450     : value '=' value
451     -> ^(ASSIGNMENT value*) 
452     ;
453