Проблемы отладки инфиксной грамматики в pyparsing

1

Я написал этот скрипт для синтаксического анализа операторов с синтаксисом, аналогичным прологу, рассматривая соединительные элементы как операторы с приоритетом:

import pyparsing as pyp

alphabet = "abcdefghijklmnopqrstuvwxyz"
alphabet = alphabet + alphabet.upper()

symbol = pyp.Word(alphabet)

predicate = symbol + "(" + pyp.ZeroOrMore(symbol + ",") + symbol + ")"

parenthetic = pyp.Forward()

pyp_formula = pyp.infixNotation((predicate | parenthetic),
       [
           (pyp.oneOf('~'), 1, pyp.opAssoc.RIGHT),
           (pyp.oneOf(','), 2, pyp.opAssoc.LEFT),
           (pyp.oneOf(';'), 2, pyp.opAssoc.LEFT),
           (pyp.oneOf('::'), 2, pyp.opAssoc.LEFT),
           (pyp.oneOf('->'), 2, pyp.opAssoc.LEFT),
           (pyp.oneOf(':-'), 2, pyp.opAssoc.LEFT),
           (pyp.oneOf('--'), 1, pyp.opAssoc.LEFT),
           (pyp.oneOf('.'), 1, pyp.opAssoc.LEFT),
       ])

parenthetic << "(" + pyp_formula + ")"

Когда я бегу

parse = pyp_formula.parseString('d(A, D), e(D) :- f(A), g(D); h(D).')

parse_list = formula_parse.asList()

print(parse_list)

Я получаю, что "d (A, D), e (D)" даже не был разделен на два предиката, а "f (A), g (D); h (D)" обрабатывается как один терминал в пределах -Терминал.

[[[['d', '(', 'A', ',', 'D', ')', ',', 'e', '(', 'D', ')'],
':-', [['f', '(', 'A', ')', ',', 'g', '(', 'D', ')'],
';', 'h', '(', 'D', ')']], '.']]

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

Любая помощь приветствуется!

Теги:
pyparsing

1 ответ

1
Лучший ответ

Нет необходимости infixNotation parenthetic, infixNotation сделает это за вас. А если вы pyp.Group своего выражения predicate, то символ и его аргументы будут сгруппированы для вас. У pyparsing также есть хелпер delimitedList в качестве ярлыка для expr, expr, expr: используйте pyp.delimitedList(expr). Разделителем по умолчанию является ',', но вы можете определить другие разделители. И наконец, со столь длинным списком операторов, вероятно, у вас будут проблемы с производительностью при любом нетривиальном анализе - добавьте вызов ParserElement.enablePackrat() чтобы включить внутренний кэш синтаксического анализа.

Вот как ваш код выглядит с этими изменениями:

import pyparsing as pyp
pyp.ParserElement.enablePackrat()

alphabet = "abcdefghijklmnopqrstuvwxyz"
alphabet = alphabet + alphabet.upper()

symbol = pyp.Word(alphabet)

predicate = pyp.Group(symbol + "(" + pyp.delimitedList(symbol) + ")")

pyp_formula = pyp.infixNotation(predicate,
       [
           (pyp.oneOf('~'), 1, pyp.opAssoc.RIGHT),
           (pyp.oneOf(','), 2, pyp.opAssoc.LEFT),
           (pyp.oneOf(';'), 2, pyp.opAssoc.LEFT),
           (pyp.oneOf('::'), 2, pyp.opAssoc.LEFT),
           (pyp.oneOf('->'), 2, pyp.opAssoc.LEFT),
           (pyp.oneOf(':-'), 2, pyp.opAssoc.LEFT),
           (pyp.oneOf('--'), 1, pyp.opAssoc.LEFT),
           (pyp.oneOf('.'), 1, pyp.opAssoc.LEFT),
       ])

pyp_formula.runTests(
    '''
    d(A, D) -> h(D).
    d(A, D), e(D) :- f(A), g(D); h(D).
    '''
    )

И результаты:

d(A, D) -> h(D).
[[[['d', '(', 'A', 'D', ')'], '->', ['h', '(', 'D', ')']], '.']]
[0]:
  [[['d', '(', 'A', 'D', ')'], '->', ['h', '(', 'D', ')']], '.']
  [0]:
    [['d', '(', 'A', 'D', ')'], '->', ['h', '(', 'D', ')']]
    [0]:
      ['d', '(', 'A', 'D', ')']
    [1]:
      ->
    [2]:
      ['h', '(', 'D', ')']
  [1]:
    .


d(A, D), e(D) :- f(A), g(D); h(D).
[[[[['d', '(', 'A', 'D', ')'], ',', ['e', '(', 'D', ')']], ':-', [[['f', '(', 'A', ')'], ',', ['g', '(', 'D', ')']], ';', ['h', '(', 'D', ')']]], '.']]
[0]:
  [[[['d', '(', 'A', 'D', ')'], ',', ['e', '(', 'D', ')']], ':-', [[['f', '(', 'A', ')'], ',', ['g', '(', 'D', ')']], ';', ['h', '(', 'D', ')']]], '.']
  [0]:
    [[['d', '(', 'A', 'D', ')'], ',', ['e', '(', 'D', ')']], ':-', [[['f', '(', 'A', ')'], ',', ['g', '(', 'D', ')']], ';', ['h', '(', 'D', ')']]]
    [0]:
      [['d', '(', 'A', 'D', ')'], ',', ['e', '(', 'D', ')']]
      [0]:
        ['d', '(', 'A', 'D', ')']
      [1]:
        ,
      [2]:
        ['e', '(', 'D', ')']
    [1]:
      :-
    [2]:
      [[['f', '(', 'A', ')'], ',', ['g', '(', 'D', ')']], ';', ['h', '(', 'D', ')']]
      [0]:
        [['f', '(', 'A', ')'], ',', ['g', '(', 'D', ')']]
        [0]:
          ['f', '(', 'A', ')']
        [1]:
          ,
        [2]:
          ['g', '(', 'D', ')']
      [1]:
        ;
      [2]:
        ['h', '(', 'D', ')']
  [1]:
    .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню