X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.graph.compiler%2Fsrc%2Forg%2Fsimantics%2Fgraph%2Fcompiler%2Finternal%2Fparsing%2FGraph.g;fp=bundles%2Forg.simantics.graph.compiler%2Fsrc%2Forg%2Fsimantics%2Fgraph%2Fcompiler%2Finternal%2Fparsing%2FGraph.g;h=5f32abbc191c471f1303b1d2d7d3a0e4a5e4f75b;hp=995960f94b5019322e562cf8accc10a68cd229b5;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.graph.compiler/src/org/simantics/graph/compiler/internal/parsing/Graph.g b/bundles/org.simantics.graph.compiler/src/org/simantics/graph/compiler/internal/parsing/Graph.g index 995960f94..5f32abbc1 100644 --- a/bundles/org.simantics.graph.compiler/src/org/simantics/graph/compiler/internal/parsing/Graph.g +++ b/bundles/org.simantics.graph.compiler/src/org/simantics/graph/compiler/internal/parsing/Graph.g @@ -1,453 +1,453 @@ -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 - : '') )* '>' - ; - -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 - | ' INHERITS - | ' 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*) - ; - +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 + : '') )* '>' + ; + +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 + | ' INHERITS + | ' 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*) + ; +