Hello,
I am trying to use case insensitive keywords defined in the grammar as ID's in the same grammar.
Issue:
The following parsing unit test code snippet, fails
var Main;
ctl main(Main);
org.opentest4j.AssertionFailedError:
Unexpected errors:
XtextSyntaxDiagnostic: null:10 mismatched input 'Main' expecting RULE_ID, XtextSyntaxDiagnostic: null:10 mismatched input ')' expecting '(' ==> expected: <true> but was: <false>
Research:
https://blogs.itemis.com/en/xtext-hint-identifiers-conflicting-with-keywords
http://www.eclipse.org/forums/index.php/m/685849/
http://www.eclipse.org/forums/index.php/m/639647/
Request:
Please help me get the Parsing UnitTest to pass.
I am convinced, that something small is being missed but I just can't seem to figure it out.
Unit Test:
/*
* generated by Xtext 2.15.0-SNAPSHOT
*/
package org.xtext.example.mydsl.tests
import com.google.inject.Inject
import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.extensions.InjectionExtension
import org.eclipse.xtext.testing.util.ParseHelper
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.^extension.ExtendWith
import org.xtext.example.mydsl.myDsl.Model
@ExtendWith(InjectionExtension)
@InjectWith(MyDslInjectorProvider)
class MyDslParsingTest {
@Inject
ParseHelper<Model> parseHelper
@Test
def void test01() {
val result = parseHelper.parse('''
ctl option(*NODEBUGIO :*SRCSTMT);
VAR Foo;
ctl main(Foo);
var Bar;
ctl main(Bar);
var Main;
ctl main(Main); // <<< ERROR HERE!!! :(
''')
Assertions.assertNotNull(result)
val errors = result.eResource.errors
Assertions.assertTrue(errors.isEmpty, '''Unexpected errors: «errors.join(", ")»''')
}
}
Grammer Option1:
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
controls+=Statements+
;
Statements:
Control |
VarDef |
ValDef
;
Control:
'CTL' keywords+=ControlOption+ ';'
;
ControlOption:
ControlOptionMAIN |
ControlOptionOPTION
;
ControlOptionMAIN:
'MAIN' '(' ref=[VarOrDefRef] ')'
;
ControlOptionOPTION:
'OPTION' '(' options+=OptionOptions (':' options+=OptionOptions)* ')'
;
enum OptionOptions:
XREF='*XREF' |
NOXREF='*NOXREF' |
SECLVL='*SECLVL' |
NOSECLVL='*NOSECLVL' |
SHOWCPY='*SHOWCPY' |
NOSHOWCPY='*NOSHOWCPY' |
EXPDDS='*EXPDDS' |
NOEXPDDS='*NOEXPDDS' |
EXP='*EXT' |
NOEXP='*NOEXT' |
SHOWSKP='*SHOWSKP' |
NOSHOWSKP='*NOSHOWSKP' |
SRCSTMT='*SRCSTMT' |
NOSRCSTMT='*NOSRCSTMT' |
DEBUGIO='*DEBUGIO' |
NODEBUGIO='*NODEBUGIO' |
UNREF='*UNREF' |
NOUNREF='*NOUNREF'
;
VarDef:
'VAR' name=ValidID ';'
;
ValDef:
'VAL' name=ValidID ';'
;
VarOrDefRef:
VarDef | ValDef
;
ValidID:
ID | KEWORD
;
KEWORD:
'CTL' | 'MAIN' | 'OPION' | 'VAR' | 'VAL'
;
Grammer Option2:
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
controls+=Statements+
;
Statements:
Control |
VarDef |
ValDef
;
Control:
TCTL keywords+=ControlOption+ ';'
;
ControlOption:
ControlOptionMAIN |
ControlOptionOPTION
;
ControlOptionMAIN:
TMAIN '(' ref=[VarOrDefRef] ')'
;
ControlOptionOPTION:
TOPTION '(' options+=OptionOptions (':' options+=OptionOptions)* ')'
;
enum OptionOptions:
XREF='*XREF' |
NOXREF='*NOXREF' |
SECLVL='*SECLVL' |
NOSECLVL='*NOSECLVL' |
SHOWCPY='*SHOWCPY' |
NOSHOWCPY='*NOSHOWCPY' |
EXPDDS='*EXPDDS' |
NOEXPDDS='*NOEXPDDS' |
EXP='*EXT' |
NOEXP='*NOEXT' |
SHOWSKP='*SHOWSKP' |
NOSHOWSKP='*NOSHOWSKP' |
SRCSTMT='*SRCSTMT' |
NOSRCSTMT='*NOSRCSTMT' |
DEBUGIO='*DEBUGIO' |
NODEBUGIO='*NODEBUGIO' |
UNREF='*UNREF' |
NOUNREF='*NOUNREF'
;
VarDef:
TVAR name=MyID ';'
;
ValDef:
TVAL name=MyID ';'
;
VarOrDefRef:
VarDef | ValDef
;
MyID:
TMAIN | ID
;
terminal TCTL:
('c'|'C')('t'|'T')('l'|'L')
;
terminal TMAIN:
('m'|'M')('a'|'A')('i'|'I')('n'|'N')
;
terminal TOPTION:
('o'|'O')('p'|'P')('t'|'T')('i'|'I')('o'|'O')('n'|'N')
;
terminal TVAR:
('v'|'V')('a'|'A')('r'|'R')
;
terminal TVAL:
('v'|'V')('a'|'A')('l'|'L')
;
MWE2 WorkFlow:
module org.xtext.example.mydsl.GenerateMyDsl
import org.eclipse.xtext.xtext.generator.*
import org.eclipse.xtext.xtext.generator.model.project.*
var rootPath = ".."
Workflow {
component = XtextGenerator {
configuration = {
project = StandardProjectConfig {
baseName = "org.xtext.example.mydsl"
rootPath = rootPath
runtimeTest = {
enabled = true
}
eclipsePlugin = {
enabled = true
}
eclipsePluginTest = {
enabled = true
}
web = {
enabled = true
}
createEclipseMetaData = true
}
code = {
encoding = "windows-1252"
lineDelimiter = "\r\n"
fileHeader = "/*\n * generated by Xtext \${version}\n */"
}
}
language = StandardLanguage {
name = "org.xtext.example.mydsl.MyDsl"
fileExtensions = "mydsl"
serializer = {
generateStub = false
}
validator = {
// composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
}
junitSupport = {
junitVersion = "5"
}
parserGenerator = {
debugGrammar = true
options = {
ignoreCase = true
}
}
scopeProvider = {
ignoreCase = true
}
}
}
}