Xtext/ANTLR: 如何解决这个错误?以下令牌定义永远无法匹配...?
Xtext/ANTLR: How to fix this error? The following token definition can never be matched prior...?
我做了一个语法,编辑器没有显示任何错误,当我select 'Generate XText Artifacts',我得到以下错误:
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 仅在以下片段中使用:
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);
在每个规则的开头(除了 MidiChannel' 有一个关键字 ('Time', 'Note', 'CC', 'Aftertouch', 'PrgCh',所以我希望以下规则都是独一无二的。
而MIDI_CHANNEL的定义是:
terminal MIDI_CHANNEL:
('1' '0'..'6') |
( '0'..'9');
我该如何解决这个错误?
完整语法如下:
我做过的测试
将规则更改为不同的名称并写出数字:
航站楼 MIDI_CHANNEL_NUMBER:
('1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | ' 13' | '14' | '15' | '16');
结果:相同的错误但名称不同 (MIDI_CHANNEL_NUMBER)
删除了对 MIDI_CHANNEL_NUMBER 的引用(因此从不使用该规则):
结果:错误仍然存在。我没想到这个,因为它无处使用。
从列表中删除数字 10 到 16
结果:错误仍然存在。
删除(和)
结果:错误仍然存在。
将值更改为 'x' 和 'y'
结果:错误消失。但我不想要值 x 和 y,而是 1 到 16。
完整语法
// 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');
规则MIDI_VALUE
和DMX_VALUE
和MIDI_CHANNEL
相互重叠。
可能的解决方案
- 使用
INT
+ 验证器(对所有这些)
- 使用像
MIDI_CHANNEL: INT
这样的数据类型规则(无终端关键字)+ 值转换器
- 使用不重叠的终端规则和数据类型规则
MIDI_CHANNEL: TERMINAL1|TERMINAL2| ....
我做了一个语法,编辑器没有显示任何错误,当我select 'Generate XText Artifacts',我得到以下错误:
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 仅在以下片段中使用:
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);
在每个规则的开头(除了 MidiChannel' 有一个关键字 ('Time', 'Note', 'CC', 'Aftertouch', 'PrgCh',所以我希望以下规则都是独一无二的。
而MIDI_CHANNEL的定义是:
terminal MIDI_CHANNEL:
('1' '0'..'6') |
( '0'..'9');
我该如何解决这个错误?
完整语法如下:
我做过的测试
将规则更改为不同的名称并写出数字:
航站楼 MIDI_CHANNEL_NUMBER: ('1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | ' 13' | '14' | '15' | '16');
结果:相同的错误但名称不同 (MIDI_CHANNEL_NUMBER)
删除了对 MIDI_CHANNEL_NUMBER 的引用(因此从不使用该规则):
结果:错误仍然存在。我没想到这个,因为它无处使用。
从列表中删除数字 10 到 16
结果:错误仍然存在。
删除(和)
结果:错误仍然存在。
将值更改为 'x' 和 'y'
结果:错误消失。但我不想要值 x 和 y,而是 1 到 16。
完整语法
// 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');
规则MIDI_VALUE
和DMX_VALUE
和MIDI_CHANNEL
相互重叠。
可能的解决方案
- 使用
INT
+ 验证器(对所有这些) - 使用像
MIDI_CHANNEL: INT
这样的数据类型规则(无终端关键字)+ 值转换器 - 使用不重叠的终端规则和数据类型规则
MIDI_CHANNEL: TERMINAL1|TERMINAL2| ....