1515 */
1616package org.dslforge.xtext.generator.web.parser
1717
18+ import java.util.Arrays
19+ import java.util.HashSet
1820import java.util.Iterator
1921import java.util.List
22+ import java.util.Set
2023import java.util.regex.Matcher
2124import java.util.regex.Pattern
2225import org.dslforge.common.AbstractGenerator
@@ -39,6 +42,7 @@ import org.eclipse.xtext.TerminalRule
3942import org.eclipse.xtext.XtextFactory
4043import org.eclipse.xtext.resource.SaveOptions
4144import org.eclipse.xtext.resource.XtextResource
45+ import org.eclipse.xtext.RuleCall
4246
4347class 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 ' |' \u 000C' |' \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