Skip to content

Commit

Permalink
better handling of cross references in xtext-to-antlr transformation
Browse files Browse the repository at this point in the history
  • Loading branch information
amlajmi committed Nov 21, 2016
1 parent dc584f0 commit dbf4664
Showing 1 changed file with 35 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
*/
package org.dslforge.xtext.generator.web.parser

import java.util.Arrays
import java.util.HashSet
import java.util.Iterator
import java.util.List
import java.util.Set
import java.util.regex.Matcher
import java.util.regex.Pattern
import org.dslforge.common.AbstractGenerator
Expand All @@ -39,6 +42,7 @@ import org.eclipse.xtext.TerminalRule
import org.eclipse.xtext.XtextFactory
import org.eclipse.xtext.resource.SaveOptions
import org.eclipse.xtext.resource.XtextResource
import org.eclipse.xtext.RuleCall

class GenGrammar extends AbstractGenerator {

Expand Down Expand Up @@ -91,7 +95,6 @@ class GenGrammar extends AbstractGenerator {
val appendable = createAppendable()
var grammarDefinition = grammar.eResource as XtextResource
val rules = grammar.rules
// rename rules
var List<ParserRule> parserRules = GrammarUtil::allParserRules(grammar);
for (ParserRule pr : parserRules) {
Expand All @@ -101,23 +104,22 @@ class GenGrammar extends AbstractGenerator {
for (EnumRule en : enumRules) {
en.setName("rule_" + en.name.toFirstUpper)
}
parserRules = GrammarUtil::allParserRules(grammar);
for (ParserRule pr : parserRules) {
// rules on the client side are untyped
// rules are untyped
println(pr)
pr.setType(null)
//remove semantic predicates
pr.setType(null)
//semantic predicates
var List<AbstractElement> elements = GrammarUtil::containedAbstractElements(pr)
for (AbstractElement e: elements)
e.predicated = false
// remove the actions (xtext-specific)
e.predicated = false
// actions
val alternatives = pr.alternatives
if (alternatives instanceof Group) {
var List<AbstractElement> objs = (alternatives as Group).elements
var Iterator<AbstractElement> i = objs.iterator();
while (i.hasNext()) {
var o = i.next()
//remove actions
// actions
if (o instanceof Action) {
if (o.feature!=null)
i.remove();
Expand All @@ -133,37 +135,39 @@ class GenGrammar extends AbstractGenerator {
if (operator.equals("?=")) {
a.setOperator("=")
}
// cross references are not handled on the client side
// replace cross references in the form "reference=[Type|X]" to "reference=X" where X in {ID, STRING, FQN, ...}
// cross references
if (terminal instanceof CrossReference) {
var call = XtextFactory::eINSTANCE.createRuleCall
var replacement = XtextFactory::eINSTANCE.createTerminalRule
val allTerminalRules = GrammarUtil::allTerminalRules(grammar)
for (TerminalRule t: allTerminalRules) {
if (t.name=="ID")
replacement=t
var x = terminal.terminal
if (x instanceof RuleCall) {
var rule = (x as RuleCall).rule
if (t.name==rule.name)
replacement=t
}
}
call.setRule(replacement)
a.setTerminal(call)
}
}
var text = grammarDefinition.serializer.serialize(pr, SaveOptions::defaultOptions)
// remove all the {Pattern.current=xxx}
var text = grammarDefinition.serializer.serialize(pr, SaveOptions::defaultOptions)
// {Pattern.current=xxx}
val Pattern p = Pattern::compile("\\{(.+?)\\}")
val Matcher m = p.matcher(text)
while (m.find()) {
val group = m.group
if (!(group.substring(1, 2) == '\''))
text = text.replace(group, "")
}
// append EOF at the end of rule
}
//EOF
if (rules.get(0).equals(pr))
text = text.substring(0, text.length - 1) + " EOF!" + ";"
text = text.replaceAll("\"", "'")
appendable.newLine.append(text + "\n").newLine

appendable.newLine.append(text + "\n")
}

// Manage enumerations
enumRules = GrammarUtil::allEnumRules(grammar);
for (EnumRule en : enumRules) {
Expand All @@ -181,9 +185,18 @@ class GenGrammar extends AbstractGenerator {
}
}
builder.append(";")
appendable.newLine.append(builder + "\n").newLine
appendable.newLine.append(builder + "\n")
}
// Manage terminals
var terminalRules = GrammarUtil::allTerminalRules(grammar);
var Set<String> covered = new HashSet<String>(Arrays.asList("ID", "STRING", "COMMENT", "WS", "INT", "ML_COMMENT", "SL_COMMENT", "ANY_OTHER"));
for (TerminalRule terminal : terminalRules) {
if (!covered.contains(terminal.name)) {
var text = grammarDefinition.serializer.serialize(terminal, SaveOptions::defaultOptions)
text = text.replace("terminal ", "");
appendable.newLine.append(text + "\n");
}
}

return appendable.content
}

Expand All @@ -196,13 +209,11 @@ class GenGrammar extends AbstractGenerator {

WS: (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;} ;

//NUMBER: INT ('.' INT)?;

INT: ('0'..'9')+;
'''
def StringAppendable createAppendable() {
val appendable = new StringAppendable(indentation, lineSeparator)
return appendable
}
}
}

0 comments on commit dbf4664

Please sign in to comment.