Синтаксический анализ и парсер - PullRequest
2 голосов
/ 16 августа 2011

Я хочу разобрать что-то вроде этого:

path.to.variable

"path" и "to" - это объекты с именем "Instance" и двойной ссылкой на переменную.

У меня есть следующая грамматика:

expr                ::= instancePath:i INSTANCE_SEPARATOR SHORTCUT:s
                    {:
                        RESULT = getDouble(s);
                    :}
                ;



instancePath        ::= instanceSubPath:p
                    {:
                        RESULT = p;
                    :}
                ;


instanceSubPath     ::= instanceSubPath:i1 INSTANCE_SEPARATOR instanceSubPath:i2
                    {:
                        RESULT = i2;
                    :}
                | SHORTCUT:s
                    {:
                        RESULT = pushInstance(s);
                    :}
                ;

В этой грамматике:

  • INSTANCE_SEPARATOR - это "."char.
  • SHORTCUT - это имя, содержащее только буквы типа «путь», «к» или «переменная».
  • expr должен возвращать двойное значение, полученное в результате вызова функции getDouble, которая принимаетимя (здесь «переменная»).Эта функция использует текущий выбранный экземпляр.Экземпляр содержит хеш-таблицу, которая содержит double или другой экземпляр.
  • pushInstance - это функция, которая устанавливает текущий экземпляр

, например, у нас может быть:

  • экземпляр "путь", который содержит хеш-таблицу, которая является: "to" => ссылка на экземпляр "на"
  • экземпляр "to", который содержит хеш-таблицу, которая: "variable" => 10
  • путь "path.to.variable" должен возвращать 10.

Это не работает, потому что грамматика жалуется на нулевое значение.Это связано с тем, что синтаксический анализатор делает следующее:

expr(
  instancePath(
    instanceSubPath(SHORTCUT("path"))
    INSTANCE_SEPARATOR 
    instanceSubPath(SHORTCUT("to")) 
    INSTANCE_SEPARATOR 
    instanceSubPath(SHORTCUT("variable"))
  )
  INSTANCE_SEPARATOR
  !NULL!

)

вместо выполнения

expr(
 instancePath(
    instanceSubPath(SHORTCUT("path"))
    INSTANCE_SEPARATOR 
    instanceSubPath(SHORTCUT("to")) 
 )
 INSTANCE_SEPARATOR 
 SHORTCUT("variable")
)

Почему?есть ли проблемы с приоритетом?

В завершение, если я удалю правило instancePath, все запустится:

expr                ::= instanceSubPath:i INSTANCE_SEPARATOR SHORTCUT:s
                    {:
                        RESULT = getDouble(s);
                    :}
                ;


instanceSubPath     ::= instanceSubPath:i1 INSTANCE_SEPARATOR instanceSubPath:i2
                    {:
                        RESULT = i2;
                    :}
                | SHORTCUT:s
                    {:
                        RESULT = pushInstance(s);
                    :}
                ;

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

Я не понимаю, почему удаление этого дополнительного правила решило мою проблему ...

...