]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.graph.compiler/src/org/simantics/graph/compiler/internal/parsing/Graph.g
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.graph.compiler / src / org / simantics / graph / compiler / internal / parsing / Graph.g
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
new file mode 100644 (file)
index 0000000..67b11fb
--- /dev/null
@@ -0,0 +1,453 @@
+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 Token.EOF_TOKEN;\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
+        
\ No newline at end of file