/*******************************************************************************
*
* 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.factory.AstFactory;
import org.overture.ast.lex.VDMToken;
import org.overture.ast.patterns.ADefPatternBind;
import org.overture.ast.patterns.ATypeBind;
import org.overture.ast.patterns.PBind;
import org.overture.ast.patterns.PMultipleBind;
import org.overture.ast.patterns.PPattern;
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 set and type binds.
*/
public class BindReader extends SyntaxReader
{
public BindReader(LexTokenReader reader)
{
super(reader);
}
public ADefPatternBind readPatternOrBind() throws ParserException,
LexException
{
ParserException bindError = null;
try
{
reader.push();
PBind bind = readBind();
reader.unpush();
return AstFactory.newADefPatternBind(bind.getLocation(), bind);
} catch (ParserException e)
{
e.adjustDepth(reader.getTokensRead());
reader.pop();
bindError = e;
}
try
{
reader.push();
PPattern p = getPatternReader().readPattern();
reader.unpush();
return AstFactory.newADefPatternBind(p.getLocation(), p);
} catch (ParserException e)
{
e.adjustDepth(reader.getTokensRead());
reader.pop();
throw e.deeperThan(bindError) ? e : bindError;
}
}
public PBind readBind() throws ParserException, LexException
{
ParserException setBindError = null;
try
{
reader.push();
PBind bind = readSetSeqBind();
reader.unpush();
return bind;
} catch (ParserException e)
{
e.adjustDepth(reader.getTokensRead());
reader.pop();
setBindError = e;
}
try
{
reader.push();
PBind bind = readTypeBind();
reader.unpush();
return bind;
} catch (ParserException e)
{
e.adjustDepth(reader.getTokensRead());
reader.pop();
throw e.deeperThan(setBindError) ? e : setBindError;
}
}
public PBind readSetSeqBind() throws LexException, ParserException
{
PPattern pattern = getPatternReader().readPattern();
PBind sb = null;
if (lastToken().is(VDMToken.IN))
{
switch (nextToken().type)
{
case SET:
nextToken();
sb = AstFactory.newASetBind(pattern, getExpressionReader().readExpression());
break;
case SEQ:
if (Settings.release == Release.CLASSIC)
{
throwMessage(2328, "Sequence binds are not available in classic");
}
nextToken();
sb = AstFactory.newASeqBind(pattern, getExpressionReader().readExpression());
break;
default:
throwMessage(2000, "Expecting 'in set' or 'in seq' after pattern in binding");
}
}
else
{
throwMessage(2001, "Expecting 'in set' or 'in seq' in bind");
}
return sb;
}
public ATypeBind readTypeBind() throws LexException, ParserException
{
PPattern pattern = getPatternReader().readPattern();
ATypeBind tb = null;
if (lastToken().is(VDMToken.COLON))
{
nextToken();
tb = AstFactory.newATypeBind(pattern, getTypeReader().readType());
} else
{
throwMessage(2002, "Expecting ':' in type bind");
}
return tb;
}
public List<ATypeBind> readTypeBindList() throws ParserException,
LexException
{
List<ATypeBind> list = new Vector<ATypeBind>();
list.add(readTypeBind());
while (ignore(VDMToken.COMMA))
{
list.add(readTypeBind());
}
return list;
}
public PMultipleBind readMultipleBind() throws LexException,
ParserException
{
List<PPattern> plist = getPatternReader().readPatternList();
PMultipleBind mb = null;
switch (lastToken().type)
{
case IN:
switch (nextToken().type)
{
case SET:
nextToken();
mb = AstFactory.newASetMultipleBind(plist, getExpressionReader().readExpression());
break;
case SEQ:
if (Settings.release == Release.CLASSIC)
{
throwMessage(2328, "Sequence binds are not available in classic");
}
nextToken();
mb = AstFactory.newASeqMultipleBind(plist, getExpressionReader().readExpression());
break;
default:
throwMessage(2003, "Expecting 'in set' or 'in seq' after pattern in binding");
}
break;
case COLON:
nextToken();
mb = AstFactory.newATypeMultipleBind(plist, getTypeReader().readType());
break;
default:
throwMessage(2004, "Expecting 'in set', 'in seq' or ':' after patterns");
}
return mb;
}
public List<PMultipleBind> readBindList() throws ParserException,
LexException
{
List<PMultipleBind> list = new Vector<PMultipleBind>();
list.add(readMultipleBind());
while (ignore(VDMToken.COMMA))
{
list.add(readMultipleBind());
}
return list;
}
}