/*******************************************************************************
* Copyright (c) 2012 BMW Car IT and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.jnario.feature.parser;
import static org.jnario.feature.parser.antlr.internal.InternalFeatureLexer.RULE_BACKGROUND_TEXT;
import static org.jnario.feature.parser.antlr.internal.InternalFeatureLexer.RULE_FEATURE_TEXT;
import static org.jnario.feature.parser.antlr.internal.InternalFeatureLexer.RULE_SCENARIO_TEXT;
import static org.jnario.feature.parser.antlr.internal.InternalFeatureLexer.RULE_TEXT;
import static org.jnario.util.Strings.startsWithWord;
import java.util.List;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.Token;
import org.eclipse.xtext.parser.antlr.AbstractSplittingTokenSource;
import org.eclipse.xtext.parser.antlr.ITokenAcceptor;
import org.eclipse.xtext.util.Strings;
public class FeatureTokenSource extends AbstractSplittingTokenSource {
private static final String SCENARIO_KEYWORD = "Scenario:";
private static final String BACKGROUND_KEYWORD = "Background:";
private static final String FEATURE_KEYWORD = "Feature:";
private static class TokenFactory{
private final CommonToken source;
private final ITokenAcceptor acceptor;
public TokenFactory(ITokenAcceptor acceptor, CommonToken source) {
this.acceptor = acceptor;
this.source = source;
}
public void add(int type, int start, int stop, int line, int charPosInLine){
if(start > stop){
return;
}
CommonToken result = new CommonToken(input(), type, Token.DEFAULT_CHANNEL, offset() + start, offset() + stop);
result.setLine(source.getLine() + line);
result.setCharPositionInLine(charPosInLine);
acceptor.accept(result);
}
private int offset() {
return source.getStartIndex();
}
private CharStream input() {
return source.getInputStream();
}
public void addSource() {
acceptor.accept(source);
}
}
@Override
protected boolean shouldSplitToken(Token candidate) {
return isFeatureText(candidate) || candidate.getType() == 0 || candidate.getType() == 12;
}
private boolean isFeatureText(Token candidate) {
return candidate.getType() == ruleFeatureText();
}
/*
* public for testing purposes
*/
@Override
public void doSplitToken(final Token splitMe, ITokenAcceptor result) {
TokenFactory tokens = new TokenFactory(result, (CommonToken) splitMe);
String featureText = splitMe.getText();
List<String> lines = Strings.split(featureText, '\n');
if(lines.isEmpty()){
tokens.addSource();
return;
}
String firstLine = lines.get(0);
int index = startsWithWord(firstLine, FEATURE_KEYWORD);
if(index == -1){
tokens.addSource();
return;
}
int stop = firstLine.length();
int featureStop = featureText.length()-1;
if(lines.size() == 1){
tokens.add(ruleFeatureText(), 0, featureStop, 1, index);
return;
}
tokens.add(ruleFeatureText(), 0, stop, 1, index);
int endOfFeature = stop+1;
for(int lineNr = 1; lineNr < lines.size(); lineNr++){
String line = lines.get(lineNr);
index = startsWithWord(line, BACKGROUND_KEYWORD);
if(index != -1){
tokens.add(ruleText(), endOfFeature, stop + index, 2, 0);
tokens.add(ruleBackground(), stop + index + 1, featureStop, lineNr + 1, index);
return;
}
index = startsWithWord(line, SCENARIO_KEYWORD);
if(index != -1){
tokens.add(ruleText(), endOfFeature, stop + index, 2, 0);
tokens.add(ruleScenario(), stop + index + 1, featureStop, lineNr + 1, index);
return;
}
stop += line.length() + 1;
}
tokens.add(ruleText(), endOfFeature, featureStop, 2, 0);
}
protected int ruleScenario() {
return RULE_SCENARIO_TEXT;
}
protected int ruleBackground() {
return RULE_BACKGROUND_TEXT;
}
protected int ruleText() {
return RULE_TEXT;
}
protected int ruleFeatureText() {
return RULE_FEATURE_TEXT;
}
}