7 PARSER_BEGIN(DataParser)
\r
8 package org.simantics.databoard.parser;
\r
10 import org.simantics.databoard.parser.ast.type.*;
\r
11 import org.simantics.databoard.parser.ast.value.*;
\r
12 import java.util.ArrayList;
\r
13 import java.util.List;
\r
14 import java.util.Collections;
\r
17 * Parser for data type definitions.
\r
18 * @author Hannu Niemist�
\r
20 public class DataParser {
\r
22 PARSER_END(DataParser)
\r
24 /*** Lexer *********************************************************/
\r
27 { <WHITESPACE: " " | "\n" | "\r" | "\t" >
\r
28 | <COMMENT1: "/*" (~["*"] | "*" ~["/"])* "*/" >
\r
29 | <COMMENT2: "//" (~["\n"])* >
\r
33 { ";" | "(" | ")" | "?" | "[" | "]"
\r
34 | "{" | "}" | "|" | "&" | ":"
\r
35 | "," | ".." | "." | "=" | "<" | ">"
\r
36 | "type" | "true" | "false" | "null" | "map" | "referable"
\r
37 | <STRING: "\"" (~["\"", "\\", "\n"] | "\\" ~["\n"])* "\"">
\r
38 { matchedToken.image = StringEscapeUtils.unescape(
\r
39 matchedToken.image.substring(1,matchedToken.image.length()-1)); }
\r
40 | <LONG_STRING: "\"\"\"" (~["\""] | "\"" ~["\""] | "\"\"" ~["\""])* "\"\"\"">
\r
41 { matchedToken.image = matchedToken.image.substring(3,matchedToken.image.length()-3); }
\r
42 | <#POSITIVE_INTEGER: (["0"-"9"])+ >
\r
43 | <INTEGER: ("-"|"+")? <POSITIVE_INTEGER> >
\r
46 ( <POSITIVE_INTEGER> "." <POSITIVE_INTEGER> (["e","E"] <INTEGER>)?
\r
47 | "." <POSITIVE_INTEGER> (["e","E"] <INTEGER>)?
\r
48 | <POSITIVE_INTEGER> ["e","E"] <INTEGER>
\r
52 | <IDENT: ["a"-"z","A"-"Z","_"] (["a"-"z","A"-"Z","_","0"-"9"])* >
\r
53 | <URI: "<" (~["<",">"])* ">">
\r
54 { matchedToken.image = matchedToken.image.substring(1,matchedToken.image.length()-1); }
\r
57 /*** Type parser ***************************************************/
\r
59 List<AstTypeDefinition> typeDefinitions() : {
\r
60 AstTypeDefinition def;
\r
61 List<AstTypeDefinition> result = new ArrayList<AstTypeDefinition>();
\r
63 ( def=typeDefinition() { result.add(def); } )* <EOF>
\r
67 AstTypeDefinition typeDefinition() : {
\r
71 "type" name=<IDENT> "=" type=type()
\r
72 { return new AstTypeDefinition(name.image, type); }
\r
84 AstType unionType() : {
\r
85 List<AstComponent> components = new ArrayList<AstComponent>(4);
\r
87 ( "|" unionComponent(components) )+
\r
88 { return new AstUnionType(components); }
\r
91 private void unionComponent(List<AstComponent> components) : {
\r
97 type=simpleType() { components.add(new AstComponent(tag.image, type)); }
\r
98 | { components.add(new AstComponent(tag.image, AstRecordType.EMPTY_RECORD)); }
\r
102 AstType simpleType() : {
\r
106 ( "[" type=arraySuffix(type) )*
\r
110 private AstType arraySuffix(AstType componentType) : {
\r
115 return new AstArrayType(componentType, null, null);
\r
117 | ".." t1=<INTEGER> "]" {
\r
118 v1 = Integer.parseInt(t1.image);
\r
119 return new AstArrayType(componentType, null, v1);
\r
121 | t1=<INTEGER> { v1 = Integer.parseInt(t1.image); }
\r
123 "]" { return new AstArrayType(componentType, v1, v1); }
\r
126 "]" { return new AstArrayType(componentType, v1, null); }
\r
127 | t2=<INTEGER> "]" {
\r
128 return new AstArrayType(componentType, v1, Integer.parseInt(t2.image));
\r
134 AstType basicType() : {
\r
136 boolean referable = false;
\r
138 "(" type = tupleType() ")" { return type; }
\r
139 | ("referable" {referable=true;})?
\r
140 "{" type = recordType(referable) "}" { return type; }
\r
141 | type = typeReference() { return type; }
\r
144 AstType typeReference() : {
\r
146 List<AstType> parameters = Collections.emptyList();
\r
147 List<AstAttribute> attributes = Collections.emptyList();
\r
151 { parameters = new ArrayList<AstType>(2);
\r
152 attributes = new ArrayList<AstAttribute>(2);
\r
154 parameter(parameters, attributes)
\r
155 ("," parameter(parameters, attributes))*
\r
158 return new AstTypeReference(name.image, parameters, attributes);
\r
162 private void parameter(List<AstType> parameters, List<AstAttribute> attributes) : {
\r
167 LOOKAHEAD(<IDENT> "=")
\r
168 key=<IDENT> "=" value=attributeValue() { attributes.add(new AstAttribute(key.image, value)); }
\r
169 | type=type() { parameters.add(type); }
\r
172 String numericValue() : {}
\r
173 { (<INTEGER> | <FLOAT>)
\r
174 { return token.image; }
\r
175 | "-" (<INTEGER> | <FLOAT>)
\r
176 { return "-" + token.image; }
\r
181 String first = "", second = "";
\r
183 ( "[" | "(" ) { open = token; }
\r
184 ( first = numericValue() )?
\r
186 ( second = numericValue() )?
\r
187 ( "]" | ")" ) { close = token; }
\r
188 { return open.image + first + ".." + second + close.image; }
\r
191 String attributeValue() : {
\r
197 ) { return token.image; }
\r
198 | str=numericValue() { return str; }
\r
199 | str=range() { return str; }
\r
202 AstType tupleType() : {
\r
204 ArrayList<AstType> types;
\r
207 { types = new ArrayList<AstType>(3); types.add(type); }
\r
208 ( "," type = type() { types.add(type); } )*
\r
210 if(types.size()==1)
\r
211 return types.get(0);
\r
213 return new AstTupleType(types);
\r
215 | { return new AstTupleType(Collections.<AstType>emptyList()); }
\r
218 AstType recordType(boolean referable) : {
\r
219 AstComponent component;
\r
220 ArrayList<AstComponent> components;
\r
222 component = component()
\r
223 { components = new ArrayList<AstComponent>(3); components.add(component); }
\r
224 ( "," component = component() { components.add(component); } )*
\r
225 { return new AstRecordType(referable, components); }
\r
226 | { return new AstRecordType(referable, Collections.<AstComponent>emptyList()); }
\r
229 AstComponent component() : {
\r
233 (field=<IDENT> | field="type" | field="referable") ":" type=type()
\r
234 { return new AstComponent(field.image, type); }
\r
237 /*** Value parser **************************************************/
\r
239 List<AstValueDefinition> valueDefinitions() : {
\r
240 AstValueDefinition def;
\r
241 List<AstValueDefinition> result = new ArrayList<AstValueDefinition>();
\r
243 ( def=valueDefinition() { result.add(def); } )* <EOF>
\r
247 AstValueDefinition valueDefinition() : {
\r
252 name=<IDENT> ":" type=type() "=" value=value()
\r
253 { return new AstValueDefinition(name.image, type, value); }
\r
256 AstValue value() : {
\r
260 value = basicValue()
\r
261 ( ":" type = type()
\r
262 { value = new AstVariant(value, type); }
\r
267 AstValue basicValue() : {
\r
271 "null" { return AstNull.NULL; }
\r
272 | <STRING> { return new AstString(token.image); }
\r
273 | <LONG_STRING> { return new AstString(token.image); }
\r
274 | <INTEGER> { return new AstInteger(token.image); }
\r
275 | <FLOAT> { return new AstFloat(token.image); }
\r
276 | "true" { return AstBoolean.TRUE; }
\r
277 | "false" { return AstBoolean.FALSE; }
\r
278 | "map" "{" temp=map() "}" { return temp; }
\r
279 | "[" temp=array() "]" { return temp; }
\r
280 | "{" temp=record() "}" { return temp; }
\r
281 | "(" temp=tuple() ")" { return temp; }
\r
283 ( temp=basicValue() { return new AstTaggedValue(tag.image, temp); }
\r
284 | { return new AstReference(tag.image); }
\r
288 AstArray array() : {
\r
289 ArrayList<AstValue> components;
\r
292 { components = new ArrayList<AstValue>(); }
\r
293 value=value() { components.add(value); }
\r
294 ("," value=value() { components.add(value); })*
\r
295 { return new AstArray(components); }
\r
296 | { return AstArray.EMPTY; }
\r
299 AstValue tuple() : {
\r
300 ArrayList<AstValue> components;
\r
303 { components = new ArrayList<AstValue>(); }
\r
304 value=value() { components.add(value); }
\r
305 ("," value=value() { components.add(value); })*
\r
307 if(components.size() == 1)
\r
308 return components.get(0);
\r
310 return new AstTuple(components);
\r
312 | { return AstTuple.EMPTY; }
\r
315 AstRecord record() : {
\r
316 ArrayList<AstComponentAssignment> components;
\r
317 AstComponentAssignment assignment;
\r
319 { components = new ArrayList<AstComponentAssignment>(); }
\r
320 assignment=assignment() { components.add(assignment); }
\r
321 ("," assignment=assignment() { components.add(assignment); })*
\r
322 { return new AstRecord(components); }
\r
323 | { return AstRecord.EMPTY; }
\r
327 ArrayList<AstMapAssignment> components;
\r
328 AstMapAssignment assignment;
\r
330 { components = new ArrayList<AstMapAssignment>(); }
\r
331 assignment=mapAssignment() { components.add(assignment); }
\r
332 ("," assignment=mapAssignment() { components.add(assignment); })*
\r
333 { return new AstMap(components); }
\r
334 | { return AstMap.EMPTY; }
\r
337 AstComponentAssignment assignment() : {
\r
341 name=<IDENT> "=" value=value()
\r
342 { return new AstComponentAssignment(name.image, value); }
\r
345 AstMapAssignment mapAssignment() : {
\r
349 key=value() "=" value=value()
\r
350 { return new AstMapAssignment(key, value); }
\r