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 的说明,是为了实现更友好的错误提示,那么为什么这么改?新的数据结构把括号分离出去以后怎么做计算?

这些问题只有在仔细研究源码以后才能了解,暂时搁置了,以后有时间再回来填上这个坑。

posted @ 2021-01-12 18:07  AdjWang  阅读(1034)  评论(0编辑  收藏  举报