Я уже написал генератор, который делает трюк, но я хотел бы знать наилучший способ реализации правила вне игры.
Вкратце: Off-side rule означает в этом контексте, что отступ становится распознанным как синтаксический элемент.
Вот правило офсайда в псевдокоде для создания токенизаторов, которые фиксируют отступ в полезной форме, я не хочу ограничивать ответы языком:
token NEWLINE
matches r"\n\ *"
increase line count
pick up and store the indentation level
remember to also record the current level of parenthesis
procedure layout tokens
level = stack of indentation levels
push 0 to level
last_newline = none
per each token
if it is NEWLINE put it to last_newline and get next token
if last_newline contains something
extract new_level and parenthesis_count from last_newline
- if newline was inside parentheses, do nothing
- if new_level > level.top
push new_level to level
emit last_newline as INDENT token and clear last_newline
- if new_level == level.top
emit last_newline and clear last_newline
- otherwise
while new_level < level.top
pop from level
if new_level > level.top
freak out, indentation is broken.
emit last_newline as DEDENT token
clear last_newline
emit token
while level.top != 0
emit token as DEDENT token
pop from level
comments are ignored before they are getting into the layouter
layouter lies between a lexer and a parser
Этот затвор не генерирует больше одного NEWLINE во времени и не генерирует NEWLINE, когда появляется отступ. Поэтому правила синтаксического анализа остаются довольно простыми. Это довольно хорошо, я думаю, но сообщите, есть ли лучший способ добиться этого.
При использовании этого в течение некоторого времени я заметил, что после DEDENTs может быть приятно испускать новую строку в любом случае, таким образом вы можете разделить выражения с NEWLINE, сохраняя INDENT DEDENT в качестве трейлера для выражения.