blob: 87e4f8cb0533a622c62b8771fa1adeb4360e5b67 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package com.itemis.xtext.codebuff;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.AbstractElement;
import org.eclipse.xtext.Alternatives;
import org.eclipse.xtext.CharacterRange;
import org.eclipse.xtext.EOF;
import org.eclipse.xtext.Group;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.NegatedToken;
import org.eclipse.xtext.ParserRule;
import org.eclipse.xtext.RuleCall;
import org.eclipse.xtext.TerminalRule;
import org.eclipse.xtext.UntilToken;
import org.eclipse.xtext.Wildcard;
import org.eclipse.xtext.util.Strings;
import org.eclipse.xtext.util.XtextSwitch;
import org.eclipse.xtext.xtext.generator.parser.antlr.AntlrGrammarGenUtil;
public class TerminalRuleToLexerBody extends XtextSwitch<String>{
protected final StringBuilder result;
protected TerminalRuleToLexerBody() {
this.result = new StringBuilder();
}
public static String toLexerBody(TerminalRule rule) {
return new TerminalRuleToLexerBody().print(rule);
}
public String print(TerminalRule rule) {
doSwitch(rule.getAlternatives());
return result.toString();
}
@Override
public String caseAlternatives(Alternatives object) {
result.append('(');
boolean first = true;
for(AbstractElement elem: object.getElements()) {
if (!first) result.append('|');
first = false;
doSwitch(elem);
}
result.append(')').append(Strings.emptyIfNull(object.getCardinality()));
return "";
}
@Override
public String caseCharacterRange(CharacterRange object) {
if (!Strings.isEmpty(object.getCardinality()))
result.append('(');
doSwitch(object.getLeft());
result.append("..");
doSwitch(object.getRight());
if (!Strings.isEmpty(object.getCardinality())) {
result.append(')');
result.append(Strings.emptyIfNull(object.getCardinality()));
}
return "";
}
@Override
public String defaultCase(EObject object) {
throw new IllegalArgumentException(object.eClass().getName() + " is not a valid argument.");
}
@Override
public String caseGroup(Group object) {
if (!Strings.isEmpty(object.getCardinality()))
result.append('(');
boolean first = true;
for (AbstractElement elem : object.getElements()) {
if (!first) result.append(' ');
first = false;
doSwitch(elem);
}
if (!Strings.isEmpty(object.getCardinality()))
result.append(')');
result.append(Strings.emptyIfNull(object.getCardinality()));
return "";
}
@Override
public String caseKeyword(Keyword object) {
result.append("'");
String value = toLexerString(object.getValue());
result.append(value).append("'");
result.append(Strings.emptyIfNull(object.getCardinality()));
return "";
}
private String toLexerString(String theString) {
// return Strings.convertToJavaString(value);
int len = theString.length();
int bufLen = len * 2;
if (bufLen < 0) {
bufLen = Integer.MAX_VALUE;
}
StringBuffer outBuffer = new StringBuffer(bufLen);
for (int x = 0; x < len; x++) {
char aChar = theString.charAt(x);
// Handle common case first, selecting largest block that
// avoids the specials below
if ((aChar > 61) && (aChar < 127)) {
if (aChar == '\\') {
outBuffer.append('\\');
outBuffer.append('\\');
continue;
}
outBuffer.append(aChar);
continue;
}
switch (aChar) {
case ' ':
outBuffer.append(' ');
break;
case '\t':
outBuffer.append('\\');
outBuffer.append('t');
break;
case '\n':
outBuffer.append('\\');
outBuffer.append('n');
break;
case '\r':
outBuffer.append('\\');
outBuffer.append('r');
break;
case '\f':
outBuffer.append('\\');
outBuffer.append('f');
break;
case '\b':
outBuffer.append('\\');
outBuffer.append('b');
break;
case '\'':
outBuffer.append('\\');
outBuffer.append('\'');
break;
// don't escape double quotes
// case '"':
// outBuffer.append('\\');
// outBuffer.append('"');
// break;
default:
if ((aChar < 0x0020) || (aChar > 0x007e)) {
outBuffer.append('\\');
outBuffer.append('u');
outBuffer.append(Strings.toHex((aChar >> 12) & 0xF));
outBuffer.append(Strings.toHex((aChar >> 8) & 0xF));
outBuffer.append(Strings.toHex((aChar >> 4) & 0xF));
outBuffer.append(Strings.toHex(aChar & 0xF));
}
else {
outBuffer.append(aChar);
}
}
}
return outBuffer.toString();
}
@Override
public String caseWildcard(Wildcard object) {
result.append('.');
result.append(Strings.emptyIfNull(object.getCardinality()));
return "";
}
@Override
public String caseEOF(EOF object) {
result.append("EOF");
result.append(Strings.emptyIfNull(object.getCardinality()));
return "";
}
@Override
public String caseTerminalRule(TerminalRule object) {
result.append(AntlrGrammarGenUtil.getRuleName(object));
return "";
}
@Override
public String caseParserRule(ParserRule object) {
throw new IllegalStateException("Cannot call parser rules that are not terminal rules.");
}
@Override
public String caseRuleCall(RuleCall object) {
doSwitch(object.getRule());
result.append(Strings.emptyIfNull(object.getCardinality()));
return "";
}
@Override
public String caseNegatedToken(NegatedToken object) {
result.append("~(");
doSwitch(object.getTerminal());
result.append(")").append(Strings.emptyIfNull(object.getCardinality()));
return "";
}
@Override
public String caseUntilToken(UntilToken object) {
result.append("( options {greedy=false;} : . )*");
doSwitch(object.getTerminal());
return "";
}
}