Package: ParseTcFacade

ParseTcFacade

nameinstructionbranchcomplexitylinemethod
ParseTcFacade()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
checkTcResult(TypeCheckerUtil.TypeCheckResult)
M: 0 C: 29
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
parseExpressionString(String)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
parseModelString(String, Dialect)
M: 48 C: 0
0%
M: 4 C: 0
0%
M: 4 C: 0
0%
M: 12 C: 0
0%
M: 1 C: 0
0%
parseTcExpressionString(String)
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%
parseTcExpressionString(String, Dialect)
M: 9 C: 13
59%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 4
80%
M: 0 C: 1
100%
parseTcPpContent(List, String, boolean)
M: 7 C: 44
86%
M: 3 C: 7
70%
M: 3 C: 3
50%
M: 2 C: 12
86%
M: 0 C: 1
100%
parseTcRtContent(List, String, boolean)
M: 20 C: 31
61%
M: 7 C: 3
30%
M: 5 C: 1
17%
M: 6 C: 8
57%
M: 0 C: 1
100%
parseTcSlContent(List, String, boolean)
M: 20 C: 31
61%
M: 7 C: 3
30%
M: 5 C: 1
17%
M: 6 C: 8
57%
M: 0 C: 1
100%
static {...}
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%
typedAst(List, String, Dialect, boolean)
M: 31 C: 0
0%
M: 4 C: 0
0%
M: 4 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
typedAst(String, String)
M: 13 C: 94
88%
M: 1 C: 7
88%
M: 1 C: 4
80%
M: 2 C: 18
90%
M: 0 C: 1
100%
typedAstFromString(String, Dialect)
M: 48 C: 0
0%
M: 4 C: 0
0%
M: 4 C: 0
0%
M: 12 C: 0
0%
M: 1 C: 0
0%
typedAstNoRetry(List, String, Dialect)
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
typedAstWithRetry(List, String, Dialect)
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * #%~
3: * Overture Testing Framework
4: * %%
5: * Copyright (C) 2008 - 2014 Overture
6: * %%
7: * This program is free software: you can redistribute it and/or modify
8: * it under the terms of the GNU General Public License as
9: * published by the Free Software Foundation, either version 3 of the
10: * License, or (at your option) any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: * GNU General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public
18: * License along with this program. If not, see
19: * <http://www.gnu.org/licenses/gpl-3.0.html>.
20: * #~%
21: */
22: package org.overture.core.testing;
23:
24: import static org.junit.Assert.assertTrue;
25: import static org.junit.Assert.fail;
26:
27: import java.io.File;
28: import java.io.IOException;
29: import java.util.LinkedList;
30: import java.util.List;
31: import java.util.Vector;
32:
33: import org.overture.ast.definitions.SClassDefinition;
34: import org.overture.ast.expressions.PExp;
35: import org.overture.ast.lex.Dialect;
36: import org.overture.ast.lex.LexLocation;
37: import org.overture.ast.modules.AModuleModules;
38: import org.overture.ast.node.INode;
39: import org.overture.config.Release;
40: import org.overture.config.Settings;
41: import org.overture.parser.lex.LexException;
42: import org.overture.parser.syntax.ParserException;
43: import org.overture.parser.util.ParserUtil;
44: import org.overture.typechecker.TypeCheckException;
45: import org.overture.typechecker.util.TypeCheckerUtil;
46: import org.overture.typechecker.util.TypeCheckerUtil.TypeCheckResult;
47:
48: /**
49: * Parse and Type Check VDM Sources. This class is the main interaction point with the Overture parser and type checker.
50: * It calls on them to process and construct ASTs from various kinds of sources.<br>
51: * <br>
52: * All methods in this class will cause test failures if they cannot process the source. If you need more fine-grained
53: * control over the parsing and type checking processes, we suggest using {@link ParserUtil} and {@link TypeCheckerUtil}
54: * .
55: *
56: * @author ldc
57: */
58: public abstract class ParseTcFacade
59: {
60:
61:         static
62:         {
63:                 // Omit paths from locations. Allows error comparison on multiple machines.
64:                 LexLocation.absoluteToStringLocation = false;
65:         }
66:
67:         public static String UTF8 = "UTF-8";
68:
69:         /**
70:          * Parse and type check a VDM model. This method will try to check the model in VDM classic and VDM 10. It assumes
71:          * the model sources are encoded in UTF-8.
72:          *
73:          * @param sources
74:          * the {@link List} of {@link File} containing the model's sources
75:          * @param testName
76:          * the name of the test calling this method (used for failure reporting)
77:          * @param dialect
78:          * the VDM {@link Dialect} the source is written in
79:          * @return the AST of the model, as a list of {@link INode}
80:          * @throws LexException
81:          * @throws ParserException
82:          */
83:         public static List<INode> typedAstWithRetry(List<File> sources,
84:                         String testName, Dialect dialect) throws ParserException,
85:                         LexException
86:         {
87:                 return typedAst(sources, testName, dialect, true);
88:         }
89:
90:         /**
91:          * Parse (but don't type check) a VDM model encoded in a string.
92:          *
93:          * @param model
94:          * the String representing the model
95:          * @param dialect
96:          * the VDM dialect the model is in
97:          * @return the AST of the model, as a list of {@link INode}
98:          */
99:         public static List<INode> parseModelString(String model, Dialect dialect)
100:         {
101:                 Settings.dialect = dialect;
102:                 List<INode> r = new LinkedList<INode>();
103:•                switch (dialect)
104:                 {
105:                         case VDM_SL:
106:                                 r.addAll(ParserUtil.parseSl(model).result);
107:                                 break;
108:                         case VDM_PP:
109:                                 r.addAll(ParserUtil.parseOo(model).result);
110:                                 break;
111:                         case VDM_RT:
112:                                 r.addAll(ParserUtil.parseOo(model).result);
113:                                 break;
114:                         default:
115:                                 fail("Unrecognised dialect:" + dialect);
116:                                 return null;
117:                 }
118:                 return r;
119:         }
120:
121:         /**
122:          * Parse (but don't type check) a VDM expression encoded in a string.
123:          *
124:          * @param expression
125:          * the String representing the expression
126:          * @return the {@link PExp} AST node of the expression
127:          */
128:         public static PExp parseExpressionString(String expression)
129:                         throws ParserException, LexException
130:         {
131:                 return ParserUtil.parseExpression(expression).result;
132:         }
133:
134:         /**
135:          * Parse and type check a VDM expression encoded in a string using VDM_SL. Failure results in an exception.
136:          *
137:          * @param expression
138:          * the String representing the expression
139:          * @return the {@link PExp} AST node of the expression
140:          *
141:          * @see #parseModelString(String, Dialect)
142:          */
143:         public static PExp parseTcExpressionString(String expression)
144:                         throws ParserException, LexException
145:         {
146:                 return parseTcExpressionString(expression, Dialect.VDM_SL);
147:         }
148:
149:         /**
150:          * Parse and type check a VDM expression encoded in a string using the specified dialect. Failure results in an exception.
151:          *
152:          * @param expression
153:          * the String representing the expression
154:          * @param dialect
155:          * the {@link Dialect} to use when checking
156:          * @return the {@link PExp} AST node of the expression
157:          */
158:         public static PExp parseTcExpressionString(String expression,
159:                         Dialect dialect) throws ParserException, LexException,
160:                         TypeCheckException
161:         {
162:                 Settings.dialect = dialect;
163:                 TypeCheckResult<PExp> res = TypeCheckerUtil.typeCheckExpression(expression);
164:•                if (res.errors.isEmpty())
165:                 {
166:                         return res.result;
167:                 }
168:                 throw new TypeCheckException("Cannot type check string expression.", null, res.result);
169:         }
170:
171:         /**
172:          * Parse and type check a VDM model encoded in a string.
173:          *
174:          * @param model
175:          * the String representing the model
176:          * @param dialect
177:          * the VDM dialect the model is in
178:          * @return the AST of the model, as a list of {@link INode}
179:          */
180:         public static List<INode> typedAstFromString(String model, Dialect dialect)
181:                         throws ParserException, LexException
182:         {
183:                 Settings.dialect = dialect;
184:                 List<INode> r = new LinkedList<INode>();
185:•                switch (dialect)
186:                 {
187:                         case VDM_SL:
188:                                 r.addAll(TypeCheckerUtil.typeCheckSl(model).result);
189:                                 break;
190:                         case VDM_PP:
191:                                 r.addAll(TypeCheckerUtil.typeCheckPp(model).result);
192:                                 break;
193:                         case VDM_RT:
194:                                 r.addAll(TypeCheckerUtil.typeCheckRt(model).result);
195:                                 break;
196:                         default:
197:                                 fail("Unrecognised dialect:" + dialect);
198:                                 return null;
199:                 }
200:                 return r;
201:         }
202:
203:         /**
204:          * Parse and type check a VDM model. This method will check the model in whatever language release is currently set.
205:          * It assumes the model sources are encoded in UTF-8.
206:          *
207:          * @param sources
208:          * the {@link List} of {@link File} containing the model's sources
209:          * @param testName
210:          * the name of the test calling this method (used for failure reporting)
211:          * @param dialect
212:          * the VDM {@link Dialect} the source is written in
213:          * @return the AST of the model, as a list of {@link INode}
214:          * @throws LexException
215:          * @throws ParserException
216:          */
217:         public static List<INode> typedAstNoRetry(List<File> sources,
218:                         String testName, Dialect dialect) throws ParserException,
219:                         LexException {
220:                 return typedAst(sources, testName, dialect, false);
221:         }
222:
223:         /**
224:          * Parse and type check a single VDM source file. It assumes the model source is encoded in UTF-8.
225:          *
226:          * @param sourcePath
227:          * a {@link String} with the path to a single VDM model source
228:          * @param testName
229:          * the name of the test calling this method (used for failure reporting)
230:          * @return the AST of the model as a {@link List} of {@link INode}.
231:          * @throws IOException
232:          * @throws ParserException
233:          * @throws LexException
234:          */
235:         public static List<INode> typedAst(String sourcePath, String testName)
236:                         throws IOException, ParserException, LexException
237:         {
238:                 String[] parts = sourcePath.split("\\.");
239:                 String ext;
240:•                if (parts.length == 1)
241:                 {
242:                         ext = "vdm"
243:                                         + sourcePath.substring(sourcePath.length() - 2, sourcePath.length()).toLowerCase();
244:                 } else
245:                 {
246:                         ext = parts[1];
247:                 }
248:                 File f = new File(sourcePath);
249:                 List<File> sources = new Vector<File>();
250:                 sources.add(f);
251:
252:•                if (ext.equals("vdmsl") | ext.equals("vdm"))
253:                 {
254:                         return parseTcSlContent(sources, testName, true);
255:                 }
256:
257:                 else
258:                 {
259:•                        if (ext.equals("vdmpp") | ext.equals("vpp"))
260:                         {
261:                                 List<File> files = new Vector<File>();
262:                                 files.add(f);
263:                                 return parseTcPpContent(files, testName, true);
264:
265:                         } else
266:                         {
267:•                                if (ext.equals("vdmrt"))
268:                                 {
269:                                         List<File> files = new Vector<File>();
270:                                         files.add(f);
271:                                         return parseTcRtContent(files, testName, true);
272:                                 } else
273:                                 {
274:                                         fail("Unexpected extension in file " + sourcePath
275:                                                         + ". Only .vdmpp, .vdmsl and .vdmrt allowed");
276:                                 }
277:                         }
278:                 }
279:
280:                 // only needed to compile. will never hit because of fail()
281:                 return null;
282:         }
283:
284:         private static List<INode> typedAst(List<File> content, String testName,
285:                         Dialect dialect, boolean retry) throws ParserException,
286:                         LexException
287:         {
288:
289:•                switch (dialect)
290:                 {
291:                         case VDM_SL:
292:                                 return parseTcSlContent(content, testName, retry);
293:                         case VDM_PP:
294:                                 return parseTcPpContent(content, testName, retry);
295:                         case VDM_RT:
296:                                 return parseTcRtContent(content, testName, retry);
297:                         default:
298:                                 fail("Unrecognised dialect:" + dialect);
299:                                 return null;
300:                 }
301:
302:         }
303:
304:         // These 3 methods have so much duplicated code because we cannot
305:         // return the TC results since their types are all different.
306:         private static List<INode> parseTcRtContent(List<File> content,
307:                         String testName, boolean retry) throws ParserException,
308:                         LexException
309:         {
310:                 Settings.dialect = Dialect.VDM_RT;
311:
312:                 TypeCheckResult<List<SClassDefinition>> TC = TypeCheckerUtil.typeCheckRt(content, UTF8);
313:
314:                 // retry with other dialect
315:•                if (retry
316:•                                && (!TC.parserResult.errors.isEmpty() || !TC.errors.isEmpty()))
317:                 {
318:•                        if (Settings.release == Release.CLASSIC)
319:                         {
320:                                 Settings.release = Release.VDM_10;
321:                                 return parseTcRtContent(content, testName, false);
322:                         }
323:•                        if (Settings.release == Release.VDM_10)
324:                         {
325:                                 Settings.release = Release.CLASSIC;
326:                                 return parseTcRtContent(content, testName, false);
327:                         }
328:                 }
329:
330:                 checkTcResult(TC);
331:
332:                 List<INode> r = new LinkedList<INode>();
333:                 r.addAll(TC.result);
334:
335:                 return r;
336:         }
337:
338:         private static List<INode> parseTcPpContent(List<File> content,
339:                         String testName, boolean retry)
340:         {
341:                 Settings.dialect = Dialect.VDM_PP;
342:
343:                 TypeCheckResult<List<SClassDefinition>> TC = TypeCheckerUtil.typeCheckPp(content, UTF8);
344:
345:                 // retry with other dialect
346:•                if (retry
347:•                                && (!TC.parserResult.errors.isEmpty() || !TC.errors.isEmpty()))
348:                 {
349:•                        if (Settings.release == Release.CLASSIC)
350:                         {
351:                                 Settings.release = Release.VDM_10;
352:                                 return parseTcPpContent(content, testName, false);
353:                         }
354:•                        if (Settings.release == Release.VDM_10)
355:                         {
356:                                 Settings.release = Release.CLASSIC;
357:                                 return parseTcPpContent(content, testName, false);
358:                         }
359:                 }
360:
361:                 checkTcResult(TC);
362:
363:                 List<INode> r = new LinkedList<INode>();
364:                 r.addAll(TC.result);
365:
366:                 return r;
367:         }
368:
369:         private static List<INode> parseTcSlContent(List<File> content,
370:                         String testName, boolean retry)
371:         {
372:                 Settings.dialect = Dialect.VDM_SL;
373:
374:                 TypeCheckResult<List<AModuleModules>> TC = TypeCheckerUtil.typeCheckSl(content, UTF8);
375:
376:                 // retry with other dialect
377:•                if (retry
378:•                                && (!TC.parserResult.errors.isEmpty() || !TC.errors.isEmpty()))
379:                 {
380:•                        if (Settings.release == Release.CLASSIC)
381:                         {
382:                                 Settings.release = Release.VDM_10;
383:                                 return parseTcSlContent(content, testName, false);
384:                         }
385:•                        if (Settings.release == Release.VDM_10)
386:                         {
387:                                 Settings.release = Release.CLASSIC;
388:                                 return parseTcSlContent(content, testName, false);
389:                         }
390:                 }
391:
392:                 checkTcResult(TC);
393:
394:                 List<INode> r = new LinkedList<INode>();
395:                 r.addAll(TC.result);
396:
397:                 return r;
398:         }
399:
400:         protected static void checkTcResult(
401:                         @SuppressWarnings("rawtypes") TypeCheckResult TC)
402:         {
403:                 assertTrue("Parse Error:\n" + TC.parserResult.getErrorString(), TC.parserResult.errors.isEmpty());
404:                 assertTrue("Type Check Error:\n" + TC.getErrorString(), TC.errors.isEmpty());
405:         }
406:
407: }