1

所以我正在编写一个python解析器,我需要根据python语法规范INDENT动态生成和DEDENT标记(因为python不使用显式分隔符)。

基本上我有一堆代表缩进级别的整数。在INDENT令牌中嵌入的 Java 操作中,我检查当前缩进级别是否高于堆栈顶部的级别;如果是,我推它;如果没有,我打电话给skip().

问题是,如果当前缩进级别与堆栈中的多个级别匹配,我必须生成多个DEDENT标记,而我不知道该怎么做。

我当前的代码:(请注意,within_indent_blockcurrent_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();
         }
         }
         ;

我该怎么做和/或有更好的方法?

4

1 回答 1

5

您发布的代码存在一些问题。

  1. INDENTandDEDENT规则在语义上是相同的(考虑谓词和规则引用,但忽略操作)。由于INDENT首先出现,这意味着你永远不可能有一个由DEDENT规则产生的标记是这个语法。
  2. {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();
}
于 2013-08-10T04:09:53.133 回答