Skip to content

Commit dbf4664

Browse files
committed
better handling of cross references in xtext-to-antlr transformation
1 parent dc584f0 commit dbf4664

1 file changed

Lines changed: 35 additions & 24 deletions

File tree

  • plugins/org.dslforge.xtext.generator/src/org/dslforge/xtext/generator/web/parser

plugins/org.dslforge.xtext.generator/src/org/dslforge/xtext/generator/web/parser/GenGrammar.xtend

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515
*/
1616
package org.dslforge.xtext.generator.web.parser
1717

18+
import java.util.Arrays
19+
import java.util.HashSet
1820
import java.util.Iterator
1921
import java.util.List
22+
import java.util.Set
2023
import java.util.regex.Matcher
2124
import java.util.regex.Pattern
2225
import org.dslforge.common.AbstractGenerator
@@ -39,6 +42,7 @@ import org.eclipse.xtext.TerminalRule
3942
import org.eclipse.xtext.XtextFactory
4043
import org.eclipse.xtext.resource.SaveOptions
4144
import org.eclipse.xtext.resource.XtextResource
45+
import org.eclipse.xtext.RuleCall
4246

4347
class GenGrammar extends AbstractGenerator {
4448

@@ -91,7 +95,6 @@ class GenGrammar extends AbstractGenerator {
9195
val appendable = createAppendable()
9296
var grammarDefinition = grammar.eResource as XtextResource
9397
val rules = grammar.rules
94-
9598
// rename rules
9699
var List<ParserRule> parserRules = GrammarUtil::allParserRules(grammar);
97100
for (ParserRule pr : parserRules) {
@@ -101,23 +104,22 @@ class GenGrammar extends AbstractGenerator {
101104
for (EnumRule en : enumRules) {
102105
en.setName("rule_" + en.name.toFirstUpper)
103106
}
104-
parserRules = GrammarUtil::allParserRules(grammar);
105107
for (ParserRule pr : parserRules) {
106-
// rules on the client side are untyped
108+
// rules are untyped
107109
println(pr)
108-
pr.setType(null)
109-
//remove semantic predicates
110+
pr.setType(null)
111+
//semantic predicates
110112
var List<AbstractElement> elements = GrammarUtil::containedAbstractElements(pr)
111113
for (AbstractElement e: elements)
112-
e.predicated = false
113-
// remove the actions (xtext-specific)
114+
e.predicated = false
115+
// actions
114116
val alternatives = pr.alternatives
115117
if (alternatives instanceof Group) {
116118
var List<AbstractElement> objs = (alternatives as Group).elements
117119
var Iterator<AbstractElement> i = objs.iterator();
118120
while (i.hasNext()) {
119121
var o = i.next()
120-
//remove actions
122+
// actions
121123
if (o instanceof Action) {
122124
if (o.feature!=null)
123125
i.remove();
@@ -133,37 +135,39 @@ class GenGrammar extends AbstractGenerator {
133135
if (operator.equals("?=")) {
134136
a.setOperator("=")
135137
}
136-
// cross references are not handled on the client side
137-
// replace cross references in the form "reference=[Type|X]" to "reference=X" where X in {ID, STRING, FQN, ...}
138+
// cross references
138139
if (terminal instanceof CrossReference) {
139140
var call = XtextFactory::eINSTANCE.createRuleCall
140141
var replacement = XtextFactory::eINSTANCE.createTerminalRule
141142
val allTerminalRules = GrammarUtil::allTerminalRules(grammar)
142143
for (TerminalRule t: allTerminalRules) {
143-
if (t.name=="ID")
144-
replacement=t
144+
var x = terminal.terminal
145+
if (x instanceof RuleCall) {
146+
var rule = (x as RuleCall).rule
147+
if (t.name==rule.name)
148+
replacement=t
149+
}
150+
145151
}
146152
call.setRule(replacement)
147153
a.setTerminal(call)
148154
}
149155
}
150-
var text = grammarDefinition.serializer.serialize(pr, SaveOptions::defaultOptions)
151-
// remove all the {Pattern.current=xxx}
156+
var text = grammarDefinition.serializer.serialize(pr, SaveOptions::defaultOptions)
157+
// {Pattern.current=xxx}
152158
val Pattern p = Pattern::compile("\\{(.+?)\\}")
153159
val Matcher m = p.matcher(text)
154160
while (m.find()) {
155161
val group = m.group
156162
if (!(group.substring(1, 2) == '\''))
157163
text = text.replace(group, "")
158-
}
159-
// append EOF at the end of rule
164+
}
165+
//EOF
160166
if (rules.get(0).equals(pr))
161167
text = text.substring(0, text.length - 1) + " EOF!" + ";"
162168
text = text.replaceAll("\"", "'")
163-
appendable.newLine.append(text + "\n").newLine
164-
169+
appendable.newLine.append(text + "\n")
165170
}
166-
167171
// Manage enumerations
168172
enumRules = GrammarUtil::allEnumRules(grammar);
169173
for (EnumRule en : enumRules) {
@@ -181,9 +185,18 @@ class GenGrammar extends AbstractGenerator {
181185
}
182186
}
183187
builder.append(";")
184-
appendable.newLine.append(builder + "\n").newLine
188+
appendable.newLine.append(builder + "\n")
189+
}
190+
// Manage terminals
191+
var terminalRules = GrammarUtil::allTerminalRules(grammar);
192+
var Set<String> covered = new HashSet<String>(Arrays.asList("ID", "STRING", "COMMENT", "WS", "INT", "ML_COMMENT", "SL_COMMENT", "ANY_OTHER"));
193+
for (TerminalRule terminal : terminalRules) {
194+
if (!covered.contains(terminal.name)) {
195+
var text = grammarDefinition.serializer.serialize(terminal, SaveOptions::defaultOptions)
196+
text = text.replace("terminal ", "");
197+
appendable.newLine.append(text + "\n");
198+
}
185199
}
186-
187200
return appendable.content
188201
}
189202

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

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

199-
//NUMBER: INT ('.' INT)?;
200-
201212
INT: ('0'..'9')+;
202213
'''
203214
204215
def StringAppendable createAppendable() {
205216
val appendable = new StringAppendable(indentation, lineSeparator)
206217
return appendable
207218
}
208-
}
219+
}

0 commit comments

Comments
 (0)