Анализатор ruby ​​на верхушке дерева - не удалось разобрать упорядоченный выбор - PullRequest
1 голос
/ 23 декабря 2010

Я определил простую грамматику для разбора строки и числа с помощью Treetop, как показано ниже.

grammar Simple
    rule value
        number / string
    end 

    rule string
        word space string
        /
        word
    end

    rule word
        [0-9a-zA-Z]+
    end

    rule number
        [1-9] [0-9]*
    end

    rule space
        ' '+
    end
end

Ruby:

parser = SimpleParser.new
parser.parse('123abc wer') # => nil

Я ожидаю, что парсер вернет строковый узел , но похоже, что парсер не смог понять входные данные. Любая идея будет оценена.

1 Ответ

4 голосов
/ 23 декабря 2010

В Treetop (и вообще в целом, в PEG) оператор выбора упорядочен , в отличие от большинства других формализмов синтаксического анализа.

Итак, в

rule value
  number / string
end

выTreetop говорит, что вы предпочитаете number вместо string.

Ваш ввод начинается с 1, что соответствует обоим number и string(через word), но вы сказали Treetop предпочесть интерпретацию number, поэтому она анализирует ее как number.Когда дело доходит до a во входных данных, у него больше нет правил для применения, и поэтому он ничего не возвращает (nil), потому что в Treetop это ошибка не использовать весь входной поток.

Если вы просто измените порядок выбора, весь ввод будет интерпретирован как string вместо number:

SyntaxNode+String0 offset=0, "123abc wer" (word,space,string):
  SyntaxNode offset=0, "123abc":
    SyntaxNode offset=0, "1"
    SyntaxNode offset=1, "2"
    SyntaxNode offset=2, "3"
    SyntaxNode offset=3, "a"
    SyntaxNode offset=4, "b"
    SyntaxNode offset=5, "c"
  SyntaxNode offset=6, " ":
    SyntaxNode offset=6, " "
  SyntaxNode offset=7, "wer":
    SyntaxNode offset=7, "w"
    SyntaxNode offset=8, "e"
    SyntaxNode offset=9, "r"

Или вы можете оставить порядок как есть, нопозволяют правилу value совпадать несколько раз.Либо вставьте новое правило верхнего уровня, например:

rule values
  value+
end

, либо измените правило value следующим образом:

rule value
  (number / string)+
end

, которое даст вам AST примерно так:

SyntaxNode offset=0, "123abc wer":
  SyntaxNode+Number0 offset=0, "123":
    SyntaxNode offset=0, "1"
    SyntaxNode offset=1, "23":
      SyntaxNode offset=1, "2"
      SyntaxNode offset=2, "3"
      SyntaxNode+String0 offset=3, "abc wer" (word,space,string):
        SyntaxNode offset=3, "abc":
          SyntaxNode offset=3, "a"
          SyntaxNode offset=4, "b"
      SyntaxNode offset=5, "c"
    SyntaxNode offset=6, " ":
      SyntaxNode offset=6, " "
    SyntaxNode offset=7, "wer":
      SyntaxNode offset=7, "w"
      SyntaxNode offset=8, "e"
      SyntaxNode offset=9, "r"
...