我正在尝试为照明控制系统创建语法,并且在使用 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
;
我已经取得了一定程度的成功,能够覆盖 AddRangeSource 的监听器,因为我可以遍历并添加正确的类型,但是当我尝试删除一个范围时,一切都崩溃了。
1 > 50 - 30 > 35 @ 50
这会产生一个问题,因为删除的范围与“addRangeSource”相匹配。
我很确定我遗漏了一些明显的东西,我一直在努力阅读我在亚马逊上购买的这本书,但我的脑海中仍然没有弄清楚如何实现我所追求的东西,我已经看了这个一周了。
为了更好地衡量,下面是一个更高级的查询树,除了选择之外似乎还不错。
有人对我哪里出错有任何指示/建议吗?
干杯, 迈克
最佳答案
你可以通过稍微重组语法来解决这个问题:
将
rangeSource
与sourceRange
合并: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;
添加匹配
singleSource
或rangeSource
的source
规则:source : singleSource | rangeSource;
将
+
和-
放在同一级别(如addSource
和removeSource
):addSource : plus source; removeSource : minus source;
更改
sourceList
以接受addSource
/removeSource
列表:sourceList : source (addSource|removeSource)*;
我试过了,它在解析更高级的查询时没有任何问题。
关于c# - 用于删除选择的 ANTLR4 语法集成复杂性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53106950/