antlr - ANTLR4。使用操作访问上下文对象
问题描述
解析大于计算机内存大小的输入文件需要三个步骤:
- 使用无缓冲的字符和令牌流
- 从滑动缓冲区中复制文本并存储在令牌中
- 要求解析器不要创建解析树
目标是一种简化的语法来解析由多行组成的文件,每一行由许多单词组成。
考虑到这个要求,下面的代码使用@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();
}
}
解决方案
推荐阅读
- python - numpy 数组将 uin8 lsb 转换为 uint16 msb
- ios - 在后台或应用未运行时监控 Bluecats 信标
- wordpress - Laravel 5 覆盖辅助函数 __() 因为在 wordpress 中使用
- java - Spring security antMatchers 未应用于 POST 请求,仅适用于 GET
- javascript - 转换特定的正则表达式而不进行负面回顾
- reporting-services - SSRS 动态图表宽度,但保持边距静态宽度
- vba - Excel VBA - 打开同时被其他人保存的工作簿
- php - Wordpress jigoshop 端点不会调用 processResponse()
- xpages - 如何在重复控制中对记录进行排序
- html - 在 R Shiny 中翻译数据表