--- /dev/null
+options {\r
+ JDK_VERSION = "1.6";\r
+ STATIC = false;\r
+ IGNORE_CASE = false;\r
+}\r
+\r
+PARSER_BEGIN(DataParser)\r
+package org.simantics.databoard.parser;\r
+\r
+import org.simantics.databoard.parser.ast.type.*;\r
+import org.simantics.databoard.parser.ast.value.*;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Collections;\r
+\r
+/**\r
+ * Parser for data type definitions.\r
+ * @author Hannu Niemist�\r
+ */\r
+public class DataParser { \r
+}\r
+PARSER_END(DataParser)\r
+\r
+/*** Lexer *********************************************************/\r
+\r
+SKIP:\r
+{ <WHITESPACE: " " | "\n" | "\r" | "\t" > \r
+| <COMMENT1: "/*" (~["*"] | "*" ~["/"])* "*/" > \r
+| <COMMENT2: "//" (~["\n"])* >\r
+}\r
+\r
+TOKEN:\r
+{ ";" | "(" | ")" | "?" | "[" | "]"\r
+| "{" | "}" | "|" | "&" | ":" \r
+| "," | ".." | "." | "=" | "<" | ">"\r
+| "type" | "true" | "false" | "null" | "map" | "referable"\r
+| <STRING: "\"" (~["\"", "\\", "\n"] | "\\" ~["\n"])* "\"">\r
+ { matchedToken.image = StringEscapeUtils.unescape(\r
+ matchedToken.image.substring(1,matchedToken.image.length()-1)); }\r
+| <LONG_STRING: "\"\"\"" (~["\""] | "\"" ~["\""] | "\"\"" ~["\""])* "\"\"\"">\r
+ { matchedToken.image = matchedToken.image.substring(3,matchedToken.image.length()-3); }\r
+| <#POSITIVE_INTEGER: (["0"-"9"])+ >\r
+| <INTEGER: ("-"|"+")? <POSITIVE_INTEGER> >\r
+| <FLOAT: \r
+ ("-")? \r
+ ( <POSITIVE_INTEGER> "." <POSITIVE_INTEGER> (["e","E"] <INTEGER>)?\r
+ | "." <POSITIVE_INTEGER> (["e","E"] <INTEGER>)?\r
+ | <POSITIVE_INTEGER> ["e","E"] <INTEGER>\r
+ | "NaN"\r
+ | "Infinity"\r
+ ) >\r
+| <IDENT: ["a"-"z","A"-"Z","_"] (["a"-"z","A"-"Z","_","0"-"9"])* >\r
+| <URI: "<" (~["<",">"])* ">"> \r
+ { matchedToken.image = matchedToken.image.substring(1,matchedToken.image.length()-1); }\r
+}\r
+\r
+/*** Type parser ***************************************************/\r
+\r
+List<AstTypeDefinition> typeDefinitions() : {\r
+ AstTypeDefinition def;\r
+ List<AstTypeDefinition> result = new ArrayList<AstTypeDefinition>();\r
+} {\r
+ ( def=typeDefinition() { result.add(def); } )* <EOF>\r
+ { return result; }\r
+}\r
+\r
+AstTypeDefinition typeDefinition() : {\r
+ Token name;\r
+ AstType type;\r
+} {\r
+ "type" name=<IDENT> "=" type=type() \r
+ { return new AstTypeDefinition(name.image, type); } \r
+}\r
+\r
+AstType type() : { \r
+ AstType type;\r
+} {\r
+ type=simpleType()\r
+ { return type; }\r
+ | type=unionType()\r
+ { return type; }\r
+}\r
+\r
+AstType unionType() : {\r
+ List<AstComponent> components = new ArrayList<AstComponent>(4);\r
+} {\r
+ ( "|" unionComponent(components) )+\r
+ { return new AstUnionType(components); }\r
+}\r
+\r
+private void unionComponent(List<AstComponent> components) : {\r
+ Token tag;\r
+ AstType type;\r
+} {\r
+ tag=<IDENT>\r
+ ( \r
+ type=simpleType() { components.add(new AstComponent(tag.image, type)); }\r
+ | { components.add(new AstComponent(tag.image, AstRecordType.EMPTY_RECORD)); }\r
+ ) \r
+}\r
+\r
+AstType simpleType() : { \r
+ AstType type;\r
+} {\r
+ type=basicType()\r
+ ( "[" type=arraySuffix(type) )*\r
+ { return type; }\r
+}\r
+\r
+private AstType arraySuffix(AstType componentType) : {\r
+ Token t1, t2;\r
+ Integer v1;\r
+} {\r
+ "]" { \r
+ return new AstArrayType(componentType, null, null); \r
+ }\r
+ | ".." t1=<INTEGER> "]" {\r
+ v1 = Integer.parseInt(t1.image); \r
+ return new AstArrayType(componentType, null, v1); \r
+ }\r
+ | t1=<INTEGER> { v1 = Integer.parseInt(t1.image); } \r
+ (\r
+ "]" { return new AstArrayType(componentType, v1, v1); } \r
+ | ".." \r
+ (\r
+ "]" { return new AstArrayType(componentType, v1, null); }\r
+ | t2=<INTEGER> "]" {\r
+ return new AstArrayType(componentType, v1, Integer.parseInt(t2.image)); \r
+ }\r
+ ) \r
+ ) \r
+}\r
+\r
+AstType basicType() : { \r
+ AstType type;\r
+ boolean referable = false;\r
+} { \r
+ "(" type = tupleType() ")" { return type; }\r
+ | ("referable" {referable=true;})? \r
+ "{" type = recordType(referable) "}" { return type; }\r
+ | type = typeReference() { return type; }\r
+}\r
+\r
+AstType typeReference() : {\r
+ Token name;\r
+ List<AstType> parameters = Collections.emptyList();\r
+ List<AstAttribute> attributes = Collections.emptyList();\r
+} {\r
+ name=<IDENT> \r
+ ("("\r
+ { parameters = new ArrayList<AstType>(2);\r
+ attributes = new ArrayList<AstAttribute>(2); \r
+ } \r
+ parameter(parameters, attributes)\r
+ ("," parameter(parameters, attributes))*\r
+ ")")?\r
+ { \r
+ return new AstTypeReference(name.image, parameters, attributes); \r
+ }\r
+}\r
+\r
+private void parameter(List<AstType> parameters, List<AstAttribute> attributes) : {\r
+ Token key;\r
+ String value;\r
+ AstType type;\r
+} {\r
+ LOOKAHEAD(<IDENT> "=")\r
+ key=<IDENT> "=" value=attributeValue() { attributes.add(new AstAttribute(key.image, value)); } \r
+ | type=type() { parameters.add(type); }\r
+}\r
+\r
+String numericValue() : {}\r
+{ (<INTEGER> | <FLOAT>)\r
+ { return token.image; }\r
+| "-" (<INTEGER> | <FLOAT>)\r
+ { return "-" + token.image; }\r
+}\r
+\r
+String range() : {\r
+ Token open, close;\r
+ String first = "", second = "";\r
+} {\r
+ ( "[" | "(" ) { open = token; }\r
+ ( first = numericValue() )?\r
+ ".."\r
+ ( second = numericValue() )?\r
+ ( "]" | ")" ) { close = token; }\r
+ { return open.image + first + ".." + second + close.image; } \r
+}\r
+\r
+String attributeValue() : {\r
+ String str;\r
+} {\r
+ ( <STRING> \r
+ | "true"\r
+ | "false" \r
+ ) { return token.image; }\r
+| str=numericValue() { return str; }\r
+| str=range() { return str; }\r
+}\r
+\r
+AstType tupleType() : { \r
+ AstType type;\r
+ ArrayList<AstType> types; \r
+} { \r
+ type = type() \r
+ { types = new ArrayList<AstType>(3); types.add(type); }\r
+ ( "," type = type() { types.add(type); } )* \r
+ { \r
+ if(types.size()==1)\r
+ return types.get(0);\r
+ else\r
+ return new AstTupleType(types);\r
+ }\r
+ | { return new AstTupleType(Collections.<AstType>emptyList()); } \r
+}\r
+\r
+AstType recordType(boolean referable) : {\r
+ AstComponent component;\r
+ ArrayList<AstComponent> components; \r
+} { \r
+ component = component() \r
+ { components = new ArrayList<AstComponent>(3); components.add(component); }\r
+ ( "," component = component() { components.add(component); } )*\r
+ { return new AstRecordType(referable, components); }\r
+ | { return new AstRecordType(referable, Collections.<AstComponent>emptyList()); }\r
+}\r
+\r
+AstComponent component() : {\r
+ Token field;\r
+ AstType type;\r
+} {\r
+ (field=<IDENT> | field="type" | field="referable") ":" type=type() \r
+ { return new AstComponent(field.image, type); }\r
+}\r
+ \r
+/*** Value parser **************************************************/\r
+\r
+List<AstValueDefinition> valueDefinitions() : {\r
+ AstValueDefinition def;\r
+ List<AstValueDefinition> result = new ArrayList<AstValueDefinition>();\r
+} {\r
+ ( def=valueDefinition() { result.add(def); } )* <EOF>\r
+ { return result; }\r
+}\r
+\r
+AstValueDefinition valueDefinition() : {\r
+ Token name;\r
+ AstValue value;\r
+ AstType type;\r
+} {\r
+ name=<IDENT> ":" type=type() "=" value=value() \r
+ { return new AstValueDefinition(name.image, type, value); }\r
+}\r
+\r
+AstValue value() : {\r
+ AstValue value;\r
+ AstType type;\r
+} {\r
+ value = basicValue()\r
+ ( ":" type = type()\r
+ { value = new AstVariant(value, type); } \r
+ )*\r
+ { return value; }\r
+}\r
+\r
+AstValue basicValue() : {\r
+ Token tag;\r
+ AstValue temp;\r
+} {\r
+ "null" { return AstNull.NULL; }\r
+ | <STRING> { return new AstString(token.image); }\r
+ | <LONG_STRING> { return new AstString(token.image); }\r
+ | <INTEGER> { return new AstInteger(token.image); }\r
+ | <FLOAT> { return new AstFloat(token.image); }\r
+ | "true" { return AstBoolean.TRUE; }\r
+ | "false" { return AstBoolean.FALSE; }\r
+ | "map" "{" temp=map() "}" { return temp; }\r
+ | "[" temp=array() "]" { return temp; }\r
+ | "{" temp=record() "}" { return temp; }\r
+ | "(" temp=tuple() ")" { return temp; }\r
+ | tag=<IDENT> \r
+ ( temp=basicValue() { return new AstTaggedValue(tag.image, temp); }\r
+ | { return new AstReference(tag.image); } \r
+ ) \r
+}\r
+\r
+AstArray array() : {\r
+ ArrayList<AstValue> components;\r
+ AstValue value;\r
+} {\r
+ { components = new ArrayList<AstValue>(); }\r
+ value=value() { components.add(value); }\r
+ ("," value=value() { components.add(value); })*\r
+ { return new AstArray(components); }\r
+ | { return AstArray.EMPTY; } \r
+}\r
+\r
+AstValue tuple() : {\r
+ ArrayList<AstValue> components;\r
+ AstValue value;\r
+} {\r
+ { components = new ArrayList<AstValue>(); }\r
+ value=value() { components.add(value); }\r
+ ("," value=value() { components.add(value); })*\r
+ { \r
+ if(components.size() == 1)\r
+ return components.get(0);\r
+ else\r
+ return new AstTuple(components); \r
+ }\r
+ | { return AstTuple.EMPTY; } \r
+}\r
+\r
+AstRecord record() : {\r
+ ArrayList<AstComponentAssignment> components;\r
+ AstComponentAssignment assignment;\r
+} {\r
+ { components = new ArrayList<AstComponentAssignment>(); }\r
+ assignment=assignment() { components.add(assignment); }\r
+ ("," assignment=assignment() { components.add(assignment); })*\r
+ { return new AstRecord(components); }\r
+ | { return AstRecord.EMPTY; } \r
+}\r
+\r
+AstMap map() : {\r
+ ArrayList<AstMapAssignment> components;\r
+ AstMapAssignment assignment;\r
+} {\r
+ { components = new ArrayList<AstMapAssignment>(); }\r
+ assignment=mapAssignment() { components.add(assignment); }\r
+ ("," assignment=mapAssignment() { components.add(assignment); })*\r
+ { return new AstMap(components); }\r
+ | { return AstMap.EMPTY; } \r
+}\r
+\r
+AstComponentAssignment assignment() : {\r
+ Token name;\r
+ AstValue value;\r
+} {\r
+ name=<IDENT> "=" value=value() \r
+ { return new AstComponentAssignment(name.image, value); }\r
+}\r
+\r
+AstMapAssignment mapAssignment() : {\r
+ AstValue key;\r
+ AstValue value;\r
+} {\r
+ key=value() "=" value=value() \r
+ { return new AstMapAssignment(key, value); }\r
+}
\ No newline at end of file