我目前正在使用antlr4创建一个编译器,它应该允许解析java代码。
我如何允许:
public void =(Integer value) => java { this.value = value; }
java { }之间的代码没有被antlr解析,但在我的解析器中应该有一个访问者。
目前我有
javaStatementBody: KWJAVA LCURLY .*? RCURLY
但这显然不起作用,.*?解析整个文件。
请不要用“使用引号”回答,这不是我的解决方案,因为我想允许 java 代码突出显示。
最佳答案
您可以创建单独的词法分析器和解析器语法,以便可以使用 lexical modes 。每当词法分析器“看到”输入 java {
时,它就会移动到 JAVA_MODE
。在 Java 模式下,您可以对注释、字符串和字 rune 字进行标记。此外,在此模式下,您遇到 {
,您会推送相同的 JAVA_MODE
,以便词法分析器知道它嵌套了一次。当您遇到 }
时,您会从堆栈中弹出一个模式(导致返回到默认模式,或保持在 Java 模式但深度较低一层)。
快速演示:
IslandLexer.g4
lexer grammar IslandLexer;
JAVA_START
: 'java' SPACES '{' -> pushMode(JAVA_MODE)
;
OTHER
: .
;
fragment SPACES : [ \t\r\n]+;
mode JAVA_MODE;
JAVA_CHAR : '\'' ( ~[\\'\r\n] | '\\' [tbnrf'\\] ) '\'';
JAVA_STRING : '"' ( ~[\\"\r\n] | '\\' [tbnrf"\\] )* '"';
JAVA_LINE_COMMENT : '//' ~[\r\n]*;
JAVA_BLOCK_COMMENT : '/*' .*? '*/';
JAVA_OPEN_BRACE : '{' -> pushMode(JAVA_MODE);
JAVA_CLOSE_BRACE : '}' -> popMode;
JAVA_OTHER : ~[{}];
IslandParser.g4
parser grammar IslandParser;
options { tokenVocab=IslandLexer; }
parse
: unit* EOF
;
unit
: base_language
| java_janguage
;
base_language
: OTHER+
;
java_janguage
: JAVA_START java_atom+
;
java_atom
: JAVA_CHAR
| JAVA_STRING
| JAVA_LINE_COMMENT
| JAVA_BLOCK_COMMENT
| JAVA_OPEN_BRACE
| JAVA_CLOSE_BRACE
| JAVA_OTHER
;
使用以下代码进行测试:
String source = "foo \n" +
"\n" +
"java { \n" +
" char foo() { \n" +
" /* a quote in a comment \\\" */ \n" +
" String s = \"java {...}\"; \n" +
" return '}'; \n" +
" }\n" +
"}\n" +
"\n" +
"bar";
IslandLexer lexer = new IslandLexer(CharStreams.fromString(source));
IslandParser parser = new IslandParser(new CommonTokenStream(lexer));
System.out.println(parser.parse().toStringTree(parser));
这是以下解析树:
关于java - 如何让词法分析器解析java中的特定代码部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63260964/