Xtext/ANTLR:如何修复此错误?以下令牌定义在…之前永远无法匹配。。。?

Xtext/ANTLR:如何修复此错误?以下令牌定义在…之前永远无法匹配。。。?,antlr,grammar,dsl,xtext,model-driven-development,Antlr,Grammar,Dsl,Xtext,Model Driven Development,我制作了一个语法,编辑器没有显示任何错误,当我选择“生成XText工件”时,我得到以下错误: 错误(208):../mestra.dmxlightshow/src gen/mestra/parser/antlr/internal/InternalDmxLightShow.g:3668:1:无法匹配以下令牌定义,因为先前的令牌与相同的输入匹配:RULE_MIDI_CHANNEL 错误(208):../mestra.dmxlightshow.ide/src gen/mestra/ide/conten

我制作了一个语法,编辑器没有显示任何错误,当我选择“生成XText工件”时,我得到以下错误:

错误(208):../mestra.dmxlightshow/src gen/mestra/parser/antlr/internal/InternalDmxLightShow.g:3668:1:无法匹配以下令牌定义,因为先前的令牌与相同的输入匹配:RULE_MIDI_CHANNEL 错误(208):../mestra.dmxlightshow.ide/src gen/mestra/ide/contentassist/antlr/internal/internal dmxlightshow.g:10741:1:无法匹配以下令牌定义,因为先前的令牌匹配相同的输入:RULE\u MIDI\u CHANNEL

MIDI_通道/MIDI通道仅用于以下片段:

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_通道的定义为:

terminal MIDI_CHANNEL:
    ('1' '0'..'6') |
    (    '0'..'9');
如何修复此错误

完整语法如下:

我做的测试

  • 将规则更改为其他名称并写出数字:

    终端MIDI_通道编号: (“1”、“2”、“3”、“4”、“5”、“6”、“7”、“9”、“10”、“11”、“12”、“13”、“14”、“15”、“16”)

    结果:相同错误,名称不同(MIDI_频道编号)

  • 删除了对MIDI_频道编号的引用(因此从不使用该规则):

    结果:错误仍然存在。我没有预料到这一点,因为它没有在任何地方使用

  • 从列表中删除数字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\u值
    DMX\u值
    MIDI\u通道
    相互重叠

    可能的解决办法

  • 使用
    INT
    +验证器(适用于所有验证器)
  • 使用数据类型规则,如
    MIDI\u通道:INT
    (无终端关键字)+值转换器
  • 使用不重叠的终端规则和数据类型规则
    MIDI_通道:TERMINAL1 | TERMINAL2 |..

  • 啊,这似乎与我的另一个问题非常相关……我会检查(当我有时间时,明天或周五)