/*******************************************************************************
*
* Copyright (c) 2008 Fujitsu Services Ltd.
*
* Author: Nick Battle
*
* This file is part of VDMJ.
*
* VDMJ is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VDMJ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with VDMJ. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
package org.overture.parser.syntax;
import java.util.List;
import java.util.Vector;
import org.overture.ast.definitions.AAssignmentDefinition;
import org.overture.ast.definitions.PDefinition;
import org.overture.ast.expressions.PExp;
import org.overture.ast.factory.AstFactory;
import org.overture.ast.intf.lex.ILexLocation;
import org.overture.ast.lex.Dialect;
import org.overture.ast.lex.LexIdentifierToken;
import org.overture.ast.lex.LexNameToken;
import org.overture.ast.lex.LexToken;
import org.overture.ast.lex.VDMToken;
import org.overture.ast.patterns.ADefPatternBind;
import org.overture.ast.patterns.PMultipleBind;
import org.overture.ast.patterns.PPattern;
import org.overture.ast.statements.AApplyObjectDesignator;
import org.overture.ast.statements.AAssignmentStm;
import org.overture.ast.statements.ABlockSimpleBlockStm;
import org.overture.ast.statements.ACaseAlternativeStm;
import org.overture.ast.statements.ACasesStm;
import org.overture.ast.statements.AElseIfStm;
import org.overture.ast.statements.AFieldObjectDesignator;
import org.overture.ast.statements.AIdentifierObjectDesignator;
import org.overture.ast.statements.ALetBeStStm;
import org.overture.ast.statements.ALetStm;
import org.overture.ast.statements.ANonDeterministicSimpleBlockStm;
import org.overture.ast.statements.ASpecificationStm;
import org.overture.ast.statements.ATixeStmtAlternative;
import org.overture.ast.statements.PObjectDesignator;
import org.overture.ast.statements.PStateDesignator;
import org.overture.ast.statements.PStm;
import org.overture.ast.typechecker.NameScope;
import org.overture.ast.types.PType;
import org.overture.config.Release;
import org.overture.config.Settings;
import org.overture.parser.lex.LexException;
import org.overture.parser.lex.LexTokenReader;
/**
* A syntax analyser to parse statements.
*/
public class StatementReader extends SyntaxReader
{
public StatementReader(LexTokenReader reader)
{
super(reader);
}
public PStm readStatement() throws ParserException, LexException
{
PStm stmt = null;
LexToken token = lastToken();
ILexLocation location = token.location;
switch (token.type)
{
case LET:
stmt = readLetStatement(token);
break;
case RETURN:
stmt = readReturnStatement(location);
break;
case BRA:
stmt = readBlockStatement(location);
break;
case NAME:
case IDENTIFIER:
case NEW:
case SELF:
stmt = readAssignmentOrCallStatement(token);
break;
case IF:
nextToken(); // to allow elseif to call it too
stmt = readConditionalStatement(location);
break;
case CASES:
stmt = readCasesStatement(location);
break;
case FOR:
stmt = readForStatement(location);
break;
case WHILE:
stmt = readWhileStatement(location);
break;
case PIPEPIPE:
stmt = readNonDetStatement(location);
break;
case ALWAYS:
stmt = readAlwaysStatement(location);
break;
case ATOMIC:
stmt = readAtomicStatement(location);
break;
case TRAP:
stmt = readTrapStatement(location);
break;
case TIXE:
stmt = readTixeStatement(location);
break;
case DEF:
stmt = readDefStatement(location);
break;
case EXIT:
stmt = readExitStatement(location);
break;
case SEQ_OPEN:
stmt = readSpecStatement(location);
break;
case ERROR:
stmt = AstFactory.newAErrorStm(location);
nextToken();
break;
case SKIP:
stmt = AstFactory.newASkipStm(location);
nextToken();
break;
case START:
stmt = readStartStatement(location);
break;
case STARTLIST:
stmt = readStartlistStatement(location);
break;
case STOP:
if (Settings.release == Release.CLASSIC)
{
throwMessage(2304, "'stop' not available in VDM classic");
}
stmt = readStopStatement(location);
break;
case STOPLIST:
if (Settings.release == Release.CLASSIC)
{
throwMessage(2305, "'stoplist' not available in VDM classic");
}
stmt = readStoplistStatement(location);
break;
case CYCLES:
stmt = readCyclesStatement(location);
break;
case DURATION:
stmt = readDurationStatement(location);
break;
default:
throwMessage(2063, "Unexpected token in statement");
}
return stmt;
}
private PStm readExitStatement(ILexLocation token) throws ParserException,
LexException
{
checkFor(VDMToken.EXIT, 2190, "Expecting 'exit'");
try
{
reader.push();
PExp exp = getExpressionReader().readExpression();
reader.unpush();
return AstFactory.newAExitStm(token, exp);
} catch (ParserException e)
{
reader.pop();
}
return AstFactory.newAExitStm(token);
}
private PStm readTixeStatement(ILexLocation token) throws ParserException,
LexException
{
checkFor(VDMToken.TIXE, 2191, "Expecting 'tixe'");
List<ATixeStmtAlternative> traps = new Vector<ATixeStmtAlternative>();
BindReader br = getBindReader();
checkFor(VDMToken.SET_OPEN, 2192, "Expecting '{' after 'tixe'");
while (lastToken().isNot(VDMToken.SET_CLOSE))
{
ADefPatternBind patternBind = br.readPatternOrBind();
checkFor(VDMToken.MAPLET, 2193, "Expecting '|->' after pattern bind");
PStm result = readStatement();
traps.add(AstFactory.newATixeStmtAlternative(patternBind, result));
ignore(VDMToken.COMMA);
}
nextToken();
checkFor(VDMToken.IN, 2194, "Expecting 'in' after tixe traps");
PStm body = getStatementReader().readStatement();
return AstFactory.newATixeStm(token, traps, body);
}
private PStm readTrapStatement(ILexLocation token) throws ParserException,
LexException
{
checkFor(VDMToken.TRAP, 2195, "Expecting 'trap'");
ADefPatternBind patternBind = getBindReader().readPatternOrBind();
checkFor(VDMToken.WITH, 2196, "Expecting 'with' in trap statement");
PStm with = getStatementReader().readStatement();
checkFor(VDMToken.IN, 2197, "Expecting 'in' in trap statement");
PStm body = getStatementReader().readStatement();
return AstFactory.newATrapStm(token, patternBind, with, body);
}
private PStm readAlwaysStatement(ILexLocation token)
throws ParserException, LexException
{
checkFor(VDMToken.ALWAYS, 2198, "Expecting 'always'");
PStm always = getStatementReader().readStatement();
checkFor(VDMToken.IN, 2199, "Expecting 'in' after 'always' statement");
PStm body = getStatementReader().readStatement();
return AstFactory.newAAlwaysStm(token, always, body);
}
private PStm readNonDetStatement(ILexLocation token)
throws ParserException, LexException
{
checkFor(VDMToken.PIPEPIPE, 2200, "Expecting '||'");
checkFor(VDMToken.BRA, 2201, "Expecting '(' after '||'");
ANonDeterministicSimpleBlockStm block = AstFactory.newANonDeterministicSimpleBlockStm(token);
block.getStatements().add(readStatement()); // Must be one
while (ignore(VDMToken.COMMA))
{
block.getStatements().add(readStatement());
}
checkFor(VDMToken.KET, 2202, "Expecting ')' at end of '||' block");
return block;
}
private PStm readAssignmentOrCallStatement(LexToken token)
throws ParserException, LexException
{
ParserException assignError = null;
PStm stmt = null;
try
{
reader.push();
stmt = readAssignmentStatement(token.location);
reader.unpush();
return stmt;
} catch (ParserException e)
{
e.adjustDepth(reader.getTokensRead());
reader.pop();
assignError = e;
}
try
{
reader.push();
stmt = readCallStatement();
reader.unpush();
return stmt;
} catch (ParserException e)
{
e.adjustDepth(reader.getTokensRead());
reader.pop();
throw e.deeperThan(assignError) ? e : assignError;
}
}
private PStm readAtomicStatement(ILexLocation token)
throws ParserException, LexException
{
checkFor(VDMToken.ATOMIC, 2203, "Expecting 'atomic'");
checkFor(VDMToken.BRA, 2204, "Expecting '(' after 'atomic'");
List<AAssignmentStm> assignments = new Vector<AAssignmentStm>();
assignments.add(readAssignmentStatement(lastToken().location));
ignore(VDMToken.SEMICOLON); // Every statement has an ignorable semicolon
while (lastToken().isNot(VDMToken.KET))
{
assignments.add(readAssignmentStatement(lastToken().location));
ignore(VDMToken.SEMICOLON);
}
checkFor(VDMToken.KET, 2205, "Expecting ')' after atomic assignments");
return AstFactory.newAAtomicStm(token, assignments);
}
public PStm readCallStatement() throws ParserException, LexException
{
if (dialect != Dialect.VDM_SL)
{
return readObjectCallStatement();
} else
{
return readSimpleCallStatement();
}
}
private PStm readSimpleCallStatement() throws ParserException, LexException
{
LexNameToken name = readNameToken("Expecting operation name in call statement");
checkFor(VDMToken.BRA, 2206, "Expecting '(' after call operation name");
List<PExp> args = new Vector<PExp>();
ExpressionReader er = getExpressionReader();
if (lastToken().isNot(VDMToken.KET))
{
args.add(er.readExpression());
while (ignore(VDMToken.COMMA))
{
args.add(er.readExpression());
}
}
checkFor(VDMToken.KET, 2124, "Expecting ')' after args");
return AstFactory.newACallStm(name, args);
}
private PStm readObjectCallStatement() throws ParserException, LexException
{
PObjectDesignator designator = readObjectDesignator();
// All operation calls actually look like object apply designators,
// since they end with <name>([args]). So we unpick the apply
// designator to extract the operation name and args.
if (!(designator instanceof AApplyObjectDesignator))
{
throwMessage(2064, "Expecting <object>.identifier(args) or name(args)");
}
AApplyObjectDesignator oad = (AApplyObjectDesignator) designator;
List<PExp> args = oad.getArgs();
if (oad.getObject() instanceof AFieldObjectDesignator)
{
AFieldObjectDesignator ofd = (AFieldObjectDesignator) oad.getObject();
if (ofd.getClassName() != null)
{
return AstFactory.newACallObjectStm(ofd.getObject(), ofd.getClassName(), args);
} else
{
return AstFactory.newACallObjectStm(ofd.getObject(), (LexIdentifierToken) ofd.getFieldName().clone(), args);
}
} else if (oad.getObject() instanceof AIdentifierObjectDesignator)
{
AIdentifierObjectDesignator oid = (AIdentifierObjectDesignator) oad.getObject();
return AstFactory.newACallStm(oid.getName(), args);
} else
{
throwMessage(2065, "Expecting <object>.name(args) or name(args)");
return null;
}
}
private PObjectDesignator readObjectDesignator() throws ParserException,
LexException
{
PObjectDesignator des = readSimpleObjectDesignator();
boolean done = false;
while (!done)
{
switch (lastToken().type)
{
case POINT:
LexToken field = nextToken();
// If we just read a qualified name, we're dealing with
// something like new A().X`op(), else it's the more usual
// new A().op().
switch (field.type)
{
case IDENTIFIER:
des = AstFactory.newAFieldObjectDesignator(des, (LexIdentifierToken) field);
break;
case NAME:
des = AstFactory.newAFieldObjectDesignator(des, (LexNameToken) field);
break;
default:
throwMessage(2066, "Expecting object field name");
}
nextToken();
break;
case BRA:
nextToken();
ExpressionReader er = getExpressionReader();
List<PExp> args = new Vector<PExp>();
if (lastToken().isNot(VDMToken.KET))
{
args.add(er.readExpression());
while (ignore(VDMToken.COMMA))
{
args.add(er.readExpression());
}
}
checkFor(VDMToken.KET, 2124, "Expecting ')' after args");
des = AstFactory.newAApplyObjectDesignator(des, args);
break;
default:
done = true;
break;
}
}
return des;
}
private PObjectDesignator readSimpleObjectDesignator() throws LexException,
ParserException
{
LexToken token = readToken();
switch (token.type)
{
case SELF:
return AstFactory.newASelfObjectDesignator(token.location);
case IDENTIFIER:
{
return AstFactory.newAIdentifierObjectDesignator(idToName((LexIdentifierToken) token));
}
case NAME:
{
return AstFactory.newAIdentifierObjectDesignator((LexNameToken) token);
}
case NEW:
LexIdentifierToken name = readIdToken("Expecting class name after 'new'");
checkFor(VDMToken.BRA, 2207, "Expecting '(' after new class name");
List<PExp> args = new Vector<PExp>();
ExpressionReader er = getExpressionReader();
if (lastToken().isNot(VDMToken.KET))
{
args.add(er.readExpression());
while (ignore(VDMToken.COMMA))
{
args.add(er.readExpression());
}
}
checkFor(VDMToken.KET, 2124, "Expecting ')' after constructor args");
return AstFactory.newANewObjectDesignator(name, args);
default:
throwMessage(2067, "Expecting 'self', 'new' or name in object designator");
break;
}
return null;
}
private PStm readWhileStatement(ILexLocation token) throws ParserException,
LexException
{
checkFor(VDMToken.WHILE, 2208, "Expecting 'while'");
PExp exp = getExpressionReader().readExpression();
checkFor(VDMToken.DO, 2209, "Expecting 'do' after while expression");
PStm body = getStatementReader().readStatement();
return AstFactory.newAWhileStm(token, exp, body);
}
private PStm readForStatement(ILexLocation token) throws ParserException,
LexException
{
checkFor(VDMToken.FOR, 2210, "Expecting 'for'");
PStm forstmt = null;
if (lastToken().is(VDMToken.ALL))
{
nextToken();
PPattern p = getPatternReader().readPattern();
checkFor(VDMToken.IN, 2211, "Expecting 'in set' after 'for all'");
checkFor(VDMToken.SET, 2212, "Expecting 'in set' after 'for all'");
PExp set = getExpressionReader().readExpression();
checkFor(VDMToken.DO, 2213, "Expecting 'do' after for all expression");
PStm body = getStatementReader().readStatement();
return AstFactory.newAForAllStm(token, p, set, body);
} else
{
ParserException forIndexError = null;
try
{
reader.push();
forstmt = readForIndexStatement(token);
reader.unpush();
return forstmt;
} catch (ParserException e)
{
e.adjustDepth(reader.getTokensRead());
reader.pop();
forIndexError = e;
}
try
{
reader.push();
forstmt = readForPatternBindStatement(token);
reader.unpush();
return forstmt;
} catch (ParserException e)
{
e.adjustDepth(reader.getTokensRead());
reader.pop();
throw e.deeperThan(forIndexError) ? e : forIndexError;
}
}
}
private PStm readForPatternBindStatement(ILexLocation token)
throws ParserException, LexException
{
ADefPatternBind pb = getBindReader().readPatternOrBind();
checkFor(VDMToken.IN, 2214, "Expecting 'in' after pattern bind");
// The old syntax used to include a "reverse" keyword as part
// of the loop grammar, whereas the new VDM-10 syntax (LB:2791065)
// makes the reverse a unary sequence operator.
if (Settings.release == Release.VDM_10)
{
PExp exp = getExpressionReader().readExpression();
checkFor(VDMToken.DO, 2215, "Expecting 'do' before loop statement");
PStm body = getStatementReader().readStatement();
return AstFactory.newAForPatternBindStm(token, pb, false, exp, body);
} else
{
boolean reverse = ignore(VDMToken.REVERSE);
PExp exp = getExpressionReader().readExpression();
checkFor(VDMToken.DO, 2215, "Expecting 'do' before loop statement");
PStm body = getStatementReader().readStatement();
return AstFactory.newAForPatternBindStm(token, pb, reverse, exp, body);
}
}
private PStm readForIndexStatement(ILexLocation token)
throws ParserException, LexException
{
LexIdentifierToken var = readIdToken("Expecting variable identifier");
checkFor(VDMToken.EQUALS, 2216, "Expecting '=' after for variable");
PExp from = getExpressionReader().readExpression();
checkFor(VDMToken.TO, 2217, "Expecting 'to' after from expression");
PExp to = getExpressionReader().readExpression();
PExp by = null;
if (lastToken().is(VDMToken.BY))
{
nextToken();
by = getExpressionReader().readExpression();
}
checkFor(VDMToken.DO, 2218, "Expecting 'do' before loop statement");
PStm body = getStatementReader().readStatement();
return AstFactory.newAForIndexStm(token, idToName(var), from, to, by, body);
}
private PStm readConditionalStatement(ILexLocation token)
throws ParserException, LexException
{
PExp exp = getExpressionReader().readExpression();
checkFor(VDMToken.THEN, 2219, "Missing 'then'");
PStm thenStmt = readStatement();
List<AElseIfStm> elseIfList = new Vector<AElseIfStm>();
while (lastToken().is(VDMToken.ELSEIF))
{
LexToken elseif = lastToken();
nextToken();
elseIfList.add(readElseIfStatement(elseif.location));
}
PStm elseStmt = null;
if (lastToken().is(VDMToken.ELSE))
{
nextToken();
elseStmt = readStatement();
}
return AstFactory.newAIfStm(token, exp, thenStmt, elseIfList, elseStmt);
}
private AElseIfStm readElseIfStatement(ILexLocation token)
throws ParserException, LexException
{
PExp exp = getExpressionReader().readExpression();
checkFor(VDMToken.THEN, 2220, "Missing 'then' after 'elseif' expression");
PStm thenStmt = readStatement();
return AstFactory.newAElseIfStm(token, exp, thenStmt);
}
private AAssignmentStm readAssignmentStatement(ILexLocation token)
throws ParserException, LexException
{
PStateDesignator sd = readStateDesignator();
checkFor(VDMToken.ASSIGN, 2222, "Expecting ':=' in state assignment statement");
return AstFactory.newAAssignmentStm(token, sd, getExpressionReader().readExpression());
}
private PStateDesignator readStateDesignator() throws ParserException,
LexException
{
LexNameToken name = readNameToken("Expecting name in assignment statement");
PStateDesignator sd = AstFactory.newAIdentifierStateDesignator(name);
while (lastToken().is(VDMToken.POINT) || lastToken().is(VDMToken.BRA))
{
if (lastToken().is(VDMToken.POINT))
{
if (nextToken().isNot(VDMToken.IDENTIFIER))
{
throwMessage(2068, "Expecting field identifier");
}
sd = AstFactory.newAFieldStateDesignator(sd, lastIdToken());
nextToken();
} else
{
nextToken();
PExp exp = getExpressionReader().readExpression();
checkFor(VDMToken.KET, 2223, "Expecting ')' after map/seq reference");
sd = AstFactory.newAMapSeqStateDesignator(sd, exp);
}
}
return sd;
}
public PStm readBlockStatement(ILexLocation token) throws ParserException,
LexException
{
LexToken start = lastToken();
checkFor(VDMToken.BRA, 2224, "Expecting statement block");
ABlockSimpleBlockStm block = AstFactory.newABlockSimpleBlockStm(token, readDclStatements());
boolean problems = false;
while (true) // Loop for continue in exceptions
{
try
{
while (!lastToken().is(VDMToken.KET))
{
block.getStatements().add(readStatement());
if (lastToken().isNot(VDMToken.KET)
&& lastToken().isNot(VDMToken.SEMICOLON))
{
throwMessage(2225, "Expecting ';' after statement");
}
ignore(VDMToken.SEMICOLON);
}
break;
} catch (ParserException e)
{
problems = true;
if (lastToken().is(VDMToken.EOF))
{
break;
}
VDMToken[] after = { VDMToken.SEMICOLON };
VDMToken[] upto = { VDMToken.KET };
report(e, after, upto);
continue;
}
}
checkFor(VDMToken.KET, 2226, "Expecting ')' at end of statement block");
if (!problems && block.getStatements().isEmpty())
{
throwMessage(2296, "Block cannot be empty", start);
}
return block;
}
private List<AAssignmentDefinition> readDclStatements()
throws ParserException, LexException
{
List<AAssignmentDefinition> defs = new Vector<AAssignmentDefinition>();
while (lastToken().is(VDMToken.DCL))
{
nextToken();
defs.add(readAssignmentDefinition());
while (ignore(VDMToken.COMMA))
{
defs.add(readAssignmentDefinition());
}
checkFor(VDMToken.SEMICOLON, 2227, "Expecting ';' after declarations");
}
return defs;
}
public AAssignmentDefinition readAssignmentDefinition()
throws ParserException, LexException
{
LexIdentifierToken name = readIdToken("Expecting variable identifier");
checkFor(VDMToken.COLON, 2228, "Expecting name:type in declaration");
PType type = getTypeReader().readType();
PExp exp = null;
if (lastToken().is(VDMToken.ASSIGN))
{
nextToken();
exp = getExpressionReader().readExpression();
} else if (lastToken().is(VDMToken.EQUALSEQUALS)
|| lastToken().is(VDMToken.EQUALS))
{
throwMessage(2069, "Expecting <identifier>:<type> := <expression>");
} else
{
exp = AstFactory.newAUndefinedExp(name.location);
}
return AstFactory.newAAssignmentDefinition(idToName(name), type, exp);
}
private PStm readReturnStatement(ILexLocation token)
throws ParserException, LexException
{
checkFor(VDMToken.RETURN, 2229, "Expecting 'return'");
try
{
reader.push();
PExp exp = getExpressionReader().readExpression();
reader.unpush();
return AstFactory.newAReturnStm(token, exp);
} catch (ParserException e)
{
int count = reader.getTokensRead();
e.adjustDepth(count);
reader.pop();
if (count > 2)
{
// We got some way, so error is probably in exp
throw e;
} else
{
// Probably just a simple return
return AstFactory.newAReturnStm(token);
}
}
}
private PStm readLetStatement(LexToken token) throws ParserException,
LexException
{
checkFor(VDMToken.LET, 2230, "Expecting 'let'");
ParserException letDefError = null;
try
{
reader.push();
ALetStm stmt = readLetDefStatement(token.location);
reader.unpush();
return stmt;
} catch (ParserException e)
{
e.adjustDepth(reader.getTokensRead());
reader.pop();
letDefError = e;
}
try
{
reader.push();
ALetBeStStm stmt = readLetBeStStatement(token.location);
reader.unpush();
return stmt;
} catch (ParserException e)
{
e.adjustDepth(reader.getTokensRead());
reader.pop();
throw e.deeperThan(letDefError) ? e : letDefError;
}
}
private ALetStm readLetDefStatement(ILexLocation token)
throws ParserException, LexException
{
DefinitionReader dr = getDefinitionReader();
List<PDefinition> localDefs = new Vector<PDefinition>();
localDefs.add(dr.readLocalDefinition(NameScope.LOCAL));
while (ignore(VDMToken.COMMA))
{
localDefs.add(dr.readLocalDefinition(NameScope.LOCAL));
}
checkFor(VDMToken.IN, 2231, "Expecting 'in' after local definitions");
return AstFactory.newALetStm(token, localDefs, readStatement());
}
private ALetBeStStm readLetBeStStatement(ILexLocation token)
throws ParserException, LexException
{
PMultipleBind bind = getBindReader().readMultipleBind();
PExp stexp = null;
if (lastToken().is(VDMToken.BE))
{
nextToken();
checkFor(VDMToken.ST, 2232, "Expecting 'st' after 'be' in let statement");
stexp = getExpressionReader().readExpression();
}
checkFor(VDMToken.IN, 2233, "Expecting 'in' after bind in let statement");
return AstFactory.newALetBeStStm(token, bind, stexp, readStatement());
}
private ACasesStm readCasesStatement(ILexLocation token)
throws ParserException, LexException
{
checkFor(VDMToken.CASES, 2234, "Expecting 'cases'");
PExp exp = getExpressionReader().readExpression();
checkFor(VDMToken.COLON, 2235, "Expecting ':' after cases expression");
List<ACaseAlternativeStm> cases = new Vector<ACaseAlternativeStm>();
PStm others = null;
cases.addAll(readCaseAlternatives());
while (lastToken().is(VDMToken.COMMA))
{
if (nextToken().is(VDMToken.OTHERS))
{
nextToken();
checkFor(VDMToken.ARROW, 2237, "Expecting '->' after others");
others = readStatement();
break;
} else
{
cases.addAll(readCaseAlternatives());
}
}
checkFor(VDMToken.END, 2238, "Expecting ', case alternative' or 'end' after cases");
return AstFactory.newACasesStm(token, exp, cases, others);
}
private List<ACaseAlternativeStm> readCaseAlternatives()
throws ParserException, LexException
{
List<ACaseAlternativeStm> alts = new Vector<ACaseAlternativeStm>();
List<PPattern> plist = getPatternReader().readPatternList();
checkFor(VDMToken.ARROW, 2236, "Expecting '->' after case pattern list");
PStm result = readStatement();
for (PPattern p : plist)
{
p.getLocation().executable(true);
alts.add(AstFactory.newACaseAlternativeStm(p.clone(), result.clone()));
}
return alts;
}
private ALetStm readDefStatement(ILexLocation token)
throws ParserException, LexException
{
checkFor(VDMToken.DEF, 2239, "Expecting 'def'");
DefinitionReader dr = getDefinitionReader();
List<PDefinition> equalsDefs = new Vector<PDefinition>();
while (lastToken().isNot(VDMToken.IN))
{
equalsDefs.add(dr.readEqualsDefinition());
ignore(VDMToken.SEMICOLON);
}
checkFor(VDMToken.IN, 2240, "Expecting 'in' after equals definitions");
return AstFactory.newALetStm(token, equalsDefs, readStatement());
}
private ASpecificationStm readSpecStatement(ILexLocation token)
throws ParserException, LexException
{
checkFor(VDMToken.SEQ_OPEN, 2241, "Expecting '['");
DefinitionReader dr = getDefinitionReader();
ASpecificationStm stmt = dr.readSpecification(token, false);
checkFor(VDMToken.SEQ_CLOSE, 2242, "Expecting ']' after specification statement");
return stmt;
}
private PStm readStartStatement(ILexLocation location) throws LexException,
ParserException
{
checkFor(VDMToken.START, 2243, "Expecting 'start'");
checkFor(VDMToken.BRA, 2244, "Expecting 'start('");
PExp obj = getExpressionReader().readExpression();
checkFor(VDMToken.KET, 2245, "Expecting ')' after start object");
return AstFactory.newAStartStm(location, obj);
}
private PStm readStartlistStatement(ILexLocation location)
throws LexException, ParserException
{
checkFor(VDMToken.STARTLIST, 2246, "Expecting 'startlist'");
checkFor(VDMToken.BRA, 2247, "Expecting 'startlist('");
PExp set = getExpressionReader().readExpression();
checkFor(VDMToken.KET, 2248, "Expecting ')' after startlist objects");
return AstFactory.newAStartStm(location, set);
}
private PStm readStopStatement(ILexLocation location) throws LexException,
ParserException
{
checkFor(VDMToken.STOP, 2306, "Expecting 'stop'");
checkFor(VDMToken.BRA, 2307, "Expecting 'stop('");
PExp obj = getExpressionReader().readExpression();
checkFor(VDMToken.KET, 2308, "Expecting ')' after stop object");
return AstFactory.newAStopStm(location, obj);
}
private PStm readStoplistStatement(ILexLocation location)
throws LexException, ParserException
{
checkFor(VDMToken.STOPLIST, 2309, "Expecting 'stoplist'");
checkFor(VDMToken.BRA, 2310, "Expecting 'stoplist('");
PExp set = getExpressionReader().readExpression();
checkFor(VDMToken.KET, 2311, "Expecting ')' after stoplist objects");
return AstFactory.newAStopStm(location, set);
}
private PStm readDurationStatement(ILexLocation location)
throws LexException, ParserException
{
checkFor(VDMToken.DURATION, 2271, "Expecting 'duration'");
checkFor(VDMToken.BRA, 2272, "Expecting 'duration('");
PExp duration = getExpressionReader().readExpression();
checkFor(VDMToken.KET, 2273, "Expecting ')' after duration");
PStm stmt = readStatement();
return AstFactory.newADurationStm(location, duration, stmt);
}
private PStm readCyclesStatement(ILexLocation location)
throws LexException, ParserException
{
checkFor(VDMToken.CYCLES, 2274, "Expecting 'cycles'");
checkFor(VDMToken.BRA, 2275, "Expecting 'cycles('");
PExp duration = getExpressionReader().readExpression();
checkFor(VDMToken.KET, 2276, "Expecting ')' after cycles");
PStm stmt = readStatement();
return AstFactory.newACyclesStm(location, duration, stmt);
}
}