所以我正在编写一个python解析器,我需要根据python grammar specification动态生成INDENT
和DEDENT
标记(因为python不使用显式分隔符)。
基本上我有一堆表示缩进级别的整数。在INDENT
令牌中的嵌入式Java操作中,我检查当前缩进级别是否高于堆栈顶部的级别;如果是的话,我就推开它;如果没有,我打电话给skip()
。
问题是,如果当前缩进级别与堆栈中的多个级别匹配,我必须生成多个DEDENT
令牌,而我无法弄清楚如何执行此操作。
我当前的代码:(请注意within_indent_block
和current_indent_level
在其他地方管理)
fragment DENT: {within_indent_block}? (SPACE|TAB)+;
INDENT: {within_indent_block}? DENT
{if(current_indent_level > whitespace_stack.peek().intValue()){
whitespace_stack.push(new Integer(current_indent_level));
within_indent_block = false;
}else{
skip();
}
}
;
DEDENT: {within_indent_block}? DENT
{if(current_indent_level < whitespace_stack.peek().intValue()){
while(current_indent_level < whitespace_stack.peek().intValue()){
whitespace_stack.pop();
<<injectDedentToken()>>; //how do I do this
}
}else{
skip();
}
}
;
我该怎么做和/或有更好的方法吗?
答案 0 :(得分:5)
您发布的代码存在一些问题。
INDENT
和DEDENT
规则在语义上是相同的(考虑谓词和规则引用,但忽略操作)。由于INDENT
首先出现,这意味着您永远拥有DEDENT
规则生成的令牌就是这种语法。{within_indent_block}?
谓词出现在您引用DENT
之前以及DENT
片段规则本身之前。这种复制没有任何意义,但会减慢你的词法分析器。匹配后操作的实际处理最好放在Lexer.nextToken()
的覆盖中。例如,您可以从以下内容开始。
private final Deque<Token> pendingTokens = new ArrayDeque<>();
@Override
public Token nextToken() {
while (pendingTokens.isEmpty()) {
Token token = super.nextToken();
switch (token.getType()) {
case INDENT:
// handle indent here. to skip this token, simply don't add
// anything to the pendingTokens queue and super.nextToken()
// will be called again.
break;
case DEDENT:
// handle indent here. to skip this token, simply don't add
// anything to the pendingTokens queue and super.nextToken()
// will be called again.
break;
default:
pendingTokens.add(token);
break;
}
}
return pendingTokens.poll();
}