我正在使用 ANTLR 来解析 scala 文件。
我在这里找到了 scala 语言的语法: https://github.com/antlr/grammars-v4/blob/master/scala/Scala.g4
借助 antlr4-maven-plugin,我从语法中生成了 ANTLR 类。
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.13.1</version>
<executions>
<execution>
<id>antlr-generate</id>
<phase>generate-sources</phase>
<goals>
<goal>antlr4</goal>
</goals>
</execution>
</executions>
<configuration>
<sourceDirectory>src/main/antlr4</sourceDirectory>
<outputDirectory>target/generated-sources/antlr4</outputDirectory>
<listener>true</listener>
<visitor>true</visitor>
</configuration>
</plugin>
我对运行时有依赖性:
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.13.1</version>
</dependency>
这是我解析 scala 文件的代码:
public class Main {
public static void main(String[] args) throws IOException {
Path filePath = Paths.get(args[0]);
CharStream charStream = CharStreams.fromPath(filePath , StandardCharsets.UTF_8);
ScalaLexer lexer = new ScalaLexer(charStream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ScalaParser parser = new ScalaParser(tokens);
ParseTree tree = parser.compilationUnit();
ParseTreeWalker.DEFAULT.walk(new ScalaBaseListener(), tree);
}
}
我使用这个 scala 文件 test.scala 作为输入:
object replace {
def process(node: Node): Seq[Node] = node match {
case <abc:name>{ value @ _* }</abc:name> => <abc:surname>{ value }</abc:surname>
case _ => node
}
}
stderr 表示它发现了意外字符,例如
:
中的 <abc:name>
。
line 3:13 extraneous input ':' expecting {'-', 'null', 'this', 'super', '(', '_', Id, BooleanLiteral, CharacterLiteral, SymbolLiteral, IntegerLiteral, StringLiteral, FloatingPointLiteral, Varid, NL}
line 3:19 extraneous input '{' expecting {'-', 'null', 'this', 'super', '(', '_', Id, BooleanLiteral, CharacterLiteral, SymbolLiteral, IntegerLiteral, StringLiteral, FloatingPointLiteral, Varid, NL}
line 3:27 mismatched input '@' expecting {'=>', 'if'}
line 3:30 extraneous input '*' expecting {'-', 'null', 'this', 'super', '(', '{', '}', 'type', 'val', '_', 'implicit', 'if', 'while', 'try', 'do', 'for', 'throw', 'return', '+', '~', '!', 'new', 'lazy', 'case', '@', 'var', 'override', 'abstract', 'final', 'sealed', 'private', 'protected', 'import', 'def', 'class', 'object', 'trait', Id, BooleanLiteral, CharacterLiteral, SymbolLiteral, IntegerLiteral, StringLiteral, FloatingPointLiteral}
scala 文件是正确的,它是我要解析的文件的简化版本,可以编译。
我需要在语法中修正什么?
语法似乎无法处理 XML 文字,因为以下代码已成功解析:
object replace {
def process(node: Node): Seq[Node] = node match {
case a => 1
case _ => node
}
}
但是,经过 Google 快速搜索后,似乎不再支持 CML 文字,而是被 XML 字符串插值取代。那么,回答你的问题:
我需要在语法中修正什么?
问题是:让词法分析器和解析器识别 XML 文本。一个快速修复方法是添加词法分析器规则:
XmlLiteral
: '<' ~[ \t\r\n<>]+ '>' (XmlLiteral | ~[<>])*? '</' ~[ \t\r\n<>]+ '>'
;
然后将
XmlLiteral
添加到 literal
解析器规则中:
literal
: '-'? IntegerLiteral
| '-'? FloatingPointLiteral
| BooleanLiteral
| CharacterLiteral
| StringLiteral
| SymbolLiteral
| 'null'
| XmlLiteral
;
然后您的示例输入就被正确解析了。
我说“快速修复”是因为这会导致 XML 文字被标记为单个标记,而不具有任何结构。为了将 XML 正确解析为树本身,需要对词法分析器和解析器语法进行更多更改。