c# - 用于删除选择的 ANTLR4 语法集成复杂性

标签 c# tree antlr antlr4 ll

我正在尝试为照明控制系统创建语法,并且在使用 tree gui 工具进行测试时取得了良好的进展,但当我尝试将其实现到我的应用程序中时,一切似乎都崩溃了。

语言的基本结构是[Source] [Mask] [Command] [Destination] . Mask 是可选的,因此 super 简单的示例输入可能如下所示:Fixture 1 @ 50 绕过 Mask。灯具 1 是源,@ 是命令,50 是目标,在本例中是强度值。

我对这种类型的输入没有任何问题,但随着我尝试构建更复杂的源选择,事情变得复杂了。假设我想选择一系列灯具并从选择中删除一些灯具,然后再添加更多灯具。

灯具 1 至 50 – 25 – 30 – 35 + 40 > 45 @ 50

这是现有控制系统上非常常见的语法,但我对如何以一种不会太痛苦地集成到我的应用程序中的方式为此设计语法感到困惑。

用户可以很容易地输入以下内容:

1 至 50 – 25 – 30 – 35 + 40 > 45 @ 50

因为没有提供 sourceType (fixture),所以它是推断的。

为了尝试处理上述情况,我编写了以下内容:

grammar LiteMic;

/*
 * Parser Rules
 */

start       : expression;

expression  : source command destination 
            | source mask command destination
            | command destination
            | source command; 

destination : sourceType number 
            | sourceType number sourceType number 
            | number;

command     : COMMAND;

mask        : SOURCETYPE;

operator    : ADD                                       #Add
            | SUB                                       #Subtract
            ;

plus : ADD;
minus : SUB;

source          : singleSource (plus source)*
                | rangeSource (plus source)*
                ;

singleSource    : sourceType number             #SourceWithType
                | number                        #InferedSource
                ;

rangeSource     : sourceRange (removeSource)*
                ;

sourceRange   : singleSource '>' singleSource;

removeSource     : '-' source;

sourceType      : SOURCETYPE;

number : NUMBER;


compileUnit
    :   EOF
    ;

/*
 * Lexer Rules
 */

SOURCETYPE      : 'Cue'
                | 'Playback' 
                | 'List'
                | 'Intensity'
                | 'Position'
                | 'Colour'
                | 'Beam'
                | 'Effect'
                | 'Group'
                | 'Fixture'
                ;


COMMAND     : '@' 
            | 'Record' 
            | 'Update' 
            | 'Copy' 
            | 'Move' 
            | 'Delete' 
            | 'Highlight' 
            | 'Full'
            ;

ADD         : '+'               ;       
SUB         : '-'               ;
THRU        : '>'               ;

/* A number: can be an integer value, or a decimal value */
NUMBER     : [0-9]+ ;

/* We're going to ignore all white space characters */
WS : [ \t\r\n]+ -> skip
   ;

针对 grun gui 运行命令会产生以下结果:enter image description here

我已经取得了一定程度的成功,能够覆盖 AddRangeSource 的监听器,因为我可以遍历并添加正确的类型,但是当我尝试删除一个范围时,一切都崩溃了。

1 > 50 - 30 > 35 @ 50

这会产生一个问题,因为删除的范围与“addRangeSource”相匹配。

enter image description here

我很确定我遗漏了一些明显的东西,我一直在努力阅读我在亚马逊上购买的这本书,但我的脑海中仍然没有弄清楚如何实现我所追求的东西,我已经看了这个一周了。

为了更好地衡量,下面是一个更高级的查询树,除了选择之外似乎还不错。 enter image description here

有人对我哪里出错有任何指示/建议吗?

干杯, 迈克

最佳答案

你可以通过稍微重组语法来解决这个问题:

  • rangeSourcesourceRange 合并:

    rangeSource : singleSource '>' singleSource;
    

    注意:此规则也匹配像 Beam 1 > Group 16 这样的输入,这可能是无意的,在这种情况下你可以使用这个:

    rangeSource : sourceType? number '>' number;
    
  • source 重命名为 sourceList(不要忘记在 expression 规则中更改它):

    expression : sourceList command destination 
               | sourceList mask command destination
               | command destination
               | sourceList command; 
    
  • 添加匹配 singleSourcerangeSourcesource 规则:

    source : singleSource | rangeSource;
    
  • +- 放在同一级别(如 addSourceremoveSource):

    addSource : plus source;
    removeSource : minus source;
    
  • 更改 sourceList 以接受 addSource/removeSource 列表:

    sourceList : source (addSource|removeSource)*;
    

我试过了,它在解析更高级的查询时没有任何问题。

关于c# - 用于删除选择的 ANTLR4 语法集成复杂性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53106950/

相关文章:

c# - 从 Installer 类获取当前 msi 安装文件的名称

tree - Visual Studio代码侧边栏垂直引导线(自定义侧边栏)

java - antlr:生成的 Lexer 源中缺少包声明

c# - DotNetZip 密码错误特殊字符

C# WinForms : Make CheckBox look like a RadioButton

c# - 如何在 MSI 安装程序中包含 pdb 文件以与应用程序的其余部分一起部署?

search - 在Elasticsearch中存储任意长度的分层数据的最佳方法

Python Tkinter : Tree selection

parsing - Xtext和ANTLR之间有什么关系?

python - 两个基本的 ANTLR 问题