I have made a grammar and the editor does not show any error, when I select 'Generate XText Artifacts', I get the following error:
error(208): ../mestra.dmxlightshow/src-gen/mestra/parser/antlr/internal/InternalDmxLightShow.g:3668:1: The following token definitions can never be matched because prior tokens match the same input: RULE_MIDI_CHANNEL error(208): ../mestra.dmxlightshow.ide/src-gen/mestra/ide/contentassist/antlr/internal/InternalDmxLightShow.g:10741:1: The following token definitions can never be matched because prior tokens match the same input: RULE_MIDI_CHANNEL
MIDI_CHANNEL / MidiChannel is only used in the following fragments:
MidiNoteTrigger:
'Note' onOff=ON_OFF 'Channel' mc=MidiChannel ('Note' note=MidiNote | 'NoteRange' noteRange=MidiNoteRange) velocity=MIDI_VALUE;
MidiCcTrigger:
'CC' 'Channel' mc=MidiChannel 'Number' ccNumber=(MIDI_VALUE) ('Value' value=MidiValue | 'ValueRange' valueRange=MidiValueRange);
MidiAftertouchTrigger:
'Aftertouch' 'Channel' mc=MidiChannel ('Value' value=MidiValue | 'ValueRange' valueRange=MidiValueRange);
MidiProgramChangeTrigger:
'PrgChg' 'Channel' mc=MidiChannel 'Bank' bank=MidiValue 'Program' program=MidiValue;
MidiChannel:
channel=('OMNI' | MIDI_CHANNEL);
At the start of each rule (except MidiChannel' there is a keyword ('Time', 'Note', 'CC', 'Aftertouch', 'PrgCh', so I hoped following rules would be all unique.
And the definition of MIDI_CHANNEL is:
terminal MIDI_CHANNEL:
('1' '0'..'6') |
( '0'..'9');
How can I fix this error?
The full grammar is below:
TESTS I DID
Changing the rule into a different name and written out numbers:
terminal MIDI_CHANNEL_NUMBER: ('1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | '13' | '14' | '15' | '16');
Result: same error with different name (MIDI_CHANNEL_NUMBER)
Removed the reference to MIDI_CHANNEL_NUMBER (so the rule is never used):
Result: ERROR IS STILL PRESENT. I did not expect this as it is nowhere used.
Removing numbers 10 to 16 from the list
Result: Error is still present.
Removed ( and )
Result: Error is still present.
Changing values to 'x' and 'y'
Result: Error disappears. But I don't want values x and y, but 1 to 16.
FULL GRAMMAR
// Grammar
grammar mestra.DmxLightShow with org.eclipse.xtext.common.Terminals
generate dmxLightShow 'http://www.DmxLightShow.mestra'
// Main structure
Mestra:
'songs:' songs +=Song+
'triggers:' triggers+=RuleTrigger+
'commands:' commands+=Command+;
// Song structure
Song:
'song' name=ID ':'
'bank' bank=MIDI_VALUE 'program' program=MIDI_VALUE ';'
rules=Rules
('order' sequenceRefs+=[Sequence] (',' sequenceRefs+=[Sequence])* ';'
'sequences:' sequences += Sequence+)?;
Sequence:
'sequence' name=ID ':'
rules=Rules
('order' stepRefs+=[Step] (',' stepRefs+=[Step])* ';'
'steps:' steps += Step+)?;
Step:
'step' name=ID ':'
rules=Rules;
// Rules
Rules:
{Rules} rules+=Rule*;
Rule:
'rule' (ruleTriggers=RuleTriggers ':')? ruleCommands=RuleCommands ';';
RuleTriggers:
triggerRefs+=[RuleTrigger] (',' triggerRefs+=[RuleTrigger])*;
RuleCommands:
commandsRefs+=[Command] (',' commandsRefs+=[Command])*;
// Rule Triggers
RuleTrigger:
name=ID type=(/* DmxRuleTrigger | */ MidiRuleTrigger) ';';
// DmxRuleTrigger: // Not supported
MidiRuleTrigger:
type=(MidiTimeTrigger | MidiNoteTrigger | MidiCcTrigger | MidiAftertouchTrigger | MidiProgramChangeTrigger) ';';
MidiTimeTrigger:
'Time' time=Time;
MidiNoteTrigger:
'Note' onOff=ON_OFF 'Channel' mc=MidiChannel ('Note' note=MidiNote | 'NoteRange' noteRange=MidiNoteRange) velocity=MIDI_VALUE;
MidiCcTrigger:
'CC' 'Channel' mc=MidiChannel 'Number' ccNumber=(MIDI_VALUE) ('Value' value=MidiValue | 'ValueRange' valueRange=MidiValueRange);
MidiAftertouchTrigger:
'Aftertouch' 'Channel' mc=MidiChannel ('Value' value=MidiValue | 'ValueRange' valueRange=MidiValueRange);
MidiProgramChangeTrigger:
'PrgChg' 'Channel' mc=MidiChannel 'Bank' bank=MidiValue 'Program' program=MidiValue;
MidiChannel:
channel=('OMNI' | MIDI_CHANNEL);
MidiValue:
value=MIDI_VALUE;
MidiValueRange:
start=MIDI_VALUE '-' end=MIDI_VALUE;
MidiNote:
'Note' note=MIDI_NOTE;
MidiNoteRange:
'NoteRange' start=MIDI_NOTE '-' end=MIDI_NOTE;
Time:
'Time' time=INT type=('ms' | 's' );
// Commands
Command:
name=ID type=(DmxCommand /* | MidiCommand */ ) ';';
// MidiCommand: // Not supported
DmxCommand:
parGroup=ParGroup dmxSubCommands=DmxSubCommands ';';
ParGroup:
(parGroup= 'AllGroupsAll' |
{ParGroup} 'AllGroupsCenter' |
{ParGroup} 'AllGroupsAllExceptEgoRisers' |
{ParGroup} 'AllGroupsLeft' |
{ParGroup} 'AllGroupsRight' |
{ParGroup} 'LedBarAll' |
{ParGroup} 'LedBarCenter' |
{ParGroup} 'LedBarLeft' |
{ParGroup} 'LedBarRight' |
{ParGroup} 'DrumsAll' |
{ParGroup} 'DrumsLeft' |
{ParGroup} 'DrumsRight' |
{ParGroup} 'EgoRisersAll' |
{ParGroup} 'EgoRisersLeft' |
{ParGroup} 'EgoRisersRight' |
{ParGroup} 'FrontAll' |
{ParGroup} 'FontCorners' |
{ParGroup} 'FrontMiddle' |
{ParGroup} 'FrontInner' |
{ParGroup} 'FrontOuter' |
{ParGroup} 'FrontLeft1Inside' |
{ParGroup} 'FrontLeft2' |
{ParGroup} 'FrontLeft3' |
{ParGroup} 'FrontLeft4Outside' |
{ParGroup} 'FrontLeftAll' |
{ParGroup} 'FrontLeftInner' |
{ParGroup} 'FrontLeftOuter' |
{ParGroup} 'BannerAll' |
{ParGroup} 'BannerLeft' |
{ParGroup} 'BannerRight' |
{ParGroup} 'FrontRight1Inside' |
{ParGroup} 'FrontRight2' |
{ParGroup} 'FrontRight3' |
{ParGroup} 'FrontRight4Outside' |
{ParGroup} 'FrontRightAll' |
{ParGroup} 'FrontRightInner' |
{ParGroup} 'FrontRightOuter');
DmxSubCommands:
{DmxSubCommands}
(mode=DmxModeSubCommand)?
(preset=DmxPresetSubCommand)?
(delayTime=DmxDelayTimeSubCommand)?
(strobeTime=DmxStrobeTimeSubCommand)?
(stepNumber=DmxStepNumberSubCommand)?
(hold=DmxHoldSubCommand)?
(once=DmxOnceSubCommand)?
(DefaultColor=DmxDefaultColorSubCommand)?
(AlternateColor=DmxAlternateColorSubCommand)?;
DmxModeSubCommand:
'Mode' DmxModeSubCommandData;
DmxModeSubCommandData:
type=('trigger' | 'loop' | 'once' | 'restart');
DmxPresetSubCommand:
'Preset' DmxPresetSubCommandData;
DmxPresetSubCommandData:
presetName= 'def2alt' |
{DmxPresetSubCommandData} 'alt2def' |
{DmxPresetSubCommandData} 'switch_def_alt' |
{DmxPresetSubCommandData} 'def2act' |
{DmxPresetSubCommandData} 'actual2def' |
{DmxPresetSubCommandData} 'switch_def_actual' |
{DmxPresetSubCommandData} 'alt2actual' |
{DmxPresetSubCommandData} 'actual2alt' |
{DmxPresetSubCommandData} 'switch_alt_actual' |
{DmxPresetSubCommandData} 'solid' |
{DmxPresetSubCommandData} 'dual_colors_def_alt' |
{DmxPresetSubCommandData} 'dual_colors_alt_def' |
{DmxPresetSubCommandData} 'chase_left2right' |
{DmxPresetSubCommandData} 'chase_right2left' |
{DmxPresetSubCommandData} 'switch_left_right_left' |
{DmxPresetSubCommandData} 'switch_right_left_right' |
{DmxPresetSubCommandData} 'fade_alt2def' |
{DmxPresetSubCommandData} 'fade_def2alt' |
{DmxPresetSubCommandData} 'fade_def_alt_def' |
{DmxPresetSubCommandData} 'fade_alt_def_alt' |
{DmxPresetSubCommandData} 'fade_chase_left2right' |
{DmxPresetSubCommandData} 'fade_chase_right2left' |
{DmxPresetSubCommandData} 'fade_chase_left_right_left' |
{DmxPresetSubCommandData} 'fade_chase_right_left_right' |
{DmxPresetSubCommandData} 'rainbow_no_fade_left2right' |
{DmxPresetSubCommandData} 'rainbow_no_fade_right2left' |
{DmxPresetSubCommandData} 'rainbow_fade_left2right' |
{DmxPresetSubCommandData} 'rainbow_fade_right2left';
DmxDelayTimeSubCommand:
'DelayTime' time=Time;
DmxStrobeTimeSubCommand:
'StrobeTime' time=Time;
DmxStepNumberSubCommand:
'StepNumber' (last='Last' | value=INT);
DmxHoldSubCommand:
'Hold' onOff=ON_OFF;
DmxOnceSubCommand:
'Once' onOff=ON_OFF;
DmxDefaultColorSubCommand:
'DefaultColor' color=DmxColor;
DmxAlternateColorSubCommand:
'AlternateColor' color=DmxColor;
DmxColor:
ShortDmxColor | LongDmxColor;
ShortDmxColor:
{ShortDmxColor} (intensity='I')? (red='R')? (green='G')? (blue='B')? (white='W')?;
LongDmxColor:
intensity=DMX_VALUE red=DMX_VALUE green=DMX_VALUE blue=DMX_VALUE (white=DMX_VALUE)?;
// Terminals
terminal MIDI_VALUE:
('1' '2' '0'..'7') |
('1' '0'..'1' '0'..'9') |
( '1'..'9' '0'..'9') |
( '0'..'9');
terminal DMX_VALUE:
('2' '5' '0'..'5') |
('2' '0'..'4' '0'..'9') |
('1' '0'..'9' '0'..'9') |
( '1'..'9' '0'..'9') |
( '0'..'9');
terminal MIDI_CHANNEL:
('1' '0'..'6') |
( '0'..'9');
terminal MIDI_NOTE:
('C' | 'D' | 'E' | 'F' | 'G' | 'A' | 'B')
('b' | '#')
('0'..'9') | ('1' '0'..'1');
terminal ON_OFF:
('ON' | 'OFF');
the rules MIDI_VALUE
and DMX_VALUE
and MIDI_CHANNEL
overlap with each other.
possible solutions
INT
+ validator (for all of them)MIDI_CHANNEL: INT
(no terminal keyword) + a valueconverterMIDI_CHANNEL: TERMINAL1|TERMINAL2| ....