ANTLR 4-输入不匹配
我正在尝试为我的一个项目使用ANTLR开发一个小型DSL。 因此我为lexer编写了定义ANTLR 4-输入不匹配,antlr,antlr4,Antlr,Antlr4,我正在尝试为我的一个项目使用ANTLR开发一个小型DSL。 因此我为lexer编写了定义 lexer grammar SpamkillerLexer; MAILBOX: 'Mailbox'; PASSWORD: 'Password'; HOST: 'Host'; USER: 'User'; FOLDER: 'Folder'; PORT: 'Port'; ACTIONS: 'Actions'; WHEN: 'When'; SUBJECT: 'Subject'; BODY: 'Body'; EQ
lexer grammar SpamkillerLexer;
MAILBOX: 'Mailbox';
PASSWORD: 'Password';
HOST: 'Host';
USER: 'User';
FOLDER: 'Folder';
PORT: 'Port';
ACTIONS: 'Actions';
WHEN: 'When';
SUBJECT: 'Subject';
BODY: 'Body';
EQUALS: 'Equals';
CONTAINS: 'Contains';
THEN: 'Then';
DELETE: 'Delete';
REDIRECT: 'Redirect';
TO: 'to';
BR_OP: '{';
BR_CL: '}';
EQ: '=';
STRING: '"' ( '\\"' | . )*? '"';
LITERAL: [a-zA-Z_0-9]+;
WS : [ \n\t\r]+ -> skip ;
…和解析器
parser grammar SpamkillerParser;
mailboxes: mailbox+;
mailbox: MAILBOX LITERAL BR_OP settings BR_CL;
settings: setting+;
setting: (key EQ STRING | ACTIONS EQ actions);
key: MAILBOX | PASSWORD | HOST | USER | FOLDER | PORT;
actions: BR_OP action* BR_CL;
action: WHEN condition THEN job;
condition: (SUBJECT | BODY) (EQUALS | CONTAINS) STRING;
job: (DELETE | (REDIRECT TO STRING));
我的测试文件如下所示:
Mailbox Foobar {
Port = "123"
Host = "foohost"
User = "foouser"
Password = "foopass"
Folder = "Inbox"
Actions = {
When Subject Equals "fooooo" Then Delete
When Body Contains "fooooo" Then Redirect to "foo@bar.baz"
}
}
String input = FileUtils.readFileToString(new File("test.txt"), Charsets.UTF_8);
CodePointCharStream inputStream = CharStreams.fromString(input);
SpamkillerLexer lexer = new SpamkillerLexer(inputStream);
CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
SpamkillerParser parser = new SpamkillerParser(commonTokenStream);
SpamkillerParser.MailboxesContext mailboxes = parser.mailboxes();
当我在ANTLR IntelliJ插件中测试邮箱时,它工作正常,我得到了相应的AST:
但是当我试图用编程的方式解析我的测试文件时,我得到了一个错误
line 1:8 mismatched input 'Foobar' expecting LITERAL
我试着重新排列我的lexer规则,但没有一次能帮我摆脱这个错误。有人知道如何解决这个问题吗
我解析文件的代码如下所示:
Mailbox Foobar {
Port = "123"
Host = "foohost"
User = "foouser"
Password = "foopass"
Folder = "Inbox"
Actions = {
When Subject Equals "fooooo" Then Delete
When Body Contains "fooooo" Then Redirect to "foo@bar.baz"
}
}
String input = FileUtils.readFileToString(new File("test.txt"), Charsets.UTF_8);
CodePointCharStream inputStream = CharStreams.fromString(input);
SpamkillerLexer lexer = new SpamkillerLexer(inputStream);
CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
SpamkillerParser parser = new SpamkillerParser(commonTokenStream);
SpamkillerParser.MailboxesContext mailboxes = parser.mailboxes();
您没有在解析器中指定必须使用哪个标记词汇表。因此,ANTLR为解析器创建隐式标记(实际上是简单的终端),而不是在lexer中使用标记 要解决此问题,请提供
tokenVocab
选项:
parser grammar SpamkillerParser;
options {
tokenVocab=SpamkillerLexer;
}
mailboxes: mailbox+;
mailbox: MAILBOX LITERAL BR_OP settings BR_CL;
settings: setting+;
setting: (key EQ STRING | ACTIONS EQ actions);
key: MAILBOX | PASSWORD | HOST | USER | FOLDER | PORT;
actions: BR_OP action* BR_CL;
action: WHEN condition THEN job;
condition: (SUBJECT | BODY) (EQUALS | CONTAINS) STRING;
job: (DELETE | (REDIRECT TO STRING));
这解决了我的问题:)非常感谢!