Я пишу парсер языка. Он основан на правилах стиля BNF, где правило содержит список опций или терминальных токенов. Например:
# Rule A matches the current token stream position if it matches rule B
# followed by rule C followed by a semicolon
rule_a:
rule_b rule_c ";"
# Rule B matches the current token stream position if the token
# there equals "foo"
rule_b:
"foo"
# Rule C matches the current token stream position if it matches
# either rule D or rule E
rule_c:
rule_d | rule_e
rule_d:
"bar"
rule_e:
"bar bar"
Проблема, с которой я сталкиваюсь, заключается в том, что если при разборе правила C ОБА правила D и E соответствуют текущему потоку токенов, но только позже (прогресс в Правило A) Становится ли очевидным, что только один из D или E был правильным выбором? При повторном обращении к синтаксическому дереву такого типа создается впечатление, что историю необходимо каким-то образом сохранить, чтобы можно было «повторить попытку» обход конкретного синтаксического дерева, но с другими параметрами, чем в прошлый раз.
Как Например, используя приведенные выше правила, что, если я пытаюсь проанализировать следующий текст:
foo bar bar;
Дерево вызовов обхода выглядит следующим образом, здесь используются отступы для отображения глубины рекурсии.
parse(token = "foo", rule = rule_a)
parse(token = "foo", rule = rule_b)
parse(token = "foo", rule = terminal_token("foo")
success: consume "foo", return true
success: return true
// So far so good, keep going with rule_a
parse(token = "bar", rule = rule_c)
parse(token = "bar", rule = rule_d) // Try rule D first.
parse(token = "bar", rule = terminal_token("bar")
success: consume "bar", return true
success: return true
success: return true // Rule D matched.
// Still good, keep going.
parse(token = "bar", rule = terminal token ";") // second "bar" here
fail: return false // "bar" != ";"
fail: return false. // Sequence rule_b rule_c ";" did not match
Таким образом, теперь синтаксический анализ не удался, даже несмотря на то, что он был бы успешным, если бы было опробовано правило E вместо правила D. У меня возникли проблемы с поиском хорошего способа отследить, какие правила были опробованы на каком токене. Если правило A в конечном итоге терпит неудачу, как показано выше, его действительно следует повторить, на этот раз попробуйте другие параметры в некоторых из подчиненных правил - в этом случае выбирается второй параметр (rule_e) при синтаксическом анализе rule_ c. Но это усложняется очень быстро - с более сложными грамматиками могут быть длинные цепочки правил, каждая с несколькими вариантами. Поэтому мне неясно, как вы узнали бы из неудачного результата разбора, были ли другие способы, которые могли бы быть проанализированы, а затем, как исчерпывающе попробовать их все.