Package: TypeReader

TypeReader

nameinstructionbranchcomplexitylinemethod
TypeReader(LexTokenReader)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
productExpand(PType)
M: 0 C: 26
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
readBasicType()
M: 4 C: 146
97%
M: 1 C: 15
94%
M: 1 C: 15
94%
M: 1 C: 53
98%
M: 0 C: 1
100%
readComposeType()
M: 0 C: 43
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 12
100%
M: 0 C: 1
100%
readDiscretionaryType()
M: 0 C: 37
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 12
100%
M: 0 C: 1
100%
readFieldList()
M: 22 C: 172
89%
M: 4 C: 22
85%
M: 4 C: 10
71%
M: 5 C: 42
89%
M: 0 C: 1
100%
readMapType()
M: 0 C: 54
100%
M: 0 C: 3
100%
M: 0 C: 3
100%
M: 0 C: 15
100%
M: 0 C: 1
100%
readOperationType()
M: 0 C: 22
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
readProductType()
M: 0 C: 39
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 10
100%
M: 0 C: 1
100%
readSetSeqType()
M: 4 C: 79
95%
M: 1 C: 6
86%
M: 1 C: 5
83%
M: 1 C: 22
96%
M: 0 C: 1
100%
readType()
M: 4 C: 39
91%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 1 C: 10
91%
M: 0 C: 1
100%
readUnionType()
M: 0 C: 24
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 7
100%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: *
3: *        Copyright (c) 2008 Fujitsu Services Ltd.
4: *
5: *        Author: Nick Battle
6: *
7: *        This file is part of VDMJ.
8: *
9: *        VDMJ is free software: you can redistribute it and/or modify
10: *        it under the terms of the GNU General Public License as published by
11: *        the Free Software Foundation, either version 3 of the License, or
12: *        (at your option) any later version.
13: *
14: *        VDMJ is distributed in the hope that it will be useful,
15: *        but WITHOUT ANY WARRANTY; without even the implied warranty of
16: *        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: *        GNU General Public License for more details.
18: *
19: *        You should have received a copy of the GNU General Public License
20: *        along with VDMJ. If not, see <http://www.gnu.org/licenses/>.
21: *
22: ******************************************************************************/
23:
24: package org.overture.parser.syntax;
25:
26: import java.util.List;
27: import java.util.Vector;
28:
29: import org.overture.ast.factory.AstFactory;
30: import org.overture.ast.intf.lex.ILexLocation;
31: import org.overture.ast.lex.LexIdentifierToken;
32: import org.overture.ast.lex.LexNameToken;
33: import org.overture.ast.lex.LexQuoteToken;
34: import org.overture.ast.lex.LexToken;
35: import org.overture.ast.lex.VDMToken;
36: import org.overture.ast.types.AFieldField;
37: import org.overture.ast.types.AOperationType;
38: import org.overture.ast.types.AProductType;
39: import org.overture.ast.types.ARecordInvariantType;
40: import org.overture.ast.types.AVoidType;
41: import org.overture.ast.types.PField;
42: import org.overture.ast.types.PType;
43: import org.overture.config.Release;
44: import org.overture.config.Settings;
45: import org.overture.parser.lex.LexException;
46: import org.overture.parser.lex.LexTokenReader;
47:
48: /**
49: * A syntax analyser to parse type expressions.
50: */
51:
52: public class TypeReader extends SyntaxReader
53: {
54:         public TypeReader(LexTokenReader reader)
55:         {
56:                 super(reader);
57:         }
58:
59:         public PType readType() throws ParserException, LexException
60:         {
61:                 PType type = readDiscretionaryType();
62:
63:•                if (lastToken().is(VDMToken.ARROW)
64:•                                || lastToken().is(VDMToken.TOTAL_FUNCTION))
65:                 {
66:                         LexToken token = lastToken();
67:                         nextToken();
68:                         PType result = readType();
69:
70:                         type = AstFactory.newAFunctionType(token.location, token.is(VDMToken.ARROW), productExpand(type), result);
71:                 }
72:•                else if (type instanceof AVoidType)
73:                 {
74:                         throwMessage(2070, "Cannot use '()' type here");
75:                 }
76:
77:                 return type;
78:         }
79:         
80:         private PType readDiscretionaryType()
81:                         throws ParserException, LexException
82:         {
83:                 LexToken token = lastToken();
84:                 ILexLocation location = token.location;
85:                 PType type = null;
86:
87:•                if (token.is(VDMToken.BRA))
88:                 {
89:                         reader.push();
90:
91:•                        if (nextToken().is(VDMToken.KET))
92:                         {
93:                                 type = AstFactory.newAVoidType(location);
94:                                 nextToken();
95:                                 reader.unpush();
96:                                 return type;
97:                         }
98:                         else
99:                         {
100:                                 reader.pop();
101:                         }
102:                 }
103:
104:                 return readUnionType();
105:         }
106:
107:         private PType readUnionType() throws ParserException, LexException
108:         {
109:                 PType type = readProductType();
110:
111:•                while (lastToken().type == VDMToken.PIPE)
112:                 {
113:                         LexToken token = lastToken();
114:                         nextToken();
115:                         type = AstFactory.newAUnionType(token.location, type, readProductType());
116:                 }
117:
118:                 return type;
119:         }
120:
121:         private PType readProductType() throws ParserException, LexException
122:         {
123:                 LexToken token = lastToken();
124:                 PType type = readComposeType();
125:                 List<PType> productList = new Vector<PType>();
126:                 productList.add(type);
127:
128:•                while (lastToken().type == VDMToken.TIMES)
129:                 {
130:                         nextToken();
131:                         productList.add(readComposeType());
132:                 }
133:
134:•                if (productList.size() == 1)
135:                 {
136:                         return type;
137:                 }
138:
139:                 return AstFactory.newAProductType(token.location, productList);
140:         }
141:
142:         private PType readComposeType() throws ParserException, LexException
143:         {
144:                 PType type = null;
145:
146:•                if (lastToken().is(VDMToken.COMPOSE))
147:                 {
148:                         nextToken();
149:                         LexIdentifierToken id = readIdToken("Compose not followed by record identifier");
150:                         checkFor(VDMToken.OF, 2249, "Missing 'of' in compose type");
151:                         ARecordInvariantType rtype = AstFactory.newARecordInvariantType(idToName(id), readFieldList());
152:                         rtype.setComposed(true);
153:                         checkFor(VDMToken.END, 2250, "Missing 'end' in compose type");
154:                         type = rtype;
155:                 } else
156:                 {
157:                         type = readMapType();
158:                 }
159:
160:                 return type;
161:         }
162:
163:         public List<AFieldField> readFieldList() throws ParserException,
164:                         LexException
165:         {
166:                 List<AFieldField> list = new Vector<AFieldField>();
167:
168:•                while (lastToken().isNot(VDMToken.END)
169:•                                && lastToken().isNot(VDMToken.SEMICOLON)
170:•                                && lastToken().isNot(VDMToken.INV))
171:                 {
172:                         reader.push();
173:                         LexToken tag = lastToken();
174:                         LexToken separator = nextToken();
175:
176:•                        if (separator.is(VDMToken.COLON))
177:                         {
178:•                                if (tag.isNot(VDMToken.IDENTIFIER))
179:                                 {
180:                                         throwMessage(2071, "Expecting field identifier before ':'");
181:                                 }
182:
183:                                 nextToken();
184:                                 LexIdentifierToken tagid = (LexIdentifierToken) tag;
185:
186:•                                if (tagid.isOld())
187:                                 {
188:                                         throwMessage(2295, "Can't use old name here", tag);
189:                                 }
190:
191:                                 LexNameToken tagname = idToName(tagid);
192:                                 list.add(AstFactory.newAFieldField(tagname, tagid.getName(), readType(), false));
193:                                 reader.unpush();
194:•                        } else if (separator.is(VDMToken.EQABST))
195:                         {
196:•                                if (tag.isNot(VDMToken.IDENTIFIER))
197:                                 {
198:                                         throwMessage(2072, "Expecting field name before ':-'");
199:                                 }
200:
201:                                 nextToken();
202:                                 LexIdentifierToken tagid = (LexIdentifierToken) tag;
203:
204:•                                if (tagid.isOld())
205:                                 {
206:                                         throwMessage(2295, "Can't use old name here", tag);
207:                                 }
208:
209:                                 LexNameToken tagname = idToName(tagid);
210:                                 list.add(AstFactory.newAFieldField(tagname, tagid.getName(), readType(), true));
211:                                 reader.unpush();
212:                         } else
213:                         // Anonymous field or end of fields
214:                         {
215:                                 try
216:                                 {
217:                                         reader.retry();
218:                                         String anon = Integer.toString(list.size() + 1);
219:                                         PType ftype = readType();
220:                                         LexNameToken tagname = new LexNameToken(getCurrentModule(), anon, ftype.getLocation());
221:                                         list.add(AstFactory.newAFieldField(tagname, anon, ftype, false));
222:                                         reader.unpush();
223:                                 } catch (Exception e)
224:                                 {
225:                                         // End? EOF? Or badly formed type, fails elsewhere...
226:                                         reader.pop();
227:                                         break;
228:                                 }
229:                         }
230:                 }
231:
232:•                for (PField f1 : list)
233:                 {
234:•                        for (PField f2 : list)
235:                         {
236:•                                if (f1 != f2
237:•                                                && ((AFieldField) f1).getTag().equals(((AFieldField) f2).getTag()))
238:                                 {
239:                                         throwMessage(2073, "Duplicate field names in record type");
240:                                 }
241:                         }
242:                 }
243:
244:                 return list;
245:         }
246:
247:         private PType readMapType() throws ParserException, LexException
248:         {
249:                 PType type = null;
250:                 LexToken token = lastToken();
251:
252:•                switch (token.type)
253:                 {
254:                         case MAP:
255:                                 nextToken();
256:                                 type = readType(); // Effectively bracketed by 'to'
257:                                 checkFor(VDMToken.TO, 2251, "Expecting 'to' in map type");
258:                                 type = AstFactory.newAMapMapType(token.location, type, readComposeType());
259:                                 break;
260:
261:                         case INMAP:
262:                                 nextToken();
263:                                 type = readType(); // Effectively bracketed by 'to'
264:                                 checkFor(VDMToken.TO, 2252, "Expecting 'to' in inmap type");
265:                                 type = AstFactory.newAInMapMapType(token.location, type, readComposeType());
266:                                 break;
267:
268:                         default:
269:                                 type = readSetSeqType();
270:                                 break;
271:                 }
272:
273:                 return type;
274:         }
275:
276:         private PType readSetSeqType() throws ParserException, LexException
277:         {
278:                 PType type = null;
279:                 LexToken token = lastToken();
280:
281:•                switch (token.type)
282:                 {
283:                         case SET:
284:                                 nextToken();
285:                                 checkFor(VDMToken.OF, 2253, "Expecting 'of' after set");
286:                                 type = AstFactory.newASetSetType(token.location, readComposeType());
287:                                 break;
288:
289:                         case SET1:
290:•                                if (Settings.release == Release.CLASSIC)
291:                                 {
292:                                         throwMessage(2327, "Type set1 is not available in classic");
293:                                 }
294:                                 
295:                                 nextToken();
296:                                 checkFor(VDMToken.OF, 2326, "Expecting 'of' after set1");
297:                                 type = AstFactory.newASet1SetType(token.location, readComposeType());
298:                                 break;
299:
300:                         case SEQ:
301:                                 nextToken();
302:                                 checkFor(VDMToken.OF, 2254, "Expecting 'of' after seq");
303:                                 type = AstFactory.newASeqSeqType(token.location, readComposeType());
304:                                 break;
305:
306:                         case SEQ1:
307:                                 nextToken();
308:                                 checkFor(VDMToken.OF, 2255, "Expecting 'of' after seq1");
309:                                 type = AstFactory.newASeq1SeqType(token.location, readComposeType());
310:                                 break;
311:
312:                         default:
313:                                 type = readBasicType();
314:                                 break;
315:                 }
316:
317:                 return type;
318:         }
319:
320:         private PType readBasicType() throws ParserException, LexException
321:         {
322:                 PType type = null;
323:                 LexToken token = lastToken();
324:                 ILexLocation location = token.location;
325:
326:•                switch (token.type)
327:                 {
328:                         case NAT:
329:                                 type = AstFactory.newANatNumericBasicType(location);
330:                                 nextToken();
331:                                 break;
332:
333:                         case NAT1:
334:                                 type = AstFactory.newANatOneNumericBasicType(location);
335:                                 nextToken();
336:                                 break;
337:
338:                         case BOOL:
339:                                 type = AstFactory.newABooleanBasicType(location);
340:                                 nextToken();
341:                                 break;
342:
343:                         case REAL:
344:                                 type = AstFactory.newARealNumericBasicType(location);
345:                                 nextToken();
346:                                 break;
347:
348:                         case INT:
349:                                 type = AstFactory.newAIntNumericBasicType(location);
350:                                 nextToken();
351:                                 break;
352:
353:                         case RAT:
354:                                 type = AstFactory.newARationalNumericBasicType(location);
355:                                 nextToken();
356:                                 break;
357:
358:                         case CHAR:
359:                                 type = AstFactory.newACharBasicType(location);
360:                                 nextToken();
361:                                 break;
362:
363:                         case TOKEN:
364:                                 type = AstFactory.newATokenBasicType(location);
365:                                 nextToken();
366:                                 break;
367:
368:                         case QUOTE:
369:                                 type = AstFactory.newAQuoteType((LexQuoteToken) token);
370:                                 nextToken();
371:                                 break;
372:
373:                         case BRA:
374:                                 nextToken();
375:                                 type = AstFactory.newABracketType(location, readType());
376:                                 checkFor(VDMToken.KET, 2256, "Bracket mismatch");
377:                                 break;
378:
379:                         case SEQ_OPEN:
380:                                 nextToken();
381:                                 type = AstFactory.newAOptionalType(location, readType());
382:                                 checkFor(VDMToken.SEQ_CLOSE, 2257, "Missing close bracket after optional type");
383:                                 break;
384:
385:                         case IDENTIFIER:
386:                                 LexIdentifierToken id = (LexIdentifierToken) token;
387:                                 type = AstFactory.newAUnresolvedType(idToName(id));
388:                                 nextToken();
389:                                 break;
390:
391:                         case NAME:
392:                                 type = AstFactory.newAUnresolvedType((LexNameToken) token);
393:                                 nextToken();
394:                                 break;
395:
396:                         case AT:
397:                                 nextToken();
398:                                 type = AstFactory.newAParameterType(idToName(readIdToken("Invalid type parameter")));
399:                                 break;
400:
401:                         case QMARK:
402:                                 nextToken();
403:                                 type = AstFactory.newAUnknownType(location); // Not strictly VDM :-)
404:                                 break;
405:
406:                         default:
407:                                 throwMessage(2074, "Unexpected token in type expression");
408:                 }
409:
410:                 return type;
411:         }
412:
413:         public AOperationType readOperationType() throws ParserException,
414:                         LexException
415:         {
416:                 PType paramtype = readDiscretionaryType();
417:                 LexToken arrow = lastToken();
418:                 checkFor(VDMToken.OPDEF, 2258, "Expecting '==>' in explicit operation type");
419:                 PType resulttype = readDiscretionaryType();
420:                 return AstFactory.newAOperationType(arrow.location, productExpand(paramtype), resulttype);
421:         }
422:
423:         private List<PType> productExpand(PType parameters)
424:         {
425:                 List<PType> types = new Vector<PType>();
426:
427:•                if (parameters instanceof AProductType)
428:                 {
429:                         // Expand unbracketed product types
430:                         AProductType pt = (AProductType) parameters;
431:                         types.addAll(pt.getTypes());
432:•                } else if (parameters instanceof AVoidType)
433:                 {
434:                         // No type
435:                 } else
436:                 {
437:                         // One parameter, including bracketed product types
438:                         types.add(parameters);
439:                 }
440:
441:                 return types;
442:         }
443: }