ANTLR4为逻辑通用行打破规则

  • 本文关键字:规则 ANTLR4 antlr antlr4
  • 更新时间 :
  • 英文 :


这个问题的后续问题Bart已经完美地回答了

我的目标可能是为"通用脚本行"one_answers";或"函数体内的行",理想情况下丢弃空白,但仍然可以批量获取<%%>标记之外的任何行。我想到了一个解决方案,但看着这棵树,它似乎很乱。

这是我的lexer:

lexer grammar CmScriptLexer;
//Whitespace:  Spaces -> channel(HIDDEN);
ScriptStart : '<%' (Spaces)* -> mode(Script);
SpacesPlain : [rn]+ -> skip;
GenericText : . ;
mode Script;
ScriptEnd  : '%>' -> mode(DEFAULT_MODE);
Comment    : ''' ~[rn]* -> skip;
Function   : 'function' -> mode(FunctionDeclaration);
NL : [rn]+;
ScriptText : . ;
mode FunctionDeclaration;
FunctionComment    : ''' ~[rn]* -> skip;
FunctionName      : Id;
DeclarationSpaces : Spaces+ -> skip;
OPar              : '(' -> mode(FunctionParameter);
mode FunctionParameter;
FunctionParameterComment    : ''' ~[rn]* -> skip;
ParameterName   : Id;
ParameterSpaces : Spaces+ -> skip;
Comma           : ',';
CPar            : ')' -> mode(InFunction);
mode InFunction;
FunctionBodyComment    : ''' ~[rn]* -> skip;
EndFunction    : 'end' Spaces 'function' -> mode(Script);
FunctionLine : ~[ rn]+;
FunctionSpaces : Spaces+;
//FunctionText   : . ;
fragment Spaces : [ rnt]+;
fragment Id     : [a-zA-Z0-9_u0080-ufffe]+;

和解析器:

parser grammar CmScriptParser;
options { tokenVocab=CmScriptLexer; }
file
: block* EOF
;
block
: plainText
| ScriptStart script* ScriptEnd
;
plainText
: GenericText+ NL*
;
script
: simpleScript NL*
| function NL*
;
simpleScript
: ScriptText+ 
;
function
: Function FunctionName OPar parameters? CPar functionBody EndFunction
;
functionBody
: functionLines+
;
functionLines
: FunctionSpaces* functionLine FunctionSpaces*
;
functionLine
: FunctionLine+
;
parameters
: ParameterName ( Comma ParameterName )*
;

最后是我用作测试用例的:

foo
bar
<%
line 1

line 2 

function x(y)
spanning
multiple
lines
end function
function a(b)    no newlines         end function

%>     
baz

我的问题是它看起来真的很冗长,我害怕我的"解决方案"。而测试用例只是布局不佳,我可能过度思考规则。

有什么改进的建议吗?我想要的只是修剪线条元素,因此匹配n nntscript line nntn之类的东西导致script line的行是理想的。

编辑:添加我认为是我所追求的一个例子,再一次,可能不是最好的表达方式:

simpleScript:
scriptLine: line1
scriptLine: line2
function: 
name: x
parameters:
paramter: y
body:
functionLine: spanning
functionLine: multiple
functionLine: lines
function: 
name: a
parameters:
paramter: b
body:
functionLine: no newlines
最后的目标是当遍历树时,我可以创建一个新的"函数调用对象",并调用像 这样的东西
script = new Script() // on script "enter"
script.addLine("line 1")
script.addLine("line 2")
program.addNode(script) // on script "exit"
...
function = new Function() // on function "enter"
function.setName("y") // on "function"?
...
function.addParameter("a") // on "parameter"
...
function.addBodyLine("spanning") // on "line" ??
function.addBodyLine("multiple")
function.addBodyLine("lines")
...
program.addFunctionDeclaration(function) // on function "exit" once complete

问题是,在脚本中,您不能简单地告诉语法匹配除换行符以外的所有非空格。当然,这将匹配line 1,但这也将匹配function x(y),因为词法分析器会贪婪地匹配(它试图消耗尽可能多的字符)。因此,您必须在空格上分割标记。

您可以使用~[ trn]+合并一些单个字符标记,但是您不能创建导致多个单词之间有空格作为单个标记匹配的标记。

像这样:

lexer grammar CmScriptLexer;
ScriptStart : '<%' Spaces* -> mode(Script);
GenericText : ~[ trn]+;
TextSpaces  : Spaces -> skip;
mode Script;
ScriptEnd   : '%>' -> mode(DEFAULT_MODE);
Comment     : ''' ~[rn]* -> skip;
Function    : 'function' -> mode(FunctionDeclaration);
NL          : [rn]+;
ScriptText  : ~[ trn]+;
SciptSpaces : Spaces -> skip;
mode FunctionDeclaration;
FunctionComment   : ''' ~[rn]* -> skip;
FunctionName      : Id;
DeclarationSpaces : Spaces+ -> skip;
OPar              : '(' -> mode(FunctionParameter);
mode FunctionParameter;
FunctionParameterComment : ''' ~[rn]* -> skip;
ParameterName            : Id;
ParameterSpaces          : Spaces+ -> skip;
Comma                    : ',';
CPar                     : ')' -> mode(InFunction);
mode InFunction;
FunctionBodyComment : ''' ~[rn]* -> skip;
EndFunction         : 'end' Spaces 'function' -> mode(Script);
FunctionLine        : ~[ trn]+;
FunctionSpaces      : Spaces+ -> skip;
fragment Spaces : [ rnt]+;
fragment Id     : [a-zA-Z0-9_u0080-ufffe]+;

相关内容

  • 没有找到相关文章

最新更新