blob: f4e6fc1d79759c9c35ea7e87f1416d990bfc850d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2018 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink - initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.examples.xtext2lpg;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.ocl.examples.xtext2lpg.XBNF.AbstractElement;
import org.eclipse.ocl.examples.xtext2lpg.XBNF.AbstractRule;
import org.eclipse.ocl.examples.xtext2lpg.XBNF.CharacterRange;
import org.eclipse.ocl.examples.xtext2lpg.XBNF.Conjunction;
import org.eclipse.ocl.examples.xtext2lpg.XBNF.Disjunction;
import org.eclipse.ocl.examples.xtext2lpg.XBNF.Grammar;
import org.eclipse.ocl.examples.xtext2lpg.XBNF.Keyword;
import org.eclipse.ocl.examples.xtext2lpg.XBNF.LexerGrammar;
import org.eclipse.ocl.examples.xtext2lpg.XBNF.ParserGrammar;
import org.eclipse.ocl.examples.xtext2lpg.XBNF.Syntax;
import org.eclipse.ocl.examples.xtext2lpg.XBNF.TerminalRule;
import org.eclipse.ocl.examples.xtext2lpg.XBNF.TypedRule;
import org.eclipse.ocl.examples.xtext2lpg.XBNF.UntypedRule;
//import org.eclipse.ocl.examples.build.acceleo.GenerateXBNF2LPG;
public abstract class GenerateLPGUtils extends GenerateLPG
{
protected final @NonNull Comparator<CharacterRange> characterRangeComparator = new Comparator<CharacterRange>()
{
public int compare(CharacterRange o1, CharacterRange o2) {
String m1 = o1.getLeft();
String m2 = o2.getLeft();
if (m1 == null) m1 = "";
if (m2 == null) m2 = "";
int diff = m1.compareTo(m2);
if (diff == 0) {
m1 = o1.getRight();
m2 = o2.getRight();
if (m1 == null) m1 = "";
if (m2 == null) m2 = "";
diff = m1.compareTo(m2);
}
return diff;
}
};
protected final @NonNull Comparator<Conjunction> conjunctionComparator = new Comparator<Conjunction>()
{
public int compare(Conjunction o1, Conjunction o2) {
int m1 = o1.getElements().size();
int m2 = o2.getElements().size();
int diff = m1 - m2;
if (diff == 0) {
for (int i = 0; i < m1; i++) {
AbstractElement e1 = o1.getElements().get(i);
AbstractElement e2 = o2.getElements().get(i);
String d1 = e1.getDebug();
String d2 = e2.getDebug();
if (d1 == null) d1 = "";
if (d2 == null) d2 = "";
diff = d1.compareTo(d2);
if (diff != 0) {
break;
}
}
}
return diff;
}
};
protected final @NonNull Comparator<AbstractRule> ruleComparator = new Comparator<AbstractRule>()
{
public int compare(AbstractRule o1, AbstractRule o2) {
String m1 = o1.getName();
String m2 = o2.getName();
if (m1 == null) m1 = "";
if (m2 == null) m2 = "";
return m1.compareTo(m2);
}
};
protected static final @NonNull Map<String, String> keyword2label = new HashMap<String, String>();
static {
keyword2label.put("_", "USCORE");
keyword2label.put("&", "AND");
keyword2label.put("@", "AT");
keyword2label.put("|", "BAR");
keyword2label.put("^", "CARET");
keyword2label.put(":", "COLON");
keyword2label.put(",", "COMMA");
keyword2label.put(".", "DOT");
keyword2label.put("=", "EQUALS");
keyword2label.put("#", "HASH");
keyword2label.put("<", "LANGLE");
keyword2label.put("{", "LBRACE");
keyword2label.put("(", "LPAREN");
keyword2label.put("[", "LSQUARE");
keyword2label.put("-", "MINUS");
keyword2label.put("!", "PLING");
keyword2label.put("+", "PLUS");
keyword2label.put("?", "QUERY");
keyword2label.put(">", "RANGLE");
keyword2label.put("}", "RBRACE");
keyword2label.put(")", "RPAREN");
keyword2label.put("]", "RSQUARE");
keyword2label.put(";", "SEMICOLON");
keyword2label.put("/", "SLASH");
keyword2label.put("*", "STAR");
keyword2label.put("'", "SQUOTE");
keyword2label.put("\"", "DQUOTE");
keyword2label.put("\\", "BSLASH");
keyword2label.put("\r", "CR");
keyword2label.put("\n", "LF");
keyword2label.put("\t", "HTAB");
keyword2label.put(" ", "SPACE");
keyword2label.put("->", "ARROW");
keyword2label.put("..", "DOTDOT");
keyword2label.put("<=", "LESSEQ");
keyword2label.put(">=", "GTREQ");
keyword2label.put("<>", "NOTEQ");
keyword2label.put("::", "SCOPE");
}
private int state = 0;
protected String emitKeyword(String keywordValue) {
return keywordValue.replace("\\w","$0 ");
}
protected String emitLabel(Character keywordValue) {
return emitLabel(keywordValue.toString());
}
protected String emitLabel(String keywordValue) {
String label = keyword2label.get(keywordValue);
if (label == null) {
label = keywordValue;
}
if (label.matches("[a-zA-Z]*")) {
return label;
}
else {
StringBuilder s = new StringBuilder();
for (int i = 0; i < label.length(); i++) {
char c = label.charAt(i);
String mapped = keyword2label.get(String.valueOf(c));
if (mapped != null) {
if (i > 0) {
s.append("_");
}
s.append(mapped);
}
else {
if (i == 0) {
s.append("T");
}
s.append("_" + (int)c);
}
}
return s.toString();
}
}
protected String emitQuotedCharacter(Character c) {
if (c == '\f') {
return "FormFeed";
}
if (c == '\n') {
return "NewLine";
}
if (c == '\r') {
return "Return";
}
if (c == '\t') {
return "HorizontalTab";
}
if (c == '\'') {
return "\"'\"";
}
return "'" + c + "'";
}
protected String emitSyntaxName(Syntax syntax) {
String name = syntax.getName();
int lastDot = name.lastIndexOf('.');
int firstCharacter = lastDot > 0 ? lastDot+1 : 1;
return name.substring(firstCharacter, name.length());
}
protected String emitSyntaxPackage(Syntax syntax) {
String name = syntax.getName();
int lastDot = name.lastIndexOf('.');
int lastCharacter = lastDot > 0 ? lastDot+1 : name.length();
return name.substring(0, lastCharacter-1);
}
protected @NonNull List<String> getCharacters(@NonNull CharacterRange characterRange) {
List<String> allCharacters = new ArrayList<String>();
char left = characterRange.getLeft().charAt(0);
char right = characterRange.getRight().charAt(0);
for (char c = left; c <= right; c++) {
allCharacters.add(String.valueOf(c));
}
return allCharacters;
}
protected @NonNull LexerGrammar getLexerGrammar(@NonNull Syntax syntax) {
for (Grammar grammar : syntax.getGrammars()) {
if (grammar instanceof LexerGrammar) {
return (LexerGrammar)grammar;
}
}
throw new IllegalStateException("No LexerGrammar");
}
protected @NonNull ParserGrammar getParserGrammar(@NonNull Syntax syntax) {
for (Grammar grammar : syntax.getGrammars()) {
if (grammar instanceof ParserGrammar) {
return (ParserGrammar)grammar;
}
}
throw new IllegalStateException("No ParserGrammar");
}
protected @NonNull List<String> getSortedAlphaChars(@NonNull Syntax syntax) {
Set<Character> allElements = new HashSet<Character>();
for (TreeIterator<EObject> tit = syntax.eAllContents(); tit.hasNext(); ) {
EObject eObject = tit.next();
if (eObject instanceof Keyword) {
String keywordValue = ((Keyword) eObject).getValue();
if (keywordValue.matches("[a-zA-Z]+")) {
for (char c : keywordValue.toCharArray()) {
allElements.add(c);
}
}
}
}
List<String> sortedElements = new ArrayList<String>();
for (Character c : allElements) {
sortedElements.add(c.toString());
}
Collections.sort(sortedElements);
return sortedElements;
}
protected @NonNull List<CharacterRange> getSortedCharacterRanges(@NonNull LexerGrammar lexerGrammar) {
Set<CharacterRange> allElements = new HashSet<CharacterRange>();
for (TreeIterator<EObject> tit = lexerGrammar.eAllContents(); tit.hasNext(); ) {
EObject eObject = tit.next();
if (eObject instanceof CharacterRange) {
CharacterRange characterRange = (CharacterRange) eObject;
String label = null;
for (CharacterRange knownRange : allElements) {
if (characterRange.getLeft().equals(knownRange.getLeft()) && characterRange.getRight().equals(knownRange.getRight())) {
label = knownRange.getDebug();
}
}
if (label == null) {
allElements.add(characterRange);
String left = characterRange.getLeft();
String right = characterRange.getRight();
if (left.equals("0") && right.equals("9")) {
label = "DIGITS";
}
else if (left.equals("a") && right.equals("z")) {
label = "LOWERS";
}
else if (left.equals("A") && right.equals("Z")) {
label = "UPPERS";
}
else {
label = "RANGE_" + allElements.size();
}
}
characterRange.setDebug(label);
}
}
List<CharacterRange> sortedElements = new ArrayList<CharacterRange>(allElements);
Collections.sort(sortedElements, characterRangeComparator);
return sortedElements;
}
protected @NonNull List<Conjunction> getSortedConjunctions(@NonNull Disjunction disjunction) {
List<Conjunction> sortedConjunctions = new ArrayList<Conjunction>(disjunction.getConjunctions());
Collections.sort(sortedConjunctions, conjunctionComparator);
return sortedConjunctions;
}
protected @NonNull List<String> getSortedKWValues(@NonNull ParserGrammar parserGrammar) {
Set<String> allElements = new HashSet<String>();
for (TreeIterator<EObject> tit = parserGrammar.eAllContents(); tit.hasNext(); ) {
EObject eObject = tit.next();
if (eObject instanceof Keyword) {
String keywordValue = ((Keyword) eObject).getValue();
if (keywordValue.matches("[a-zA-Z]+")) {
allElements.add(keywordValue);
}
}
}
List<String> sortedElements = new ArrayList<String>(allElements);
Collections.sort(sortedElements);
return sortedElements;
}
protected @NonNull List<TypedRule> getSortedParserRules(@NonNull ParserGrammar parserGrammar) {
Set<TypedRule> allElements = new HashSet<TypedRule>();
for (TypedRule subRule : parserGrammar.getRules()) {
if (!(subRule instanceof TerminalRule)) {
allElements.add(subRule);
}
}
List<TypedRule> sortedElements = new ArrayList<TypedRule>(allElements);
Collections.sort(sortedElements, ruleComparator);
return sortedElements;
}
protected @NonNull List<Character> getSortedPunctChars(@NonNull LexerGrammar lexerGrammar) {
Set<String> characterTerminals = new HashSet<String>();
for (CharacterRange characterRange: getSortedCharacterRanges(lexerGrammar)) {
for (String character: getCharacters(characterRange)) {
characterTerminals.add(character);
}
}
Set<Character> allElements = new HashSet<Character>();
for (TreeIterator<EObject> tit = lexerGrammar.eAllContents(); tit.hasNext(); ) {
EObject eObject = tit.next();
if (eObject instanceof Keyword) {
String keywordValue = ((Keyword) eObject).getValue();
if (!keywordValue.matches("[a-zA-Z]+")) {
for (char c : keywordValue.toCharArray()) {
if (!characterTerminals.contains(String.valueOf(c))) {
allElements.add(c);
}
}
}
}
}
List<Character> sortedElements = new ArrayList<Character>(allElements);
Collections.sort(sortedElements);
return sortedElements;
}
protected @NonNull List<String> getSortedPunctValues(@NonNull ParserGrammar parserGrammar) {
Set<String> allElements = new HashSet<String>();
for (TreeIterator<EObject> tit = parserGrammar.eAllContents(); tit.hasNext(); ) {
EObject eObject = tit.next();
if (eObject instanceof Keyword) {
String keywordValue = ((Keyword) eObject).getValue();
if (!keywordValue.matches("[a-zA-Z]+")) {
allElements.add(keywordValue);
}
}
}
List<String> sortedElements = new ArrayList<String>(allElements);
Collections.sort(sortedElements);
return sortedElements;
}
protected @NonNull List<UntypedRule> getSortedSubRules(@NonNull Iterable<UntypedRule> subRules) {
List<UntypedRule> allElements = new ArrayList<UntypedRule>();
for (UntypedRule subRule : subRules) {
allElements.add(subRule);
}
Collections.sort(allElements, ruleComparator);
return allElements;
}
protected @NonNull List<TerminalRule> getSortedTerminalRules(@NonNull Syntax syntax) {
Set<TerminalRule> allElements = new HashSet<TerminalRule>();
for (TreeIterator<EObject> tit = syntax.eAllContents(); tit.hasNext(); ) {
EObject eObject = tit.next();
if (eObject instanceof TerminalRule) {
allElements.add((TerminalRule)eObject);
}
}
List<TerminalRule> sortedElements = new ArrayList<TerminalRule>(allElements);
Collections.sort(sortedElements, ruleComparator);
return sortedElements;
}
protected int nextState() {
return ++state;
}
protected @NonNull <T extends AbstractRule> List<T> selectRules(@NonNull Iterable<T> rules, String name) {
List<T> selectedRules = new ArrayList<T>();
for (T rule : rules) {
if (name.equals(rule.getName())) {
selectedRules.add(rule);
}
}
return selectedRules;
}
}