Как синтаксические анализаторы Python обрабатывают отступы?

При синтаксическом анализе языка произвольной формы, такого как C, синтаксическому анализатору легко определить, связаны ли несколько выражений друг с другом, просто взглянув на символы, испускаемые синтаксическим анализатором. Например, в коде

if (x == 5) {
    a = b;
    c = d;
}

синтаксический анализатор может сказать, что a = b; и c = d; являются частью одного оператора блока, потому что они заключены в фигурные скобки. Это можно легко закодировать как CFG, используя что-то вроде этого:

STMT        ::=  IF_STMT | EXPR; | BLOCK_STMT | STMT STMT
IF_STMT     ::=  if ( EXPR ) STMT
BLOCK_STMT  ::=  { STMT }

Однако в Python и других языках, чувствительных к пробелам, это не так просто сделать, потому что структура операторов может быть выведена только из их абсолютного положения, которое Я не думаю, что можно легко закодировать в CFG. Например, приведенный выше код на Python будет выглядеть так:

if x == 5:
    a = b
    c = d

Как бы я ни старался, я не вижу способа написать CFG, который принял бы это, потому что я не могу понять, как кодировать "два оператора" на том же уровне вложения »в CFG.

Как синтаксические анализаторы Python группируют операторы, как они это делают? Полагаются ли они на сканер, который автоматически вставляет дополнительные токены, обозначающие начало и конец операторов? Создают ли они приблизительный AST для программы, а затем имеют дополнительный проход, который собирает операторы на основе их отступов? Есть ли умный CFG для этой проблемы, который мне не хватает? Или они используют более мощный парсер, чем стандартный парсер LL (1) или LALR (1), который может учитывать уровень пробелов?

22
задан templatetypedef 7 April 2019 в 19:24
поделиться