/*
This file is part of JLoom
Copyright (C) 2006 Gereon Fassbender
Homepage: jloom.sourceforge.net
JLoom 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 2 of the License, or (at your option) any later version.
This program 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 can find a copy of the GNU General Public License along with this program
in a file called COPYING. Information can also be found at www.fsf.org or
www.gnu.org or write to the Free Software Foundation, Inc., 51 Franklin Street,
Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
created: 27.12.2005 Gereon Fassbender
$Revision$
$Date$
$Log$
*/
package net.gereon.jloom.translation.core;
import java.util.*;
import java.util.regex.Matcher;
import net.gereon.jloom.problems.SyntaxProblem;
import net.gereon.jloom.util.Log;
public class ParsableToken extends AbstractToken
{
//private Readable source;
//private CharBuffer buffer;
private int position;
public ParsableToken(Token parent, String text, int start, ParsePattern pattern)
{
super(parent, text, start, pattern);
}
/*private boolean addNextChar(StringBuilder s) throws IOException
// todo buffern
{
CharBuffer b = CharBuffer.allocate(1);
int l = source.read(b);
if (l == 1) {
s.append(b);
return true;
}
else {
assert l == -1;
return false;
}
}*/
public Token parseToken(boolean allowEmpty, ParsePattern... tokenPatterns) //throws ParseException
{
CharSequence s = getUnparsedText();
for (ParsePattern pattern: tokenPatterns) {
Matcher m = pattern.getPattern().matcher(s);
//System.out.println(s);
if (m.lookingAt()) {
int p = position; // TODO p wegrefactorn
String match = m.group(); // korrekt?
if (pattern.isIgnoreLastGroup()) {
assert m.groupCount() > 0;
String g = m.group(m.groupCount());
assert g != null;
assert match.endsWith(g);
match = match.substring(0, match.length() - g.length());
}
position += match.length();
Token t = new ParsableToken(this, match, p, pattern);
addSubToken(t);
if (!allowEmpty && match.length() < 1) {
handleParseProblem(tokenPatterns);
//throw new ParseException("Unallowed empty token", pattern.getPattern().toString(), s.toString());
}
return t;
}
}
handleParseProblem(tokenPatterns);
return null;
/*
StringBuilder p = new StringBuilder();
for (ParsePattern pattern: tokenPatterns) {
p.append("{" + pattern.getPattern().pattern() + "}");
}
throw new ParseException("parse fehler", p.toString(), s.toString());
*/
}
public boolean isParseEnd()
{
if (position < getLength()) {
return false;
}
assert position == getLength();
return true;
}
public CharSequence getUnparsedText()
{
return new SubSequence(getText(), position, getLength());
}
public int getParsePosition()
{
return position;
}
private String getPatternText(ParsePattern... patterns)
{
StringBuilder sb = new StringBuilder();
Map<String, String> namesMap = new HashMap<String, String>();
List<String> names = new ArrayList<String>();
for (ParsePattern p : patterns) {
if (namesMap.get(p.getName()) == null) {
names.add(p.getName());
namesMap.put(p.getName(), "");
}
}
for (int i=0; i<names.size(); i++) {
sb.append(names.get(i));
if (i < names.size() - 1) {
if (i < names.size() - 2) { sb.append(", "); }
else { sb.append(", or "); }
}
}
return sb.toString();
}
private void handleParseProblem(ParsePattern... patterns)
{
String msg = "Expected " + getPatternText(patterns) + ".";
int pos = getStartPosAbsolute() + position;
addProblem(new SyntaxProblem(msg, pos, getLength() - position));
position = getLength();
}
public char readNextChar()
{
assert !isParseEnd();
return getText().charAt(position++);
}
public void rewind(int length)
{
assert position >= length;
position -= length;
}
public String toString()
{
return toString(true);
}
}