ANTLR3:没有可行的替代品
ANTLR3: No viable alternative at character
我有这个 ANTLR3 语法:
grammar wft;
@header {
package com.mycompany.wftdiff.parser;
import com.mycompany.wftdiff.model.*;
}
@lexer::header {
package com.mycompany.wftdiff.parser;
}
@members {
private final WftFile wftFile = new WftFile();
public WftFile getParsingResult() {
return wftFile;
}
}
wftFile:
{
System.out.println("Heyo!");
}
(CommentLine | assignment | NewLine)*
itemTypeDefinition
EOF
;
/**
* ItemTypeDefinition
* DEFINE ITEM_TYPE
* END ITEM_TYPE
*/
itemTypeDefinition:
'DEFINE ITEM_TYPE' NewLine
(KeyName|TransStmt|BaseStmt|NewLine)+
WhiteSpace* 'DEFINE ITEM_ATTRIBUTE' NewLine
(KeyName|TransStmt|BaseStmt)*
WhiteSpace* 'END ITEM_ATTRIBUTE' NewLine
'END ITEM_TYPE'
;
/**
* KeyName
* KEY NAME VARCHAR2(8)
*/
KeyName: WhiteSpace* KeyNameStart .* {$channel = HIDDEN;} NewLine;
fragment KeyNameStart: 'KEY NAME VARCHAR2(';
/**
* TransStmt
* TRANS DISPLAY_NAME VARCHAR2(80)
*/
TransStmt: WhiteSpace* TransStmtStart .* {$channel = HIDDEN;} NewLine;
fragment TransStmtStart: 'TRANS';
/**
* BaseStmt
BASE PROTECT_LEVEL NUMBER
*/
BaseStmt: WhiteSpace* BaseStmtStart .* {$channel = HIDDEN;} NewLine;
fragment BaseStmtStart: 'BASE';
/**
* Assignment
*/
assignment returns [Assignment assignment]:
{
System.out.println("Assignment found!");
}
target=AssignmentTarget
WhiteSpace '=' WhiteSpace
value=String {
assignment = new Assignment(target.getText(), value.getText());
wftFile.addAssignment(new Assignment(target.getText(), value.getText()));
}
NewLine;
AssignmentTarget: A (A|D|'_')*;
String: '"' ~'"'* '"'
;
/**
* Comment
*/
CommentLine: CommentStart .* {$channel = HIDDEN;} NewLine;
fragment CommentStart: '#';
// Lexer rules
fragment D: '0'..'9';
fragment A: 'A'..'Z'
| 'a'..'z';
StringLength: D+;
NewLine : '\r' '\n' | '\n' | '\r';
WhiteSpace: ' ';
然后我使用
为它生成一个解析器
java -cp "D:\wftdiff\lib\antlr-3.5.2\antlr-3.5.2-complete.jar" org.antlr.Tool -o src/com/mycompany/wftdiff/parser/ grammar-src/wft.g
...并这样称呼它:
val lexer = wftLexer(ANTLRFileStream(fileName))
val parser = wftParser(CommonTokenStream(lexer))
parser.wftFile()
System.out.println("Test")
fileName
指向一个包含以下内容的文本文件:
# Oracle Workflow Process Definition
# $Header$
VERSION_MAJOR = "2"
VERSION_MINOR = "6"
LANGUAGE = "GERMAN"
ACCESS_LEVEL = "100"
DEFINE ITEM_TYPE
KEY NAME VARCHAR2(8)
TRANS DISPLAY_NAME VARCHAR2(80)
TRANS DESCRIPTION VARCHAR2(240)
BASE PROTECT_LEVEL NUMBER
BASE CUSTOM_LEVEL NUMBER
BASE WF_SELECTOR VARCHAR2(240)
BASE READ_ROLE REFERENCES ROLE
BASE WRITE_ROLE REFERENCES ROLE
BASE EXECUTE_ROLE REFERENCES ROLE
BASE PERSISTENCE_TYPE VARCHAR2(8)
BASE PERSISTENCE_DAYS NUMBER
DEFINE ITEM_ATTRIBUTE
KEY NAME VARCHAR2(30)
TRANS DISPLAY_NAME VARCHAR2(80)
TRANS DESCRIPTION VARCHAR2(240)
BASE PROTECT_LEVEL NUMBER
BASE CUSTOM_LEVEL NUMBER
BASE TYPE VARCHAR2(8)
BASE FORMAT VARCHAR2(240)
BASE VALUE_TYPE VARCHAR2(8)
BASE DEFAULT VARCHAR2(4000)
END ITEM_ATTRIBUTE
END ITEM_TYPE
我得到以下输出:
Heyo!
Assignment found!
Assignment found!
Assignment found!
Assignment found!
test-data/partialSample01.wft line 25:2 no viable alternative at character 'D'
test-data/partialSample01.wft line 35:2 no viable alternative at character 'E'
Test
我应该如何更改语法以消除 no viable alternative at character 'D'
错误?
请注意,我不需要解析文件的这一部分(我对这个特定信息不感兴趣;它位于文件的后面)。
更新 1: 试图按照建议 here(使用 skip()
)忽略整个事情,但没有帮助。
新语法文件:
grammar wft;
@header {
package com.mycompany.wftdiff.parser;
import com.mycompany.wftdiff.model.*;
}
@lexer::header {
package com.mycompany.wftdiff.parser;
}
@members {
private final WftFile wftFile = new WftFile();
public WftFile getParsingResult() {
return wftFile;
}
}
wftFile:
{
System.out.println("Heyo!");
}
(CommentLine | assignment | NewLine)*
itemTypeDefinition
EOF
;
/**
* ItemTypeDefinition
* DEFINE ITEM_TYPE
* END ITEM_TYPE
*/
itemTypeDefinition:
'DEFINE ITEM_TYPE' NewLine
(KeyName|TransStmt|BaseStmt|NewLine)+
WhiteSpace*
NewLine
DefineItemAttribute
WhiteSpace*
'END ITEM_TYPE'
;
DefineItemAttribute: 'DEFINE ITEM_ATTRIBUTE' .* 'END ITEM_ATTRIBUTE' {skip();};
/**
* KeyName
* KEY NAME VARCHAR2(8)
*/
KeyName: WhiteSpace* KeyNameStart .* {$channel = HIDDEN;} NewLine;
fragment KeyNameStart: 'KEY NAME VARCHAR2(';
/**
* TransStmt
* TRANS DISPLAY_NAME VARCHAR2(80)
*/
TransStmt: WhiteSpace* TransStmtStart .* {$channel = HIDDEN;} NewLine;
fragment TransStmtStart: 'TRANS';
/**
* BaseStmt
BASE PROTECT_LEVEL NUMBER
*/
BaseStmt: WhiteSpace* BaseStmtStart .* {$channel = HIDDEN;} NewLine;
fragment BaseStmtStart: 'BASE';
/**
* Assignment
*/
assignment returns [Assignment assignment]:
{
System.out.println("Assignment found!");
}
target=AssignmentTarget
WhiteSpace '=' WhiteSpace
value=String {
assignment = new Assignment(target.getText(), value.getText());
wftFile.addAssignment(new Assignment(target.getText(), value.getText()));
}
NewLine;
AssignmentTarget: A (A|D|'_')*;
String: '"' ~'"'* '"'
;
/**
* Comment
*/
CommentLine: CommentStart .* {$channel = HIDDEN;} NewLine;
fragment CommentStart: '#';
// Lexer rules
fragment D: '0'..'9';
fragment A: 'A'..'Z'
| 'a'..'z';
StringLength: D+;
NewLine : '\r' '\n' | '\n' | '\r';
WhiteSpace: ' ';
解析结果:
Heyo!
Assignment found!
Assignment found!
Assignment found!
Assignment found!
test-data/partialSample01.wft line 25:2 no viable alternative at character 'D'
test-data/partialSample01.wft line 36:0 missing DefineItemAttribute at 'END ITEM_TYPE'
Test
赏金条款
我会将赏金奖励给完成以下英雄事迹的人:
- 创建一个解析器,能够识别 this file 的所有部分,这些部分在评论中被标记为相关,即
1.1。 BEGIN ACTIVITY
和 END ACTIVITY
标签内的所有内容,
1.2. BEGIN ACTIVITY_TRANSITION
和 END ACTIVITY_TRANSITION
中的所有内容,
1.3. BEGIN PROCESS_ACTIVITY
和 BEGIN PROCESS_ACTIVITY
标签内的所有内容。
"recognize everything" 我的意思是必须有 ANTLR 3 代码,它允许我放置 Java 语句来处理从文件中提取的数据,就像在 assignment
规则中一样原来post。您不需要在那里编写任何 Java 代码,但我必须可以稍后添加该代码。
解析器可以忽略所有未标记为相关的部分(类似于原始语法中的注释)。
您的语法必须与 ANTLR 3、Java 8 和 Windows 7 兼容。
您可以删除原始版本中的代码(如here),这样就不会出现编译错误。
解析器必须能够使用 java -cp "D:\wftdiff\lib\antlr-3.5.2\antlr-3.5.2-complete.jar" org.antlr.Tool -o src/com/mycompany/wftdiff/parser/ grammar-src/wft.g
生成,或者,如果您使用任何特殊设置,则需要在答案中指定它们。关键是,我需要能够重现你的结果。
当我将 sample file 提供给解析器时,它必须毫无怨言地使用它(不打印任何 ANTLR 错误消息,不崩溃,也不抛出像 NullPointerException 这样的技术异常)。
这是语法。它识别所有部分,您可以在任何地方添加 java 动作。
使用 jdk1.8、antlr 3.5.2 和提供的示例输入进行编译和测试。
grammar wft;
@header {
package com.mycompany.wftdiff.parser;
}
@lexer::header {
package com.mycompany.wftdiff.parser;
}
@members {
}
wftFile : (COMMENT|assignment|definition|flow)*
;
assignment
: ID EQ STRING
;
definition
: 'DEFINE' ID
(COMMENT | (dclass ID type) | definition)*
'END' ID
;
dclass : 'KEY' | 'BASE' | 'TRANS'
;
type : tnum | tvarchar | tref | tdate
;
tnum : 'NUMBER'
;
tvarchar: 'VARCHAR2' '(' INT ')'
;
tref : 'REFERENCES' ID
;
tdate : 'DATE'
;
flow : 'BEGIN' ID (STRING)+
(COMMENT|assignment|flow)+
'END' ID
;
EQ : '='
;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;
NL : '\r'? '\n' {$channel=HIDDEN;}
;
COMMENT
: '#' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
;
WS : ( ' '
| '\t'
) {$channel=HIDDEN;}
;
STRING
: '"' ( ESC_SEQ | ~('\'|'"') )* '"'
;
fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
fragment
ESC_SEQ
: '\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\')
| UNICODE_ESC
| OCTAL_ESC
;
fragment
OCTAL_ESC
: '\' ('0'..'3') ('0'..'7') ('0'..'7')
| '\' ('0'..'7') ('0'..'7')
| '\' ('0'..'7')
;
fragment
UNICODE_ESC
: '\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
;
INT : '0'..'9'+
;
我有这个 ANTLR3 语法:
grammar wft;
@header {
package com.mycompany.wftdiff.parser;
import com.mycompany.wftdiff.model.*;
}
@lexer::header {
package com.mycompany.wftdiff.parser;
}
@members {
private final WftFile wftFile = new WftFile();
public WftFile getParsingResult() {
return wftFile;
}
}
wftFile:
{
System.out.println("Heyo!");
}
(CommentLine | assignment | NewLine)*
itemTypeDefinition
EOF
;
/**
* ItemTypeDefinition
* DEFINE ITEM_TYPE
* END ITEM_TYPE
*/
itemTypeDefinition:
'DEFINE ITEM_TYPE' NewLine
(KeyName|TransStmt|BaseStmt|NewLine)+
WhiteSpace* 'DEFINE ITEM_ATTRIBUTE' NewLine
(KeyName|TransStmt|BaseStmt)*
WhiteSpace* 'END ITEM_ATTRIBUTE' NewLine
'END ITEM_TYPE'
;
/**
* KeyName
* KEY NAME VARCHAR2(8)
*/
KeyName: WhiteSpace* KeyNameStart .* {$channel = HIDDEN;} NewLine;
fragment KeyNameStart: 'KEY NAME VARCHAR2(';
/**
* TransStmt
* TRANS DISPLAY_NAME VARCHAR2(80)
*/
TransStmt: WhiteSpace* TransStmtStart .* {$channel = HIDDEN;} NewLine;
fragment TransStmtStart: 'TRANS';
/**
* BaseStmt
BASE PROTECT_LEVEL NUMBER
*/
BaseStmt: WhiteSpace* BaseStmtStart .* {$channel = HIDDEN;} NewLine;
fragment BaseStmtStart: 'BASE';
/**
* Assignment
*/
assignment returns [Assignment assignment]:
{
System.out.println("Assignment found!");
}
target=AssignmentTarget
WhiteSpace '=' WhiteSpace
value=String {
assignment = new Assignment(target.getText(), value.getText());
wftFile.addAssignment(new Assignment(target.getText(), value.getText()));
}
NewLine;
AssignmentTarget: A (A|D|'_')*;
String: '"' ~'"'* '"'
;
/**
* Comment
*/
CommentLine: CommentStart .* {$channel = HIDDEN;} NewLine;
fragment CommentStart: '#';
// Lexer rules
fragment D: '0'..'9';
fragment A: 'A'..'Z'
| 'a'..'z';
StringLength: D+;
NewLine : '\r' '\n' | '\n' | '\r';
WhiteSpace: ' ';
然后我使用
为它生成一个解析器java -cp "D:\wftdiff\lib\antlr-3.5.2\antlr-3.5.2-complete.jar" org.antlr.Tool -o src/com/mycompany/wftdiff/parser/ grammar-src/wft.g
...并这样称呼它:
val lexer = wftLexer(ANTLRFileStream(fileName))
val parser = wftParser(CommonTokenStream(lexer))
parser.wftFile()
System.out.println("Test")
fileName
指向一个包含以下内容的文本文件:
# Oracle Workflow Process Definition
# $Header$
VERSION_MAJOR = "2"
VERSION_MINOR = "6"
LANGUAGE = "GERMAN"
ACCESS_LEVEL = "100"
DEFINE ITEM_TYPE
KEY NAME VARCHAR2(8)
TRANS DISPLAY_NAME VARCHAR2(80)
TRANS DESCRIPTION VARCHAR2(240)
BASE PROTECT_LEVEL NUMBER
BASE CUSTOM_LEVEL NUMBER
BASE WF_SELECTOR VARCHAR2(240)
BASE READ_ROLE REFERENCES ROLE
BASE WRITE_ROLE REFERENCES ROLE
BASE EXECUTE_ROLE REFERENCES ROLE
BASE PERSISTENCE_TYPE VARCHAR2(8)
BASE PERSISTENCE_DAYS NUMBER
DEFINE ITEM_ATTRIBUTE
KEY NAME VARCHAR2(30)
TRANS DISPLAY_NAME VARCHAR2(80)
TRANS DESCRIPTION VARCHAR2(240)
BASE PROTECT_LEVEL NUMBER
BASE CUSTOM_LEVEL NUMBER
BASE TYPE VARCHAR2(8)
BASE FORMAT VARCHAR2(240)
BASE VALUE_TYPE VARCHAR2(8)
BASE DEFAULT VARCHAR2(4000)
END ITEM_ATTRIBUTE
END ITEM_TYPE
我得到以下输出:
Heyo!
Assignment found!
Assignment found!
Assignment found!
Assignment found!
test-data/partialSample01.wft line 25:2 no viable alternative at character 'D'
test-data/partialSample01.wft line 35:2 no viable alternative at character 'E'
Test
我应该如何更改语法以消除 no viable alternative at character 'D'
错误?
请注意,我不需要解析文件的这一部分(我对这个特定信息不感兴趣;它位于文件的后面)。
更新 1: 试图按照建议 here(使用 skip()
)忽略整个事情,但没有帮助。
新语法文件:
grammar wft;
@header {
package com.mycompany.wftdiff.parser;
import com.mycompany.wftdiff.model.*;
}
@lexer::header {
package com.mycompany.wftdiff.parser;
}
@members {
private final WftFile wftFile = new WftFile();
public WftFile getParsingResult() {
return wftFile;
}
}
wftFile:
{
System.out.println("Heyo!");
}
(CommentLine | assignment | NewLine)*
itemTypeDefinition
EOF
;
/**
* ItemTypeDefinition
* DEFINE ITEM_TYPE
* END ITEM_TYPE
*/
itemTypeDefinition:
'DEFINE ITEM_TYPE' NewLine
(KeyName|TransStmt|BaseStmt|NewLine)+
WhiteSpace*
NewLine
DefineItemAttribute
WhiteSpace*
'END ITEM_TYPE'
;
DefineItemAttribute: 'DEFINE ITEM_ATTRIBUTE' .* 'END ITEM_ATTRIBUTE' {skip();};
/**
* KeyName
* KEY NAME VARCHAR2(8)
*/
KeyName: WhiteSpace* KeyNameStart .* {$channel = HIDDEN;} NewLine;
fragment KeyNameStart: 'KEY NAME VARCHAR2(';
/**
* TransStmt
* TRANS DISPLAY_NAME VARCHAR2(80)
*/
TransStmt: WhiteSpace* TransStmtStart .* {$channel = HIDDEN;} NewLine;
fragment TransStmtStart: 'TRANS';
/**
* BaseStmt
BASE PROTECT_LEVEL NUMBER
*/
BaseStmt: WhiteSpace* BaseStmtStart .* {$channel = HIDDEN;} NewLine;
fragment BaseStmtStart: 'BASE';
/**
* Assignment
*/
assignment returns [Assignment assignment]:
{
System.out.println("Assignment found!");
}
target=AssignmentTarget
WhiteSpace '=' WhiteSpace
value=String {
assignment = new Assignment(target.getText(), value.getText());
wftFile.addAssignment(new Assignment(target.getText(), value.getText()));
}
NewLine;
AssignmentTarget: A (A|D|'_')*;
String: '"' ~'"'* '"'
;
/**
* Comment
*/
CommentLine: CommentStart .* {$channel = HIDDEN;} NewLine;
fragment CommentStart: '#';
// Lexer rules
fragment D: '0'..'9';
fragment A: 'A'..'Z'
| 'a'..'z';
StringLength: D+;
NewLine : '\r' '\n' | '\n' | '\r';
WhiteSpace: ' ';
解析结果:
Heyo!
Assignment found!
Assignment found!
Assignment found!
Assignment found!
test-data/partialSample01.wft line 25:2 no viable alternative at character 'D'
test-data/partialSample01.wft line 36:0 missing DefineItemAttribute at 'END ITEM_TYPE'
Test
赏金条款
我会将赏金奖励给完成以下英雄事迹的人:
- 创建一个解析器,能够识别 this file 的所有部分,这些部分在评论中被标记为相关,即
1.1。 BEGIN ACTIVITY
和 END ACTIVITY
标签内的所有内容,
1.2. BEGIN ACTIVITY_TRANSITION
和 END ACTIVITY_TRANSITION
中的所有内容,
1.3. BEGIN PROCESS_ACTIVITY
和 BEGIN PROCESS_ACTIVITY
标签内的所有内容。
"recognize everything" 我的意思是必须有 ANTLR 3 代码,它允许我放置 Java 语句来处理从文件中提取的数据,就像在 assignment
规则中一样原来post。您不需要在那里编写任何 Java 代码,但我必须可以稍后添加该代码。
解析器可以忽略所有未标记为相关的部分(类似于原始语法中的注释)。
您的语法必须与 ANTLR 3、Java 8 和 Windows 7 兼容。
您可以删除原始版本中的代码(如here),这样就不会出现编译错误。
解析器必须能够使用
java -cp "D:\wftdiff\lib\antlr-3.5.2\antlr-3.5.2-complete.jar" org.antlr.Tool -o src/com/mycompany/wftdiff/parser/ grammar-src/wft.g
生成,或者,如果您使用任何特殊设置,则需要在答案中指定它们。关键是,我需要能够重现你的结果。当我将 sample file 提供给解析器时,它必须毫无怨言地使用它(不打印任何 ANTLR 错误消息,不崩溃,也不抛出像 NullPointerException 这样的技术异常)。
这是语法。它识别所有部分,您可以在任何地方添加 java 动作。
使用 jdk1.8、antlr 3.5.2 和提供的示例输入进行编译和测试。
grammar wft;
@header {
package com.mycompany.wftdiff.parser;
}
@lexer::header {
package com.mycompany.wftdiff.parser;
}
@members {
}
wftFile : (COMMENT|assignment|definition|flow)*
;
assignment
: ID EQ STRING
;
definition
: 'DEFINE' ID
(COMMENT | (dclass ID type) | definition)*
'END' ID
;
dclass : 'KEY' | 'BASE' | 'TRANS'
;
type : tnum | tvarchar | tref | tdate
;
tnum : 'NUMBER'
;
tvarchar: 'VARCHAR2' '(' INT ')'
;
tref : 'REFERENCES' ID
;
tdate : 'DATE'
;
flow : 'BEGIN' ID (STRING)+
(COMMENT|assignment|flow)+
'END' ID
;
EQ : '='
;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;
NL : '\r'? '\n' {$channel=HIDDEN;}
;
COMMENT
: '#' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
;
WS : ( ' '
| '\t'
) {$channel=HIDDEN;}
;
STRING
: '"' ( ESC_SEQ | ~('\'|'"') )* '"'
;
fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
fragment
ESC_SEQ
: '\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\')
| UNICODE_ESC
| OCTAL_ESC
;
fragment
OCTAL_ESC
: '\' ('0'..'3') ('0'..'7') ('0'..'7')
| '\' ('0'..'7') ('0'..'7')
| '\' ('0'..'7')
;
fragment
UNICODE_ESC
: '\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
;
INT : '0'..'9'+
;