python等縮進語言的詞法分析實現


python等縮進語言的詞法分析實現:

定義兩個虛擬的Token:

tokens {
    INDENT;
    DEDENT;
}

還有一個縮進棧,用於確定是縮進一行,還是回退一行:
Stack<Integer> _indentStack = new Stack<Integer>();

在開始做詞法分析之前,壓入一個默認的Indent,這一步其實沒什么必要,只是用來避免寫判斷棧頂是否為空的冗余判斷:
_indentStack = new Stack<Integer>();
_indentStack.push(new Integer(0));

針對每一個新行,首先判斷行首是否是空格,如果是空格,則空格計1、Tab鍵計8個空格,如果僅僅是空行,跳過。如果在碰到行尾之前碰有非空字符,則將空格數與棧頂的空格對比,如果大於,壓入當前行的空格數,並生成一個虛擬的Indent Token,如果小於,將所有空格數大於當前行的出棧,並生成一個虛擬的Dedent Token:

NEWLINE
@init {
    int spaces = 0;
}
    :   ((('\u000C')?('\r')? '\n' ) | '\t' | ' ')* (('\u000C')?('\r')? '\n')
        leading_space = (' ' { spaces++; } | '\t' { spaces += 8; spaces -= (spaces \% 8); })*
        {
            if ( !_inATable &&
                 (getCharPositionInLine() == 0 ||
                  implicitLineJoiningLevel > 0) ) {
                emit(new ClassicToken(NEWLINE, this.getText(), HIDDEN));
            } else {
                emit(new ClassicToken(NEWLINE, this.getText(), HIDDEN));
            }

            if ( implicitLineJoiningLevel == 0 &&
                 _indentStack.size() > 0) {
                if (spaces > _indentStack.peek().intValue() ) {
                    _indentStack.push(new Integer(spaces));                   
                    emit(new ClassicToken(INDENT, ">"));
                }
                else {
                    while ( spaces < _indentStack.peek().intValue() ) {
                        _indentStack.pop();
                        emit(new ClassicToken(DEDENT, "<"));
                    }
                }
            }
        }
    | ((('\u000C')?('\r')? '\n' ) | '\t' | ' ')* (('\u000C')?('\r')? '\n')
      (' ' | '\t')* '#' (~'\n')*
        {
            $channel = HIDDEN;
        }
    ;

當然還要考慮純注釋行,和空格后僅跟有注釋的情形。

這樣詞法分析過程中,縮進的詞法分析過程就完了,在語法分析中,Indent是透明的,例如:

compound_stmt
    : IF compound_condition (suite)+ elif_clause* else_clause?
    | assignment
    ;

suite
    : INDENT (compound_stmt)+ (DEDENT | EOF)
    ;

上面的語法中,INDENT和DEDENT就跟括號的處理沒什么區別,只不過DEDENT可選,主要是考慮直接在代碼后就EOF的情況。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM