Я определил два набора идентификаторов IDENTIFIER_ONE
и IDENTIFIER_TWO
, которые являются одновременно эксклюзионными подмножествами IDENTIFIER
. Я хотел бы написать парсер, что:Попробуйте первое правило, если второе правило не удалось
"i1(arg) EOS" can't be parsed (1)
"i2(arg) EOS" can be parsed (2)
"i1(arg) = value EOS" can be parsed (3)
"i2(arg) = value EOS" can be parsed (4)
где i1
(соответственно, i2
.) Принадлежит IDENTIFIER_ONE
; (соответственно, IDENTIFIER_TWO
.) arg
и value
принадлежат к IDENTIFIER
. Следующий parser.mly
уже реализовал все моменты я после, кроме (4)
:
identifier:
| IDENTIFIER_ONE { $1 }
| IDENTIFIER_TWO { $1 }
block_statement_EOS:
| identifier LPAREN identifier RPAREN EQUAL identifier EOS { BSE_Let ($1, $3, $6) }
| IDENTIFIER_TWO LPAREN identifier RPAREN EOS { BSE_I_I ($1, $3) }
Учитывая i1(arg) = value EOS
в качестве входных данных, а цель (3)
это правильно читается как BSE_Let (i1, arg, value)
. Однако, учитывая ввод i2(arg) = value EOS
, он останавливает разбор после чтения EQUAL
. Я думаю, это потому, что раз парсе встречаются i2(arg)
, он переходит во 2-ое правило block_statement_EOS
, а затем EQUAL
не может быть разобран.
В идеале я бы надеялся, что анализатор может попробовать 1-е правило block_statement_EOS
, если 2-е правило выходит из строя. Может ли кто-нибудь помочь мне сделать это возможным?
PS: Если я напишу parser.mly
следующим образом, все цели могут быть достигнуты. Кто-нибудь знает, почему? Кроме того, я действительно не нравится этот обходной путь, потому что мне нужно написать identifier
вместо двух подмножеств во многих других правил, я хотел бы надеяться, более элегантное решение ...
block_statement_EOS:
| IDENTIFIER_ONE LPAREN identifier RPAREN EQUAL identifier EOS { BSE_Let ($1, $3, $6) }
| IDENTIFIER_TWO LPAREN identifier RPAREN EQUAL identifier EOS { BSE_Let ($1, $3, $6) }
| IDENTIFIER_TWO LPAREN identifier RPAREN EOS { BSE_I_I ($1, $3) }
Спасибо ... Давайте по-прежнему возьмем пример 'i2 (arg) = value EOS', означает ли это, что парсер выбирает' shift', когда он встречает 'LPAREN'? Жаль, что парсер не смог попробовать другой выбор ('reduce'), если один выбор (' shift') приводит к сбою ... Есть ли другой способ обойти, кроме моей второй версии, которая мне не нравится? – SoftTimur
В любой момент все символы сдвигаются (т.е. накладываются на стек). Смещение в основном означает: чтение следующего символа. То, что вы хотите, подразумевало бы откат, что потенциально очень неэффективно.Однако возможно, что другие технологии синтаксического анализа будут работать, но я не знаком с ними. Взгляните на Менхира, возможно, он справится с этим делом лучше. – Bardou