Package: SyntaxReader

SyntaxReader

nameinstructionbranchcomplexitylinemethod
SyntaxReader()
M: 45 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 14 C: 0
0%
M: 1 C: 0
0%
SyntaxReader(LexTokenReader)
M: 0 C: 46
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 14
100%
M: 0 C: 1
100%
afterAnnotations(ClassReader, List, SClassDefinition)
M: 17 C: 7
29%
M: 3 C: 1
25%
M: 2 C: 1
33%
M: 4 C: 2
33%
M: 0 C: 1
100%
afterAnnotations(DefinitionReader, List, PDefinition)
M: 17 C: 7
29%
M: 3 C: 1
25%
M: 2 C: 1
33%
M: 4 C: 2
33%
M: 0 C: 1
100%
afterAnnotations(ExpressionReader, List, PExp)
M: 24 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
afterAnnotations(ModuleReader, List, AModuleModules)
M: 17 C: 7
29%
M: 3 C: 1
25%
M: 2 C: 1
33%
M: 4 C: 2
33%
M: 0 C: 1
100%
afterAnnotations(StatementReader, List, PStm)
M: 24 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
beforeAnnotations(SyntaxReader, List)
M: 65 C: 7
10%
M: 13 C: 1
7%
M: 7 C: 1
13%
M: 14 C: 2
13%
M: 0 C: 1
100%
checkFor(VDMToken, int, String)
M: 4 C: 10
71%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 3
75%
M: 0 C: 1
100%
close()
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
getBindReader()
M: 0 C: 19
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
getClassReader()
M: 19 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
getComments()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getCurrentModule()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getDefinitionReader()
M: 0 C: 19
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
getErrorCount()
M: 0 C: 25
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
getErrors()
M: 0 C: 28
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
getExpressionReader()
M: 0 C: 19
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
getPatternReader()
M: 0 C: 19
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
getStatementReader()
M: 0 C: 19
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
getTypeReader()
M: 0 C: 19
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
getWarningCount()
M: 0 C: 25
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
getWarnings()
M: 0 C: 28
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
idToName(LexIdentifierToken)
M: 0 C: 10
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
ignore(VDMToken)
M: 0 C: 12
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
isReserved(String)
M: 0 C: 39
100%
M: 7 C: 11
61%
M: 7 C: 3
30%
M: 0 C: 9
100%
M: 0 C: 1
100%
lastIdToken()
M: 11 C: 16
59%
M: 2 C: 2
50%
M: 2 C: 1
33%
M: 3 C: 5
63%
M: 0 C: 1
100%
lastNameToken()
M: 33 C: 15
31%
M: 6 C: 2
25%
M: 4 C: 1
20%
M: 8 C: 5
38%
M: 0 C: 1
100%
lastToken()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
loadAnnotationImpl(LexIdentifierToken)
M: 82 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 12 C: 0
0%
M: 1 C: 0
0%
nextToken()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
printErrors(PrintWriter)
M: 17 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
printWarnings(PrintWriter)
M: 17 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
readAnnotation(LexTokenReader)
M: 39 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 11 C: 0
0%
M: 1 C: 0
0%
readAnnotations(ILexCommentList)
M: 33 C: 31
48%
M: 4 C: 4
50%
M: 3 C: 2
40%
M: 6 C: 6
50%
M: 0 C: 1
100%
readIdToken(String)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
readIdToken(String, boolean)
M: 29 C: 30
51%
M: 3 C: 7
70%
M: 3 C: 3
50%
M: 5 C: 8
62%
M: 0 C: 1
100%
readNameToken(String)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
readNameToken(String, boolean)
M: 26 C: 49
65%
M: 4 C: 12
75%
M: 4 C: 5
56%
M: 6 C: 12
67%
M: 0 C: 1
100%
readToken()
M: 0 C: 10
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
report(LocatedException, VDMToken[], VDMToken[])
M: 26 C: 47
64%
M: 1 C: 7
88%
M: 1 C: 4
80%
M: 4 C: 13
76%
M: 0 C: 1
100%
setCurrentModule(String)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
static {...}
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
throwMessage(int, String)
M: 0 C: 12
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
throwMessage(int, String, ILexToken)
M: 0 C: 11
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
throwMessage(int, String, int)
M: 10 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
toString()
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
warning(int, String, ILexLocation)
M: 34 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%

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.io.PrintWriter;
27: import java.lang.reflect.Constructor;
28: import java.util.Arrays;
29: import java.util.List;
30: import java.util.Vector;
31:
32: import org.overture.ast.annotations.Annotation;
33: import org.overture.ast.annotations.PAnnotation;
34: import org.overture.ast.definitions.PDefinition;
35: import org.overture.ast.definitions.SClassDefinition;
36: import org.overture.ast.expressions.PExp;
37: import org.overture.ast.factory.AstFactory;
38: import org.overture.ast.intf.lex.ILexCommentList;
39: import org.overture.ast.intf.lex.ILexLocation;
40: import org.overture.ast.intf.lex.ILexToken;
41: import org.overture.ast.lex.Dialect;
42: import org.overture.ast.lex.LexIdentifierToken;
43: import org.overture.ast.lex.LexNameToken;
44: import org.overture.ast.lex.LexToken;
45: import org.overture.ast.lex.VDMToken;
46: import org.overture.ast.messages.InternalException;
47: import org.overture.ast.modules.AModuleModules;
48: import org.overture.ast.statements.PStm;
49: import org.overture.config.Release;
50: import org.overture.config.Settings;
51: import org.overture.parser.annotations.ASTAnnotation;
52: import org.overture.parser.lex.LexException;
53: import org.overture.parser.lex.LexTokenReader;
54: import org.overture.parser.messages.LocatedException;
55: import org.overture.parser.messages.VDMError;
56: import org.overture.parser.messages.VDMWarning;
57:
58: /**
59: * The parent class of all syntax readers.
60: */
61:
62: public abstract class SyntaxReader
63: {
64:         /** The lexical analyser. */
65:         protected final LexTokenReader reader;
66:         /** The dialect of VDM that we're parsing. */
67:         protected final Dialect dialect;
68:
69:         /** A DefinitionReader, if created. */
70:         protected DefinitionReader definitionReader = null;
71:         /** An ExpressionReader, if created. */
72:         protected ExpressionReader expressionReader = null;
73:         /** A PatternReader, if created. */
74:         protected PatternReader patternReader = null;
75:         /** A TypeReader, if created. */
76:         protected TypeReader typeReader = null;
77:         /** A BindReader, if created. */
78:         protected BindReader bindReader = null;
79:         /** A StatementReader, if created. */
80:         protected StatementReader statementReader = null;
81:         /** A ClassReader, if created. */
82:         protected ClassReader classReader = null;
83:
84:         /** The errors raised. */
85:         private List<VDMError> errors = new Vector<VDMError>();
86:
87:         /** The warnings raised. */
88:         private List<VDMWarning> warnings = new Vector<VDMWarning>();
89:
90:         /** The sub-readers defined, if any. */
91:         private List<SyntaxReader> readers = new Vector<SyntaxReader>();
92:
93:         /** The maximum number of syntax errors allowed in one Reader. */
94:         private static final int MAX = 100;
95:
96:         /**
97:          * Create a reader with the given lexical analyser and VDM++ flag.
98:          */
99:
100:         protected SyntaxReader(LexTokenReader reader)
101:         {
102:                 this.reader = reader;
103:                 this.dialect = reader.dialect;
104:         }
105:
106:         protected SyntaxReader()
107:         {
108:                 this.reader = null;
109:                 this.dialect = null;
110:         }
111:
112:         /**
113:          * Read the next token from the lexical analyser, and advance by one token.
114:          *
115:          * @return The next token.
116:          */
117:
118:         protected LexToken nextToken() throws LexException
119:         {
120:                 return reader.nextToken();
121:         }
122:
123:         /**
124:          * Return the last token read by the lexical analyser without advancing. Repeated calls to this method will return
125:          * the same result.
126:          *
127:          * @return The last token again.
128:          */
129:
130:         protected LexToken lastToken() throws LexException
131:         {
132:                 return reader.getLast();
133:         }
134:
135:         /**
136:          * Return the last token read, and also advance by one token. This is equivalent to calling {@link #lastToken}
137:          * followed by {@link #nextToken}, but returning the result of lastToken.
138:          *
139:          * @return The last token.
140:          * @throws LexException
141:          */
142:
143:         protected LexToken readToken() throws LexException
144:         {
145:                 LexToken tok = reader.getLast();
146:                 reader.nextToken();
147:                 return tok;
148:         }
149:
150:         /**
151:          * Set the name of the current module or class. Unqualified symbol names use this as their module/class name. See
152:          * {@link #idToName}.
153:          *
154:          * @param module
155:          */
156:
157:         public void setCurrentModule(String module)
158:         {
159:                 reader.currentModule = module;
160:         }
161:
162:         /**
163:          * @return The current module/class name.
164:          */
165:
166:         public String getCurrentModule()
167:         {
168:                 return reader.currentModule;
169:         }
170:
171:         /**
172:          * Convert an identifier into a name. A name is an identifier that has a module name qualifier, so this method uses
173:          * the current module to convert the identifier passed in.
174:          *
175:          * @param id
176:          * The identifier to convert
177:          * @return The corresponding name.
178:          */
179:
180:         protected LexNameToken idToName(LexIdentifierToken id)
181:         {
182:                 LexNameToken name = new LexNameToken(reader.currentModule, id);
183:                 return name;
184:         }
185:
186:         /**
187:          * Return the last token, converted to a {@link LexIdentifierToken}. If the last token is not an identifier token,
188:          * an exception is thrown with the message passed in.
189:          *
190:          * @return The last token as a LexIdentifierToken.
191:          * @throws LexException
192:          */
193:
194:         protected LexIdentifierToken lastIdToken() throws ParserException,
195:                         LexException
196:         {
197:                 LexToken tok = reader.getLast();
198:
199:•                if (tok.type == VDMToken.IDENTIFIER)
200:                 {
201:                         LexIdentifierToken id = (LexIdentifierToken) tok;
202:
203:•                        if (id.isOld())
204:                         {
205:                                 throwMessage(2295, "Can't use old name here", tok);
206:                         }
207:
208:                         return id;
209:                 }
210:
211:                 throwMessage(2058, "Expecting Identifier");
212:                 return null;
213:         }
214:
215:         /**
216:          * Return the last token, converted to a {@link LexNameToken}. If the last token is not a name token, or an
217:          * identifier token that can be converted to a name, an exception is thrown with the message passed in.
218:          *
219:          * @return The last token as a LexIdentifierToken.
220:          * @throws LexException
221:          * @throws ParserException
222:          */
223:
224:         protected LexNameToken lastNameToken() throws LexException, ParserException
225:         {
226:                 LexToken tok = reader.getLast();
227:
228:•                if (tok instanceof LexNameToken)
229:                 {
230:                         LexNameToken name = (LexNameToken) tok;
231:
232:•                        if (name.old)
233:                         {
234:                                 throwMessage(2295, "Can't use old name here", tok);
235:                         }
236:
237:                         return name;
238:•                } else if (tok instanceof LexIdentifierToken)
239:                 {
240:                         LexIdentifierToken id = (LexIdentifierToken) tok;
241:
242:•                        if (id.isOld())
243:                         {
244:                                 throwMessage(2295, "Can't use old name here", tok);
245:                         }
246:
247:                         return new LexNameToken(reader.currentModule, id);
248:                 }
249:
250:                 throwMessage(2059, "Expecting a name");
251:                 return null;
252:         }
253:
254:         /**
255:          * Return the last token as an identifier, and advance by one token. This is similar to calling {@link #lastIdToken}
256:          * followed by nextToken, and returning the result of the lastIdToken.
257:          *
258:          * @param message
259:          * The message to throw if the last token is not an id.
260:          * @return The last token as a LexIdentifierToken.
261:          * @throws LexException
262:          * @throws ParserException
263:          */
264:
265:         protected LexIdentifierToken readIdToken(String message)
266:                         throws LexException, ParserException
267:         {
268:                 return readIdToken(message, false);
269:         }
270:
271:         protected LexIdentifierToken readIdToken(String message, boolean reservedOK)
272:                         throws LexException, ParserException
273:         {
274:                 LexToken tok = reader.getLast();
275:
276:•                if (tok.type == VDMToken.IDENTIFIER)
277:                 {
278:                         nextToken();
279:                         LexIdentifierToken id = (LexIdentifierToken) tok;
280:
281:•                        if (id.isOld())
282:                         {
283:                                 throwMessage(2295, "Can't use old name here", tok);
284:                         }
285:
286:•                        if (!reservedOK && isReserved(id.name))
287:                         {
288:                                 throwMessage(2295, "Name contains a reserved prefix", tok);
289:                         }
290:
291:                         return id;
292:                 }
293:
294:•                if (tok.type == VDMToken.NAME)
295:                 {
296:                         message = "Found qualified name " + tok + ". " + message;
297:                 }
298:
299:                 throwMessage(2060, message);
300:                 return null;
301:         }
302:
303:         /**
304:          * Return the last token as a name, and advance by one token. This is similar to calling {@link #lastNameToken}
305:          * followed by nextToken, and returning the result of the lastNameToken.
306:          *
307:          * @param message
308:          * The message to throw if the last token is not a name.
309:          * @return The last token as a LexNameToken.
310:          * @throws LexException
311:          * @throws ParserException
312:          */
313:
314:         protected LexNameToken readNameToken(String message) throws LexException, ParserException
315:         {
316:                 return readNameToken(message, false);
317:         }
318:
319:         protected LexNameToken readNameToken(String message, boolean reservedOK) throws LexException,
320:                         ParserException
321:         {
322:                 LexToken tok = reader.getLast();
323:                 nextToken();
324:
325:•                if (tok instanceof LexNameToken)
326:                 {
327:                         LexNameToken name = (LexNameToken) tok;
328:
329:•                        if (name.old)
330:                         {
331:                                 throwMessage(2295, "Can't use old name here", tok);
332:                         }
333:
334:•                        if (!reservedOK && isReserved(name.name))
335:                         {
336:                                 throwMessage(2295, "Name contains a reserved prefix", tok);
337:                         }
338:
339:                         return name;
340:•                } else if (tok instanceof LexIdentifierToken)
341:                 {
342:                         LexIdentifierToken id = (LexIdentifierToken) tok;
343:
344:•                        if (id.isOld())
345:                         {
346:                                 throwMessage(2295, "Can't use old name here", tok);
347:                         }
348:
349:•                        if (!reservedOK && isReserved(id.name))
350:                         {
351:                                 throwMessage(2295, "Name contains a reserved prefix", tok);
352:                         }
353:
354:                         return new LexNameToken(reader.currentModule, id);
355:                 }
356:
357:                 throwMessage(2061, message);
358:                 return null;
359:         }
360:
361:         /**
362:          * Read any annotations from the collected comments, and clear them.
363:          */
364:         private static int readingAnnotations = 0;
365:         
366:         protected List<PAnnotation> readAnnotations(ILexCommentList comments) throws LexException, ParserException
367:         {
368:                 List<PAnnotation> annotations = new Vector<PAnnotation>();
369:•                if (readingAnnotations > 0) return annotations; else readingAnnotations++;
370:                 
371:•                for (int i=0; i<comments.size(); i++)
372:                 {
373:•                        if (comments.getComment(i).trim().startsWith("@"))
374:                         {
375:                                 try
376:                                 {
377:                                         annotations.add(readAnnotation(new LexTokenReader(
378:                                                         comments.getComment(i), comments.getLocation(i), reader)));
379:                                 }
380:                                 catch (Exception e)
381:                                 {
382:•                                        if (System.getProperty("annotations.debug") != null)
383:                                         {
384:                                                 System.err.println("Annotations: " + e);
385:                                         }
386:                                 }
387:                         }
388:                 }
389:                 
390:                 readingAnnotations--;
391:                 return annotations;
392:         }
393:         
394:         private PAnnotation readAnnotation(LexTokenReader ltr) throws LexException, ParserException
395:         {
396:                 ltr.nextToken();
397:                 
398:•                if (ltr.nextToken().is(VDMToken.IDENTIFIER))
399:                 {
400:                         LexIdentifierToken name = (LexIdentifierToken)ltr.getLast();
401:                         ASTAnnotation impl = loadAnnotationImpl(name);
402:                         List<PExp> args = impl.parse(ltr);
403:                         PAnnotation ast = AstFactory.newAAnnotationAnnotation(name, args);
404:                         ast.setImpl((Annotation) impl);
405:                         impl.setAST(ast);
406:                         return ast;
407:                 }
408:                 
409:                 throwMessage(0, "Comment has no @Annotation");
410:                 return null;
411:         }
412:
413:         /**
414:          * @return A new DefinitionReader.
415:          */
416:
417:         protected DefinitionReader getDefinitionReader()
418:         {
419:•                if (definitionReader == null)
420:                 {
421:                         definitionReader = new DefinitionReader(reader);
422:                         readers.add(definitionReader);
423:                 }
424:
425:                 return definitionReader;
426:         }
427:
428:         /**
429:          * @return A new DefinitionReader.
430:          */
431:
432:         protected ExpressionReader getExpressionReader()
433:         {
434:•                if (expressionReader == null)
435:                 {
436:                         expressionReader = new ExpressionReader(reader);
437:                         readers.add(expressionReader);
438:                 }
439:
440:                 return expressionReader;
441:         }
442:
443:         /**
444:          * @return A new PatternReader.
445:          */
446:
447:         protected PatternReader getPatternReader()
448:         {
449:•                if (patternReader == null)
450:                 {
451:                         patternReader = new PatternReader(reader);
452:                         readers.add(patternReader);
453:                 }
454:
455:                 return patternReader;
456:         }
457:
458:         /**
459:          * @return A new TypeReader.
460:          */
461:
462:         protected TypeReader getTypeReader()
463:         {
464:•                if (typeReader == null)
465:                 {
466:                         typeReader = new TypeReader(reader);
467:                         readers.add(typeReader);
468:                 }
469:
470:                 return typeReader;
471:         }
472:
473:         /**
474:          * @return A new BindReader.
475:          */
476:
477:         protected BindReader getBindReader()
478:         {
479:•                if (bindReader == null)
480:                 {
481:                         bindReader = new BindReader(reader);
482:                         readers.add(bindReader);
483:                 }
484:
485:                 return bindReader;
486:         }
487:
488:         /**
489:          * @return A new StatementReader.
490:          */
491:
492:         protected StatementReader getStatementReader()
493:         {
494:•                if (statementReader == null)
495:                 {
496:                         statementReader = new StatementReader(reader);
497:                         readers.add(statementReader);
498:                 }
499:
500:                 return statementReader;
501:         }
502:
503:         /**
504:          * @return A new ClassReader.
505:          */
506:
507:         protected ClassReader getClassReader()
508:         {
509:•                if (classReader == null)
510:                 {
511:                         classReader = new ClassReader(reader);
512:                         readers.add(classReader);
513:                 }
514:
515:                 return classReader;
516:         }
517:
518:         public void close()
519:         {
520:                 reader.close();
521:         }
522:
523:         /**
524:          * If the last token is as expected, advance, else raise an error.
525:          *
526:          * @param tok
527:          * The token type to check for.
528:          * @param number
529:          * The error number.
530:          * @param message
531:          * The error message to raise if the token is not as expected.
532:          * @throws LexException
533:          * @throws ParserException
534:          */
535:
536:         protected void checkFor(VDMToken tok, int number, String message)
537:                         throws LexException, ParserException
538:         {
539:•                if (lastToken().is(tok))
540:                 {
541:                         nextToken();
542:                 } else
543:                 {
544:                         throwMessage(number, message);
545:                 }
546:         }
547:
548:         /**
549:          * If the last token is the one passed, advance by one, else do nothing.
550:          *
551:          * @param tok
552:          * The token type to check for.
553:          * @return True if the token was skipped.
554:          * @throws LexException
555:          */
556:
557:         protected boolean ignore(VDMToken tok) throws LexException
558:         {
559:•                if (lastToken().is(tok))
560:                 {
561:                         nextToken();
562:                         return true;
563:                 } else
564:                 {
565:                         return false;
566:                 }
567:         }
568:
569:         /**
570:          * Raise a {@link ParserException} at the current location.
571:          *
572:          * @param number
573:          * The error number.
574:          * @param message
575:          * The error message.
576:          * @throws ParserException
577:          * @throws LexException
578:          */
579:
580:         protected void throwMessage(int number, String message)
581:                         throws ParserException, LexException
582:         {
583:                 throw new ParserException(number, message, lastToken().location, reader.getTokensRead());
584:         }
585:
586:         /**
587:          * Raise a {@link ParserException} at the location of the token passed in.
588:          *
589:          * @param number
590:          * The error number.
591:          * @param message
592:          * The error message.
593:          * @param token
594:          * The location of the error.
595:          * @throws ParserException
596:          */
597:
598:         protected void throwMessage(int number, String message, ILexToken token)
599:                         throws ParserException
600:         {
601:                 throw new ParserException(number, message, token.getLocation(), reader.getTokensRead());
602:         }
603:         
604:         /**
605:          * Raise a {@link ParserException} with a given token depth.
606:          * @param number The error number.
607:          * @param message The error message.
608:          * @param depth The depth of the exception (tokens read).
609:          *
610:          * @throws ParserException
611:          */
612:
613:         protected void throwMessage(int number, String message, int depth)
614:                         throws ParserException, LexException
615:         {
616:                 throw new ParserException(number, message, lastToken().location, depth);
617:         }
618:
619:         /**
620:          * Raise a syntax error and attempt to recover. The error is added to the errors list, and if this exceeds 100
621:          * errors the parser is aborted. The "after" and "upto" lists of token types are then used to control the advance of
622:          * the parser to skip beyond the error. Tokens are read until one occurs in either list or EOF is reached. If the
623:          * token is in the "after" list, one more token is read before returning; if it is in the "upto" list, the last
624:          * token is left pointing to the token before returning. If EOF is reached, the method returns.
625:          *
626:          * @param error
627:          * The exception that caused the error.
628:          * @param after
629:          * A list of tokens to recover to, and step one beyond.
630:          * @param upto
631:          * A list of tokens to recover to.
632:          */
633:
634:         protected void report(LocatedException error, VDMToken[] after,
635:                         VDMToken[] upto)
636:         {
637:                 VDMError vdmerror = new VDMError(error);
638:                 errors.add(vdmerror);
639:
640:•                if (errors.size() >= MAX - 1)
641:                 {
642:                         errors.add(new VDMError(9, "Too many syntax errors", error.location));
643:                         throw new InternalException(9, "Too many syntax errors");
644:                 }
645:
646:                 // Either leave one token beyond something in the after list, or
647:                 // at something in the next upto list.
648:
649:                 List<VDMToken> afterList = Arrays.asList(after);
650:                 List<VDMToken> uptoList = Arrays.asList(upto);
651:
652:                 try
653:                 {
654:                         VDMToken tok = lastToken().type;
655:
656:•                        while (!uptoList.contains(tok) && tok != VDMToken.EOF)
657:                         {
658:•                                if (afterList.contains(tok))
659:                                 {
660:                                         nextToken();
661:                                         break;
662:                                 }
663:
664:                                 tok = nextToken().type;
665:                         }
666:                 } catch (LexException le)
667:                 {
668:                         errors.add(new VDMError(le));
669:                 }
670:         }
671:
672:         /**
673:          * Report a warning. Unlike errors, this does no token recovery.
674:          */
675:
676:         protected void warning(int no, String msg, ILexLocation location)
677:         {
678:                 VDMWarning vdmwarning = new VDMWarning(no, msg, location);
679:                 warnings.add(vdmwarning);
680:
681:•                if (warnings.size() >= MAX - 1)
682:                 {
683:                         errors.add(new VDMError(9, "Too many warnings", location));
684:                         throw new InternalException(9, "Too many warnings");
685:                 }
686:         }
687:
688:         /**
689:          * @return The error count from all readers that can raise errors.
690:          */
691:
692:         public int getErrorCount()
693:         {
694:                 int size = 0;
695:
696:•                for (SyntaxReader rdr : readers)
697:                 {
698:                         size += rdr.getErrorCount();
699:                 }
700:
701:                 return size + errors.size();
702:         }
703:
704:         /**
705:          * @return The errors from all readers that can raise errors.
706:          */
707:
708:         public List<VDMError> getErrors()
709:         {
710:                 List<VDMError> list = new Vector<VDMError>();
711:
712:•                for (SyntaxReader rdr : readers)
713:                 {
714:                         list.addAll(rdr.getErrors());
715:                 }
716:
717:                 list.addAll(errors);
718:                 return list;
719:         }
720:
721:         /**
722:          * @return The warning count from all readers that can raise warnings.
723:          */
724:
725:         public int getWarningCount()
726:         {
727:                 int size = 0;
728:
729:•                for (SyntaxReader rdr : readers)
730:                 {
731:                         size += rdr.getWarningCount();
732:                 }
733:
734:                 return size + warnings.size();
735:         }
736:
737:         /**
738:          * @return The warnings from all readers that can raise warnings.
739:          */
740:
741:         public List<VDMWarning> getWarnings()
742:         {
743:                 List<VDMWarning> list = new Vector<VDMWarning>();
744:
745:•                for (SyntaxReader rdr : readers)
746:                 {
747:                         list.addAll(rdr.getWarnings());
748:                 }
749:
750:                 list.addAll(warnings);
751:                 return list;
752:         }
753:
754:         /**
755:          * Print errors and warnings to the PrintWriter passed.
756:          *
757:          * @param out
758:          */
759:
760:         public void printErrors(PrintWriter out)
761:         {
762:•                for (VDMError e : getErrors())
763:                 {
764:                         out.println(e.toString());
765:                 }
766:         }
767:
768:         public void printWarnings(PrintWriter out)
769:         {
770:•                for (VDMWarning w : getWarnings())
771:                 {
772:                         out.println(w.toString());
773:                 }
774:         }
775:
776:         @Override
777:         public String toString()
778:         {
779:                 return reader.toString();
780:         }
781:         
782:         protected ASTAnnotation loadAnnotationImpl(LexIdentifierToken name)
783:                         throws ParserException, LexException
784:         {
785:                 String classpath = System.getProperty("overture.annotations", "org.overture.annotations;annotations;org.overture.annotations.examples;org.overture.annotations.provided");
786:                 String[] packages = classpath.split(";|:");
787:
788:•                for (String pack: packages)
789:                 {
790:                         try
791:                         {
792:                                 Class<?> clazz = Class.forName(pack + "." + name + "Annotation");
793:                                 Constructor<?> ctor = clazz.getConstructor();
794:                                 return (ASTAnnotation) ctor.newInstance();
795:                         }
796:                         catch (ClassNotFoundException e)
797:                         {
798:                                 // Try the next package
799:                         }
800:                         catch (Exception e)
801:                         {
802:                                 throwMessage(2334, "Failed to instantiate AST" + name + "Annotation");
803:                         }
804:                 }
805:
806:                 throwMessage(2334, "Cannot find AST" + name + "Annotation on " + classpath);
807:                 return null;
808:         }
809:                 
810:         protected ILexCommentList getComments()
811:         {
812:                 return reader.getComments();
813:         }
814:         
815:         /**
816:          * Annotation processing...
817:          */
818:         protected void beforeAnnotations(SyntaxReader reader, List<PAnnotation> annotations)
819:         {
820:•                for (PAnnotation annotation: annotations)
821:                 {
822:•                        if (annotation.getImpl() instanceof ASTAnnotation)
823:                         {
824:                                 ASTAnnotation impl = (ASTAnnotation)annotation.getImpl();
825:                                 
826:                                 // This is not as ugly as multiple overloaded beforeAnotation and beforeAnnotations!
827:•                                if (reader instanceof DefinitionReader)
828:                                 {
829:                                         impl.astBefore((DefinitionReader)reader);
830:                                 }
831:•                                else if (reader instanceof ExpressionReader)
832:                                 {
833:                                         impl.astBefore((ExpressionReader)reader);
834:                                 }
835:•                                else if (reader instanceof StatementReader)
836:                                 {
837:                                         impl.astBefore((StatementReader)reader);
838:                                 }
839:•                                else if (reader instanceof ModuleReader)
840:                                 {
841:                                         impl.astBefore((ModuleReader)reader);
842:                                 }
843:•                                else if (reader instanceof ClassReader)
844:                                 {
845:                                         impl.astBefore((ClassReader)reader);
846:                                 }
847:                                 else
848:                                 {
849:                                         System.err.println("Cannot apply annoation to " + reader.getClass().getSimpleName());
850:                                 }
851:                         }
852:                 }
853:         }
854:
855:         protected void afterAnnotations(DefinitionReader reader, List<PAnnotation> annotations, PDefinition def)
856:         {
857:•                for (PAnnotation annotation: annotations)
858:                 {
859:•                        if (annotation.getImpl() instanceof ASTAnnotation)
860:                         {
861:                                 ASTAnnotation impl = (ASTAnnotation)annotation.getImpl();
862:                                 impl.astAfter(reader, def);
863:                         }
864:                 }
865:         }
866:         
867:         protected void afterAnnotations(ExpressionReader reader, List<PAnnotation> annotations, PExp exp)
868:         {
869:•                for (PAnnotation annotation: annotations)
870:                 {
871:•                        if (annotation.getImpl() instanceof ASTAnnotation)
872:                         {
873:                                 ASTAnnotation impl = (ASTAnnotation)annotation.getImpl();
874:                                 impl.astAfter(reader, exp);
875:                         }
876:                 }
877:         }
878:         
879:         protected void afterAnnotations(StatementReader reader, List<PAnnotation> annotations, PStm stmt)
880:         {
881:•                for (PAnnotation annotation: annotations)
882:                 {
883:•                        if (annotation.getImpl() instanceof ASTAnnotation)
884:                         {
885:                                 ASTAnnotation impl = (ASTAnnotation)annotation.getImpl();
886:                                 impl.astAfter(reader, stmt);
887:                         }
888:                 }
889:         }
890:         
891:         protected void afterAnnotations(ModuleReader reader, List<PAnnotation> annotations, AModuleModules module)
892:         {
893:•                for (PAnnotation annotation: annotations)
894:                 {
895:•                        if (annotation.getImpl() instanceof ASTAnnotation)
896:                         {
897:                                 ASTAnnotation impl = (ASTAnnotation)annotation.getImpl();
898:                                 impl.astAfter(reader, module);
899:                         }
900:                 }
901:         }
902:         
903:         protected void afterAnnotations(ClassReader reader, List<PAnnotation> annotations, SClassDefinition clazz)
904:         {
905:•                for (PAnnotation annotation: annotations)
906:                 {
907:•                        if (annotation.getImpl() instanceof ASTAnnotation)
908:                         {
909:                                 ASTAnnotation impl = (ASTAnnotation)annotation.getImpl();
910:                                 impl.astAfter(reader, clazz);
911:                         }
912:                 }
913:         }
914:
915:         protected boolean isReserved(String name)
916:         {
917:                 return
918:•                        name.startsWith("pre_") ||
919:•                        name.startsWith("post_") ||
920:•                        name.startsWith("inv_") ||
921:•                        name.startsWith("init_") ||
922:                         Settings.release == Release.VDM_10 &&
923:                         (
924:•                                name.startsWith("eq_") ||
925:•                                name.startsWith("ord_") ||
926:•                                name.startsWith("min_") ||
927:•                                name.startsWith("max_")
928:                         );
929:         }
930: }