Antlr4 在解析器中重新定义令牌类型
需要为COS aka实现语法突出显示Antlr4 在解析器中重新定义令牌类型,antlr4,Antlr4,需要为COS aka实现语法突出显示 对于语言的一种可能的形式设计 new (new,set,kill) set kill=new 其中:“new”和“set”是命令,也是变量 grammar cos; Command_KILL :( ('k'|'K') | ( ('k'|'K')('i'|'I')('l'|'L')('l'|'L') ) ); Command_NEW :( ('n'|'N') | ( ('n'|'N')('e'|'E')('w
对于语言的一种可能的形式设计
new (new,set,kill)
set kill=new
其中:“new”和“set”是命令,也是变量
grammar cos;
Command_KILL :( ('k'|'K') | ( ('k'|'K')('i'|'I')('l'|'L')('l'|'L') ) );
Command_NEW :( ('n'|'N') | ( ('n'|'N')('e'|'E')('w'|'W') ) );
Command_SET :( ('s'|'S') | ( ('s'|'S')('e'|'E')('t'|'T') ) );
INT : [0-9]+;
ID : [a-zA-Z][a-zA-Z0-9]*;
Space: ' ';
Equal: '=';
newCommand
: Command_NEW Space ID
;
setCommand
: Command_SET Space ID Space* Equal Space* INT
;
我有一个问题,当我想把名字作为命令时(新建,设置e.t.c.)根据维基百科页面,腮腺炎没有保留词: 保留字:无。因为腮腺炎是根据上下文解释源代码的,所以不需要保留字。您可以使用语言命令的名称作为变量 类似于
Command\u KILL
的Lexer规则的功能与保留字完全相同:它们被设计为确保在遇到输入“KILL”
时不会生成其他令牌。因此,令牌类型命令\u KILL
将始终在的“KILL”
上生成,即使它是一个标识符。如果需要,您可以保留命令lexer规则,但是您也必须将它们视为id,因为您不知道仅基于令牌的“kill”
指的是什么
在ANTLR中实现腮腺炎意味着关注令牌使用和上下文,而不是令牌类型。考虑这一语法:
grammar Example;
document : (expr (EOL|EOF))+;
expr : command=ID Space+ value (Space* COMMA Space* value)* #CallExpr
| command=ID Space+ name=ID Space* Equal Space* value #SetExpr
;
value : ID | INT;
INT : [0-9]+;
ID : [a-zA-Z][a-zA-Z0-9]*;
Space : ' ';
Equal : '=';
EOL : [\r\n]+;
COMMA : ',';
解析器规则expr
知道ID
标记何时是基于整行布局的命令
- 如果输入标记是
,则输入是ID ID
:第一个CallExpr
是命令名,第二个ID
是常规标识符李>ID
- 如果输入标记是
,则输入是ID-ID-Equal-ID
:第一个SetExpr
将是一个命令(或者ID
或者类似的东西),第二个“set”
是目标标识符,第三个ID
是源标识符ID
import java.util.List;
导入org.antlr.v4.runtime.antlInputStream;
导入org.antlr.v4.runtime.CommonTokenStream;
公共类示例测试{
公共静态void main(字符串[]args){
AntlInputStream输入=新的AntlInputStream(
“新建、设置、终止\n设置终止=新建”);
ExampleLexer lexer=新的ExampleLexer(输入);
ExampleParser=newexampleparser(newcommontokenstream(lexer));
addParseListener(新示例BaseListener(){
@凌驾
public void exitCallExpr(ExampleParser.CallExprContext ctx){
System.out.println(“调用:”);
System.out.printf(“\t命令=%s%n”,ctx.command.getText());
列表值=ctx.value();
如果(值!=null){
对于(int i=0,count=values.size();i
输入
输出
由调用代码确定命令在给定上下文中是否有效。解析器无法合理地处理这一问题,因为腮腺炎对命令和标识符的处理过于松散。但这并不像听起来那么糟糕:您将知道哪些命令的功能类似于调用,哪些命令的功能类似于集合,因此您将能够测试ANTLR生成的侦听器的输入。例如,在上面的代码中,很容易测试“set”是否是传递给exitsetxpr
的命令
一些腮腺炎语法可能比这更难处理,但一般的方法是一样的:让lexer处理命令和标识符,如ID
s,并使用解析器规则根据整行的上下文确定ID
是指命令还是指标识符。稍微偏离主题,由于ANTLR 4支持字符类表示法,[…]
,因此不敏感地匹配k
大小写将更容易,就像[kK]
而不是('k'|'k')
。
new new, set, kill
set kill = new
Call:
command = new
arg[0] = new
arg[1] = set
arg[2] = kill
Set:
command = set
name = kill
value = new