首页 > 解决方案 > ANTLR4。使用操作访问上下文对象

问题描述

解析大于计算机内存大小的输入文件需要三个步骤:

  1. 使用无缓冲的字符和令牌流
  2. 从滑动缓冲区中复制文本并存储在令牌中
  3. 要求解析器不要创建解析树

目标是一种简化的语法来解析由多行组成的文件,每一行由许多单词组成。

考虑到这个要求,下面的代码使用@members动作和子类化由 ANTLR 生成的解析器

该方法printPagesAndWords接收LineContext对象列表。

它打印总行数(使用 提供的 start 方法LineContext),但无法使用对象WORD()提供的方法访问每行的 WORD 数LineContext

这是获得的输出:

Number of lines in page:    3

Line start token:           word1
Number of words in line:    0

Line start token:           2323
Number of words in line:    0

Line start token:           554545
Number of words in line:    0

此外,如果我尝试在一行中获取单词,例如更改行

System.out.println("Number of words in line:\t"+row.WORD().size()+"\n");

按行

System.out.println("Number of words in line:\t"+row.WORD(1).getText()+"\n");

抛出以下异常:

Exception in thread "main" java.lang.NullPointerException
    at TestContext.printPagesAndWords(TestContext.java:11)
    at ContextParser.read(ContextParser.java:130)
    at Main.main(Main.java:11)

以下是完整的文件集:

上下文词法分析器.g4

lexer grammar ContextLexer;
NL
 : '\r'? '\n'
 ;
WORD
 : ~[ \t\n\r]+
 ;
SPACE
 : [ \t] -> skip
 ;

上下文解析器.g4

parser grammar ContextParser;

options {
  tokenVocab=ContextLexer;
}
@members{
void printPagesAndWords(List<LineContext> rows){};
}
read
 : dataLine+=line*  {printPagesAndWords($dataLine);}
 ;
line
 : WORD* NL
 ;

扩展 ContextParser 的 TestContext

import org.antlr.v4.runtime.TokenStream;
import java.util.List;
public class TestContext extends ContextParser {
    public TestContext(TokenStream input) {
        super(input);
    }
    void printPagesAndWords(List<LineContext> rows){
        System.out.println("Number of lines in page:\t" + rows.size()+"\n");
        for(LineContext row: rows){
            System.out.println("Line start token:\t\t\t"+row.start.getText());
            System.out.println("Number of words in line:\t"+row.WORD().size()+"\n");
        }
    };
}

主类:

import org.antlr.v4.runtime.*;
import java.io.IOException;
public class Main {
    public static void main(String[] args) throws IOException {
        String source = "word1 word2 number anothernumber \n 2323 55r ere\n554545 lll 545\n";
        ContextLexer lexer = new ContextLexer(CharStreams.fromString(source));
        lexer.setTokenFactory(new CommonTokenFactory(true));
        TokenStream tokens = new UnbufferedTokenStream<CommonToken>(lexer);
        TestContext parser = new TestContext(tokens);
        parser.setBuildParseTree(false);
        parser.read();
    }
}

标签: antlrantlr4

解决方案


推荐阅读