-grammar Graph;\r
-\r
-options {\r
- language = Java;\r
- output = AST;\r
- ASTLabelType=CommonTree;\r
-}\r
-\r
-tokens {\r
- // lexer\r
- INDENT;\r
- DEDENT;\r
- \r
- // graph\r
- FILE;\r
- RESOURCE;\r
- PROPERTY;\r
- VARIABLE;\r
- EMBEDDED_VALUE;\r
- EMBEDDED_TYPE;\r
- TEMPLATE_INSTANCE;\r
- TEMPLATE_DEFINITION;\r
- \r
- BLANK;\r
- REF;\r
- \r
- EQUALS;\r
- INSTANCE_OF;\r
- INHERITS;\r
- SUBRELATION_OF;\r
- HAS_DOMAIN;\r
- HAS_RANGE;\r
- DOMAIN_OF;\r
- REQUIRES_VALUE_TYPE;\r
-\r
- // data\r
- TYPE_DEFINITIONS;\r
- TYPE_DEFINITION; \r
-\r
- UNION_TYPE; \r
- RECORD_TYPE;\r
- TUPLE_TYPE;\r
- ARRAY_TYPE;\r
- TYPE_REFERENCE;\r
- TYPE_ANNOTATION; \r
- TYPE_COMPONENT;\r
- \r
- VALUE_DEFINITIONS;\r
- VALUE_DEFINITION;\r
-\r
- NO_VALUE; \r
- VARIANT;\r
- ARRAY;\r
- TUPLE;\r
- TAGGED_VALUE;\r
- RECORD;\r
- MAP;\r
- ASSIGNMENT;\r
- TRUE;\r
- FALSE;\r
-}\r
-\r
-@parser::header { package org.simantics.graph.compiler.internal.parsing; }\r
-@lexer::header { package org.simantics.graph.compiler.internal.parsing; \r
-\r
-import gnu.trove.list.array.*;\r
-}\r
-\r
-@lexer::members {\r
-int inParen = 0;\r
-\r
-TIntArrayList iStack = new TIntArrayList();\r
-{ iStack.add(0); }\r
-\r
-List tokens = new ArrayList();\r
-public void emit(Token token) {\r
- state.token = token;\r
- tokens.add(token);\r
-}\r
-public Token nextToken() {\r
- if(tokens.isEmpty()) {\r
- super.nextToken();\r
- if ( tokens.isEmpty() ) {\r
- /* When end-of-file is encountered, we \r
- emit balancing number of DEDENT tokens.\r
- */\r
- if(iStack.size() <= 1)\r
- return getEOFToken();\r
- else { \r
- while(iStack.size() > 1) {\r
- iStack.removeAt(iStack.size()-1);\r
- state.type = DEDENT;\r
- emit();\r
- }\r
- iStack.clear();\r
- }\r
- } \r
- }\r
- return (Token)tokens.remove(0);\r
-}\r
-\r
-}\r
-\r
-// ------------------------------------------------------------------\r
-// LEXER\r
-// ------------------------------------------------------------------\r
-\r
-ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*\r
- ;\r
-\r
-COMMENT\r
- : '//' ~('\n')* {$channel=HIDDEN;}\r
- | '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}\r
- ;\r
-\r
-WS : ( ' '\r
- | '\t'\r
- | '\r'\r
- ) {$channel=HIDDEN;}\r
- ;\r
- \r
-LPAREN : '(' { ++ inParen; } ;\r
-RPAREN : ')' { -- inParen; } ; \r
-LBRACKET : '[' { ++ inParen; } ;\r
-RBRACKET : ']' { -- inParen; } ;\r
-LCURLY : '{' { ++ inParen; } ;\r
-RCURLY : '}' { -- inParen; } ;\r
-\r
-INT_RANGE : INT '..' INT?\r
- | '..' INT\r
- ;\r
-RANGE : FLOAT '..' (FLOAT | INT)?\r
- | '..' FLOAT\r
- | INT '..' FLOAT\r
- ;\r
-\r
-NEWLINE\r
-@init { int spaces = 0; } \r
- : '\n'\r
- ( ' ' { ++spaces; } \r
- | '//' ~('\n')* '\n' { spaces = 0; } \r
- | '/*' ( options {greedy=false;} : . )* '*/'\r
- | '\r'\r
- | '\n' { spaces = 0; }\r
- )*\r
- { \r
- int c = input.LA(1);\r
- \r
- if(inParen > 0) {\r
- $channel = HIDDEN;\r
- }\r
- else if(c == EOF) {\r
- while(iStack.size() > 1) {\r
- iStack.removeAt(iStack.size()-1);\r
- state.type = DEDENT;\r
- emit();\r
- }\r
- $channel = HIDDEN;\r
- iStack.clear();\r
- }\r
- else {\r
- int stackTop = iStack.get(iStack.size()-1);\r
- if(spaces > stackTop) {\r
- iStack.add(spaces);\r
- $type = INDENT;\r
- }\r
- else if(spaces < stackTop) {\r
- while(spaces < iStack.get(iStack.size()-1)) {\r
- iStack.removeAt(iStack.size()-1);\r
- state.type = DEDENT;\r
- emit();\r
- }\r
- state.type = NEWLINE;\r
- emit();\r
- // TODO check that spaces == iStack.get(iStack.size()-1)\r
- }\r
- }\r
- }\r
- ;\r
- \r
-INDENT: { false }?=> 'INDENT' ;\r
-DEDENT: { false }?=> 'DEDENT' ; \r
- \r
-INT : '-'? '0'..'9'+\r
- ;\r
-\r
-FLOAT\r
- : '-'? \r
- ( ('0'..'9')+ '.' ('0'..'9')* EXPONENT?\r
- | ('0'..'9')+ EXPONENT\r
- )\r
- ;\r
- \r
-STRING\r
- : '"' ( ESC_SEQ | ~('\\'|'"') )* '"'\r
- | '"""' ( ~('"') | '"' ~('"') | '""' ~('"') )* '"""'\r
- ;\r
-\r
-URI\r
- : '<http:' ( ~('>') )* '>'\r
- ;\r
-\r
-fragment\r
-EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;\r
-\r
-fragment\r
-HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;\r
-\r
-fragment\r
-ESC_SEQ\r
- : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')\r
- | UNICODE_ESC\r
- ;\r
-\r
-fragment\r
-UNICODE_ESC\r
- : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT\r
- ;\r
-\r
-// ------------------------------------------------------------------\r
-// STATEMENTS \r
-// ------------------------------------------------------------------\r
-\r
-file : NEWLINE? resourceDefinitions? EOF -> ^(FILE resourceDefinitions?) ;\r
-\r
-resourceDefinitions \r
- : resourceDefinition (NEWLINE! resourceDefinition)*\r
- ;\r
- \r
-resourceDefinition \r
- : resource\r
- localProperty*\r
- (INDENT property (NEWLINE property)* DEDENT)?\r
- -> ^(RESOURCE resource localProperty* property*) \r
- | template -> ^(RESOURCE ^(BLANK template) template)\r
- ;\r
- \r
-localProperty\r
- : relation resource\r
- -> ^(PROPERTY relation ^(RESOURCE resource))\r
- ; \r
-\r
-property\r
- : relation\r
- ( resourceDefinition -> ^(PROPERTY relation resourceDefinition)\r
- | INDENT resourceDefinitions DEDENT -> ^(PROPERTY relation resourceDefinitions)\r
- )\r
- | template\r
- ;\r
- \r
-template\r
- : '@' \r
- ( {input.LT(1).getText().equals("template")}?=>\r
- ID resource+ \r
- INDENT resourceDefinitions DEDENT\r
- -> ^(TEMPLATE_DEFINITION resource+ resourceDefinitions)\r
- | resource+ \r
- (INDENT resourceDefinitions DEDENT)?\r
- -> ^(TEMPLATE_INSTANCE resource+ resourceDefinitions?)\r
- )\r
- ; \r
-\r
-// ------------------------------------------------------------------\r
-// RESOURCES\r
-// ------------------------------------------------------------------\r
-\r
-relation \r
- : ( ID -> ID) \r
- ('.' ID -> ^(REF $relation ID))*\r
- | URI\r
- | '<T' -> INHERITS\r
- | '<R' -> SUBRELATION_OF\r
- | '<--' -> HAS_DOMAIN\r
- | '-->' -> HAS_RANGE\r
- | '==>' -> REQUIRES_VALUE_TYPE\r
- | '>--' -> DOMAIN_OF \r
- | ':' -> INSTANCE_OF\r
- | '=' -> EQUALS\r
- | '%' ID -> ^(VARIABLE ID)\r
- ;\r
-\r
-resource\r
- : ( {input.LT(1).getText().equals("_")}?=> ID -> ^(BLANK ID) \r
- | ID -> ID) \r
- ('.' (ID -> ^(REF $resource ID)\r
- |STRING -> ^(REF $resource STRING)\r
- )\r
- )*\r
- | URI\r
- | simpleValue -> ^(EMBEDDED_VALUE simpleValue)\r
- | '$' basicType -> ^(EMBEDDED_TYPE basicType)\r
- | '%' ID -> ^(VARIABLE ID)\r
- ;\r
-\r
-// ------------------------------------------------------------------\r
-// TYPE DEFINITIONS \r
-// ------------------------------------------------------------------\r
- \r
-/*typeDefinitions : typeDefinition* -> ^(TYPE_DEFINITIONS typeDefinition*);\r
-\r
-typeDefinition \r
- : 'type' ID '=' type -> ^(TYPE_DEFINITION ID type)\r
- ;\r
-*/\r
- \r
-type \r
- : arrayType\r
- | unionType\r
- ; \r
-\r
-unionType\r
- :\r
- ('|' unionComponent)+\r
- -> ^(UNION_TYPE unionComponent+)\r
- ;\r
-\r
-unionComponent : ID ((arrayType) => arrayType)? -> ^(TYPE_COMPONENT ID arrayType?) ;\r
-\r
-arrayType \r
- : (basicType -> basicType)\r
- (LBRACKET arrayLength? RBRACKET -> ^(ARRAY_TYPE $arrayType arrayLength?))* ;\r
-\r
-arrayLength \r
- : INT\r
- | INT_RANGE\r
- ;\r
-\r
-basicType \r
- : tupleType\r
- | recordType\r
- | typeReference\r
- ;\r
- \r
-tupleType \r
- : LPAREN (type (',' type)*)? RPAREN \r
- -> ^(TUPLE_TYPE type*) \r
- ;\r
-\r
-recordType \r
- : LCURLY (component (',' component)*)? RCURLY \r
- -> ^(RECORD_TYPE component*)\r
- ;\r
-\r
-component \r
- : ID ':' type \r
- -> ^(TYPE_COMPONENT ID type) \r
- ;\r
-\r
-typeReference \r
- : ID ((LPAREN)=> LPAREN parameter (',' parameter)* RPAREN)? \r
- -> ^(TYPE_REFERENCE ID parameter*)\r
- ;\r
-\r
-parameter \r
- : ID '=' parameterValue -> ^(TYPE_ANNOTATION ID parameterValue)\r
- | type \r
- ;\r
-\r
-parameterValue \r
- : string\r
- | boolean_\r
- | number\r
- | rangePar -> ^(RANGE rangePar) \r
- ;\r
- \r
-rangePar : (LBRACKET | LPAREN) range (RBRACKET | RPAREN) ; \r
- \r
-range\r
- : number\r
- | RANGE\r
- | INT_RANGE \r
- ; \r
- \r
-number\r
- : INT\r
- | FLOAT\r
- ;\r
-\r
-string\r
- : STRING\r
- ;\r
- \r
-boolean_\r
- : 'true' -> TRUE\r
- | 'false' -> FALSE\r
- ;\r
-\r
-// ------------------------------------------------------------------\r
-// VALUE DEFINITIONS \r
-// ------------------------------------------------------------------\r
-\r
-valueDefinitions : valueDefinition* -> ^(VALUE_DEFINITIONS valueDefinition*);\r
-\r
-valueDefinition \r
- : ID ':' type '=' value\r
- -> ^(VALUE_DEFINITION ID type value) \r
- ;\r
-\r
-value \r
- : (basicValue -> basicValue)\r
- (':' type -> ^(VARIANT type $value))* \r
- ;\r
-\r
-basicValue \r
- : simpleValue\r
- | map\r
- | {input.LT(1).getText().equals("null")}? ID -> NO_VALUE\r
- | taggedValue \r
- ;\r
- \r
-simpleValue\r
- : string\r
- | number\r
- | boolean_\r
- | array\r
- | tuple\r
- | record\r
- ; \r
-\r
-array \r
- : LBRACKET (value (',' value)*)? RBRACKET\r
- -> ^(ARRAY value*) \r
- ;\r
-\r
-tuple \r
- : LPAREN (value (',' value)*)? RPAREN\r
- -> ^(TUPLE value*) \r
- ;\r
-\r
-taggedValue \r
- : ID simpleValue?\r
- -> ^(TAGGED_VALUE ID simpleValue?) \r
- ;\r
-\r
-record \r
- : LCURLY (recordAssignment (',' recordAssignment)*)? RCURLY\r
- -> ^(RECORD recordAssignment*) \r
- ;\r
-\r
-recordAssignment \r
- : ID '=' value\r
- -> ^(ASSIGNMENT ID value)\r
- ;\r
-\r
-map : {input.LT(1).getText().equals("map")}?=> ID LCURLY (mapAssignment (',' mapAssignment)*)? RCURLY\r
- -> ^(MAP mapAssignment*) \r
- ;\r
-\r
-mapAssignment \r
- : value '=' value\r
- -> ^(ASSIGNMENT value*) \r
- ;\r
- \r
+grammar Graph;
+
+options {
+ language = Java;
+ output = AST;
+ ASTLabelType=CommonTree;
+}
+
+tokens {
+ // lexer
+ INDENT;
+ DEDENT;
+
+ // graph
+ FILE;
+ RESOURCE;
+ PROPERTY;
+ VARIABLE;
+ EMBEDDED_VALUE;
+ EMBEDDED_TYPE;
+ TEMPLATE_INSTANCE;
+ TEMPLATE_DEFINITION;
+
+ BLANK;
+ REF;
+
+ EQUALS;
+ INSTANCE_OF;
+ INHERITS;
+ SUBRELATION_OF;
+ HAS_DOMAIN;
+ HAS_RANGE;
+ DOMAIN_OF;
+ REQUIRES_VALUE_TYPE;
+
+ // data
+ TYPE_DEFINITIONS;
+ TYPE_DEFINITION;
+
+ UNION_TYPE;
+ RECORD_TYPE;
+ TUPLE_TYPE;
+ ARRAY_TYPE;
+ TYPE_REFERENCE;
+ TYPE_ANNOTATION;
+ TYPE_COMPONENT;
+
+ VALUE_DEFINITIONS;
+ VALUE_DEFINITION;
+
+ NO_VALUE;
+ VARIANT;
+ ARRAY;
+ TUPLE;
+ TAGGED_VALUE;
+ RECORD;
+ MAP;
+ ASSIGNMENT;
+ TRUE;
+ FALSE;
+}
+
+@parser::header { package org.simantics.graph.compiler.internal.parsing; }
+@lexer::header { package org.simantics.graph.compiler.internal.parsing;
+
+import gnu.trove.list.array.*;
+}
+
+@lexer::members {
+int inParen = 0;
+
+TIntArrayList iStack = new TIntArrayList();
+{ iStack.add(0); }
+
+List tokens = new ArrayList();
+public void emit(Token token) {
+ state.token = token;
+ tokens.add(token);
+}
+public Token nextToken() {
+ if(tokens.isEmpty()) {
+ super.nextToken();
+ if ( tokens.isEmpty() ) {
+ /* When end-of-file is encountered, we
+ emit balancing number of DEDENT tokens.
+ */
+ if(iStack.size() <= 1)
+ return getEOFToken();
+ else {
+ while(iStack.size() > 1) {
+ iStack.removeAt(iStack.size()-1);
+ state.type = DEDENT;
+ emit();
+ }
+ iStack.clear();
+ }
+ }
+ }
+ return (Token)tokens.remove(0);
+}
+
+}
+
+// ------------------------------------------------------------------
+// LEXER
+// ------------------------------------------------------------------
+
+ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
+ ;
+
+COMMENT
+ : '//' ~('\n')* {$channel=HIDDEN;}
+ | '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
+ ;
+
+WS : ( ' '
+ | '\t'
+ | '\r'
+ ) {$channel=HIDDEN;}
+ ;
+
+LPAREN : '(' { ++ inParen; } ;
+RPAREN : ')' { -- inParen; } ;
+LBRACKET : '[' { ++ inParen; } ;
+RBRACKET : ']' { -- inParen; } ;
+LCURLY : '{' { ++ inParen; } ;
+RCURLY : '}' { -- inParen; } ;
+
+INT_RANGE : INT '..' INT?
+ | '..' INT
+ ;
+RANGE : FLOAT '..' (FLOAT | INT)?
+ | '..' FLOAT
+ | INT '..' FLOAT
+ ;
+
+NEWLINE
+@init { int spaces = 0; }
+ : '\n'
+ ( ' ' { ++spaces; }
+ | '//' ~('\n')* '\n' { spaces = 0; }
+ | '/*' ( options {greedy=false;} : . )* '*/'
+ | '\r'
+ | '\n' { spaces = 0; }
+ )*
+ {
+ int c = input.LA(1);
+
+ if(inParen > 0) {
+ $channel = HIDDEN;
+ }
+ else if(c == EOF) {
+ while(iStack.size() > 1) {
+ iStack.removeAt(iStack.size()-1);
+ state.type = DEDENT;
+ emit();
+ }
+ $channel = HIDDEN;
+ iStack.clear();
+ }
+ else {
+ int stackTop = iStack.get(iStack.size()-1);
+ if(spaces > stackTop) {
+ iStack.add(spaces);
+ $type = INDENT;
+ }
+ else if(spaces < stackTop) {
+ while(spaces < iStack.get(iStack.size()-1)) {
+ iStack.removeAt(iStack.size()-1);
+ state.type = DEDENT;
+ emit();
+ }
+ state.type = NEWLINE;
+ emit();
+ // TODO check that spaces == iStack.get(iStack.size()-1)
+ }
+ }
+ }
+ ;
+
+INDENT: { false }?=> 'INDENT' ;
+DEDENT: { false }?=> 'DEDENT' ;
+
+INT : '-'? '0'..'9'+
+ ;
+
+FLOAT
+ : '-'?
+ ( ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
+ | ('0'..'9')+ EXPONENT
+ )
+ ;
+
+STRING
+ : '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
+ | '"""' ( ~('"') | '"' ~('"') | '""' ~('"') )* '"""'
+ ;
+
+URI
+ : '<http:' ( ~('>') )* '>'
+ ;
+
+fragment
+EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;
+
+fragment
+HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
+
+fragment
+ESC_SEQ
+ : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
+ | UNICODE_ESC
+ ;
+
+fragment
+UNICODE_ESC
+ : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
+ ;
+
+// ------------------------------------------------------------------
+// STATEMENTS
+// ------------------------------------------------------------------
+
+file : NEWLINE? resourceDefinitions? EOF -> ^(FILE resourceDefinitions?) ;
+
+resourceDefinitions
+ : resourceDefinition (NEWLINE! resourceDefinition)*
+ ;
+
+resourceDefinition
+ : resource
+ localProperty*
+ (INDENT property (NEWLINE property)* DEDENT)?
+ -> ^(RESOURCE resource localProperty* property*)
+ | template -> ^(RESOURCE ^(BLANK template) template)
+ ;
+
+localProperty
+ : relation resource
+ -> ^(PROPERTY relation ^(RESOURCE resource))
+ ;
+
+property
+ : relation
+ ( resourceDefinition -> ^(PROPERTY relation resourceDefinition)
+ | INDENT resourceDefinitions DEDENT -> ^(PROPERTY relation resourceDefinitions)
+ )
+ | template
+ ;
+
+template
+ : '@'
+ ( {input.LT(1).getText().equals("template")}?=>
+ ID resource+
+ INDENT resourceDefinitions DEDENT
+ -> ^(TEMPLATE_DEFINITION resource+ resourceDefinitions)
+ | resource+
+ (INDENT resourceDefinitions DEDENT)?
+ -> ^(TEMPLATE_INSTANCE resource+ resourceDefinitions?)
+ )
+ ;
+
+// ------------------------------------------------------------------
+// RESOURCES
+// ------------------------------------------------------------------
+
+relation
+ : ( ID -> ID)
+ ('.' ID -> ^(REF $relation ID))*
+ | URI
+ | '<T' -> INHERITS
+ | '<R' -> SUBRELATION_OF
+ | '<--' -> HAS_DOMAIN
+ | '-->' -> HAS_RANGE
+ | '==>' -> REQUIRES_VALUE_TYPE
+ | '>--' -> DOMAIN_OF
+ | ':' -> INSTANCE_OF
+ | '=' -> EQUALS
+ | '%' ID -> ^(VARIABLE ID)
+ ;
+
+resource
+ : ( {input.LT(1).getText().equals("_")}?=> ID -> ^(BLANK ID)
+ | ID -> ID)
+ ('.' (ID -> ^(REF $resource ID)
+ |STRING -> ^(REF $resource STRING)
+ )
+ )*
+ | URI
+ | simpleValue -> ^(EMBEDDED_VALUE simpleValue)
+ | '$' basicType -> ^(EMBEDDED_TYPE basicType)
+ | '%' ID -> ^(VARIABLE ID)
+ ;
+
+// ------------------------------------------------------------------
+// TYPE DEFINITIONS
+// ------------------------------------------------------------------
+
+/*typeDefinitions : typeDefinition* -> ^(TYPE_DEFINITIONS typeDefinition*);
+
+typeDefinition
+ : 'type' ID '=' type -> ^(TYPE_DEFINITION ID type)
+ ;
+*/
+
+type
+ : arrayType
+ | unionType
+ ;
+
+unionType
+ :
+ ('|' unionComponent)+
+ -> ^(UNION_TYPE unionComponent+)
+ ;
+
+unionComponent : ID ((arrayType) => arrayType)? -> ^(TYPE_COMPONENT ID arrayType?) ;
+
+arrayType
+ : (basicType -> basicType)
+ (LBRACKET arrayLength? RBRACKET -> ^(ARRAY_TYPE $arrayType arrayLength?))* ;
+
+arrayLength
+ : INT
+ | INT_RANGE
+ ;
+
+basicType
+ : tupleType
+ | recordType
+ | typeReference
+ ;
+
+tupleType
+ : LPAREN (type (',' type)*)? RPAREN
+ -> ^(TUPLE_TYPE type*)
+ ;
+
+recordType
+ : LCURLY (component (',' component)*)? RCURLY
+ -> ^(RECORD_TYPE component*)
+ ;
+
+component
+ : ID ':' type
+ -> ^(TYPE_COMPONENT ID type)
+ ;
+
+typeReference
+ : ID ((LPAREN)=> LPAREN parameter (',' parameter)* RPAREN)?
+ -> ^(TYPE_REFERENCE ID parameter*)
+ ;
+
+parameter
+ : ID '=' parameterValue -> ^(TYPE_ANNOTATION ID parameterValue)
+ | type
+ ;
+
+parameterValue
+ : string
+ | boolean_
+ | number
+ | rangePar -> ^(RANGE rangePar)
+ ;
+
+rangePar : (LBRACKET | LPAREN) range (RBRACKET | RPAREN) ;
+
+range
+ : number
+ | RANGE
+ | INT_RANGE
+ ;
+
+number
+ : INT
+ | FLOAT
+ ;
+
+string
+ : STRING
+ ;
+
+boolean_
+ : 'true' -> TRUE
+ | 'false' -> FALSE
+ ;
+
+// ------------------------------------------------------------------
+// VALUE DEFINITIONS
+// ------------------------------------------------------------------
+
+valueDefinitions : valueDefinition* -> ^(VALUE_DEFINITIONS valueDefinition*);
+
+valueDefinition
+ : ID ':' type '=' value
+ -> ^(VALUE_DEFINITION ID type value)
+ ;
+
+value
+ : (basicValue -> basicValue)
+ (':' type -> ^(VARIANT type $value))*
+ ;
+
+basicValue
+ : simpleValue
+ | map
+ | {input.LT(1).getText().equals("null")}? ID -> NO_VALUE
+ | taggedValue
+ ;
+
+simpleValue
+ : string
+ | number
+ | boolean_
+ | array
+ | tuple
+ | record
+ ;
+
+array
+ : LBRACKET (value (',' value)*)? RBRACKET
+ -> ^(ARRAY value*)
+ ;
+
+tuple
+ : LPAREN (value (',' value)*)? RPAREN
+ -> ^(TUPLE value*)
+ ;
+
+taggedValue
+ : ID simpleValue?
+ -> ^(TAGGED_VALUE ID simpleValue?)
+ ;
+
+record
+ : LCURLY (recordAssignment (',' recordAssignment)*)? RCURLY
+ -> ^(RECORD recordAssignment*)
+ ;
+
+recordAssignment
+ : ID '=' value
+ -> ^(ASSIGNMENT ID value)
+ ;
+
+map : {input.LT(1).getText().equals("map")}?=> ID LCURLY (mapAssignment (',' mapAssignment)*)? RCURLY
+ -> ^(MAP mapAssignment*)
+ ;
+
+mapAssignment
+ : value '=' value
+ -> ^(ASSIGNMENT value*)
+ ;
+