Python 括號層數限制(SyntaxError: too many nested parentheses)


Python 括號層數限制(SyntaxError: too many nested parentheses)

代碼

n = 201
s = '(' * n  + ')' * n
print(eval(s))

錯誤信息

Traceback (most recent call last):
  File "/mnt/hgfs/Python-3.9.1/test.py", line 7, in <module>
    print(eval(s))
  File "<string>", line 1
    ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
                                                                                                                                                                                                           ^
SyntaxError: too many nested parentheses

n <= 200 時,程序是正常的。

debug

在 Python 源碼目錄下,使用 find 指令尋找源碼中對應的錯誤信息:

$ find ./ -name "*.[ch]" | xargs grep "too many nested parentheses"
./Parser/tokenizer.c:            return syntaxerror(tok, "too many nested parentheses");

${Python-3.9.1}/Parser/tokenizer.h 中:

#define MAXLEVEL 200    /* Max parentheses level */

${Python-3.9.1}/Parser/tokenizer.c 中可以看出,這個宏限制的不僅是小括號,中括號和大括號也是一起計算的。

    /* Keep track of parentheses nesting level */
    switch (c) {
    case '(':
    case '[':
    case '{':
        if (tok->level >= MAXLEVEL) {
            return syntaxerror(tok, "too many nested parentheses");
        }
        tok->parenstack[tok->level] = c;
        tok->parenlinenostack[tok->level] = tok->lineno;
        tok->level++;
        break;
    case ')':
    case ']':
    case '}':
        if (!tok->level) {
            return syntaxerror(tok, "unmatched '%c'", c);
        }
        tok->level--;
        int opening = tok->parenstack[tok->level];
	    ...

MAXLEVEL 改為 300 ,然后重新編譯 Python ,程序成功執行:

()

n 增大到 301 時,再次報錯 SyntaxError: too many nested parentheses

舊版 Python

MAXLEVEL 這個宏不是一直就有的,我記得它是在 3.8 的某個版本引入的,詳細信息參考 issue33306

我下載了 Python 3.7.9 ,這個版本在 n >= 94 時報錯:

s_push: parser stack overflow
Traceback (most recent call last):
  File "test.py", line 6, in <module>
    print(eval(s))
MemoryError

尋找錯誤信息對應的源碼:

$ find ./ -name "*.[ch]" | xargs grep "parser stack overflow"
./Parser/parser.c:        fprintf(stderr, "s_push: parser stack overflow\n");

然后在 ./Parser/parser.h 中找到 DFA 棧的大小:

#define MAXSTACK 1500

將這個值改為 3000 然后重新編譯,最大括號層數從 93 增長到了 187

問題

  1. stackentry s_base[MAXSTACK]; 里面都存了什么東西,為什么 MAXSTACK 的值都上千了,最大括號層數還不是很多?
  2. 為什么使用新的實現,按照 issue 33306 的說明,是為了實現更友好的錯誤提示,那么為什么這么改?新的數據結構把括號分離出去以后怎么做計算?

這些問題只有在仔細研究源碼以后才能了解,暫時擱置了,以后有時間再回來填上這個坑。


免責聲明!

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



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