我正在使用ANTLR解析scala文件.

我在这里找到了scala langage的语法: 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 extends RewriteRule {
  def transform(node: Node): Seq[Node] = node match {
    case <abc:name>{ value @ _* }</abc:name> => <abc:surname>{ value }</abc:surname>
    case _ => node
  }
}

然而,添加了override个关键字的输入失败:

object replace extends RewriteRule {
  override def transform(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文字,因为以下代码is成功解析:

object replace {
  def process(node: Node): Seq[Node] = node match {
    case a => 1
    case _ => node
  }
}

然而,经过快速的Google搜索,它似乎不再支持XML文字,而是被XML字符串插值所取代.所以,回答你的问题:

我需要在语法中修正什么?

答案是:使lexer和解析器识别XML文字.一个快速解决方案是添加lexer规则:

XmlLiteral
 : '<' ~[ \t\r\n<>]+ '>' (XmlLiteral | ~[<>])*? '</' ~[ \t\r\n<>]+ '>'
 ;

然后将XmlLiteral添加到literal解析器规则中:

literal
    : '-'? IntegerLiteral
    | '-'? FloatingPointLiteral
    | BooleanLiteral
    | CharacterLiteral
    | StringLiteral
    | SymbolLiteral
    | 'null'
    | XmlLiteral
    ;

然后,你的示例输入被正确地解析.

我说"快速修复"是因为这会导致XML文字被标记为单个标记,而没有任何 struct .要将XML正确地解析成树本身,就需要对lexer和解析器语法进行更多的修改.

编辑

对不起,我刚刚意识到我在原来的帖子中犯了一个错误.我刚刚编辑了它,似乎是与override关键字有关的东西,

我理解你的困惑,但这不是问题所在.如果您在compilationUnit规则中包含EOF令牌:

compilationUnit
    : ('package' qualId)* topStatSeq EOF
    ;

然后再次运行示例(没有override的示例),您会在控制台上看到以下错误:

line 1:35 mismatched input '{' expecting {<EOF>, 'implicit', 'lazy', 'case', '@', 'override', 'abstract', 'final', 'sealed', 'private', 'protected', 'import', 'class', 'object', 'trait', 'package'}
line 3:34 token recognition error at: '/a'
line 3:71 token recognition error at: '/a'

这是因为通过添加EOF,您强制解析器消耗all个令牌.而如果没有EOF,则只使用前两个标记,然后解析器停止,因为它无法处理XML文字.try 添加这个:

System.out.println(tree.toStringTree(parser));

你会看到只有这个解析树被打印出来:

enter image description here

使用我提出的修复方案,override个例子也可以工作.

编辑 2

和支持属性(直到某个点),但XML文字仍然是一个单一的标记,可以看起来像这样:

XmlLiteral
 : XmlOpemTag (XmlLiteral | ~[<>])*? XmlCloseTag
 ;

fragment XmlOpemTag
 : '<' ~[ \t\r\n<>]+ (S+ Attribute)* S* '>'
 ;

fragment XmlCloseTag
 : '</' ~[ \t\r\n<>]+ '>'
 ;

fragment Attribute
 : AttributeKey S* '=' S* AttributeValue
 ;

fragment AttributeKey
 : [a-zA-Z_0-9]+
 ;

fragment AttributeValue
 : AttributeKey
 | '"' ~["]* '"'
 | '\'' ~[']* '\''
 ;

fragment S
 : [ \t\r\n]
 ;

Java相关问答推荐

javafx getHostServices(). showDocument()调出Chrome而不是默认浏览器(Linux)

无法在Java中将hhmmss格式的时间解析为LocalTime

使用Java Streams API比较两个不同的Java集合对象和一个公共属性

Java FX中的河内之塔游戏-在游戏完全解决之前什么都不会显示

Exe4j创建的应用程序无法再固定在任务栏Windows 11上

如何在Java中从XML中获取特定的 node ,然后将其删除?

使用PDFBox从PDF中删除图像

有没有可能在时间范围内得到多种解决方案?

如何在Java中为thunk创建映射器函数

从12小时开始的日期模式

视图被推出线性布局-Android

H2数据库仅支持%1个结果集?

Java中的一个错误';s stdlib SocksSocketImpl?

如何以事务方式向ibmmq发送消息

ControlsFX RangeSlider在方向垂直时滞后

无泄漏函数的Java DRY

Springboot应用程序无法识别任何@RestController或@Service,我认为@Repository也无法识别

如何从指定某些字段的父对象创建子对象

message.acknowledge()没有';在使用Spring Boot在ActiveMQ中读取消息后,t将消息出列

Jackson YAML:支持锚点扩展/覆盖