pyparsing: проблема с соответствием одному из слов (CaselessLiteral) заданного списка - PullRequest
0 голосов
/ 22 ноября 2018

Я пишу парсер с pyparsing для определенной структуры файла.В основном это список определений элементов с синтаксисом: ElementName: ElementType, ParameterList . ParameterList является необязательным и имеет структуру pp.delimitedList.Ниже приведен пример выдержки из этого файла:

"L_000333": DRIF,L=0.0607
BPM15FL2EXTR: MONI
Q8FL2EXTR: QUAD, &
            L=0.3286,K1=-0.7494081,&
               DY="vert_offset_1"
"L_000334": DRIF,L=0.359694
D8FL2EXTR: CSRCSBEN,L=0.2200112619037261,       &
       ANGLE=-0.015708,E1=-0.007854, E2=-0.007854,  &
       SG_HALFWIDTH = 1, DY = "vert_offset_1",  &
       N_KICKS = "num_CSR_kicks", BINS = "bin_num", &
       ISR = "with_ISR", CSR = "with_CSR",      &
           OUTPUT_INTERVAL = "output_interval",     &
       INTEGRATION_ORDER = "order_integration"
"L_000335": DRIF,L=0.134994
V9FL2EXTR: VKICK,L=0.1
...

Для соответствия ElementType Я хочу использовать список заданных опций, потому что есть определенный тип с именем LINE, который не соответствуеттакое же определение структуры, как в приведенном выше примере.Например, тип LINE следует синтаксису:

FL2EXTR: LINE=(STARTFLEXTR,L_000297,FSHUTTER, ... etc... )

, и его можно найти между элементами, приведенными выше.Но сейчас я забуду о том, как анализировать этот конкретный тип элемента, потому что проблемы возникают раньше: - /.

Чтобы добиться правильного анализа данного списка элементов, я определил следующую сборкуblocks:

import pyparsing as pp

# allowed delimiters:
lte_delim_0 = pp.Literal(',')
lte_delim_1 = pp.Literal('&')
lte_delim_2 = pp.Literal(',') + lte_delim_1
lte_delim = pp.Or([lte_delim_0, lte_delim_1, lte_delim_2])

# ElementName:
elementName = pp.Or([pp.Word(pp.alphanums + '_'), pp.dblQuotedString]) + \
              pp.Literal(':').suppress()

# ElementType:
elementType = pp.Or([pp.CaselessLiteral('DRIF'),
                     pp.CaselessLiteral('ALPH'),
                     pp.CaselessLiteral('BGGEXP'),
                     pp.CaselessLiteral('BMAPXY'),
                     pp.CaselessLiteral('BMXYZ'),

                     ... looong list of possible ElementType ...

                     pp.CaselessLiteral('ZTRANSVERSE')])

# ParameterName and ParameterValue for the ParameterList:
parameterName = pp.Word(pp.alphanums + '_')
parameterValue = pp.Or([pp.Word(pp.alphanums + '_'),
                        pp.pyparsing_common.number,
                        pp.dblQuotedString])

# basic assignment definition:
assignmentExpr = pp.Group(parameterName('ParameterName') + \
                          pp.Literal('=').suppress() + \ 
                          parameterValue('ParameterValue'))

parameterList = pp.Dict(pp.delimitedList(assignmentExpr, 
                        delim = lte_delim, combine = False))

# element definition
elementDefinition = pp.Group(elementName('ElementName') + \
                             elementType('ElementType') + \
                             pp.Optional(lte_delim.suppress() + \
                                         parameterList('ParameterList')))

Затем я просто создаю синтаксический анализатор для списка элементов следующим образом:

elementList = pp.OneOrMore(ElementDefinition)

Однако, когда я анализирую приведенный выше список примеров, анализатор прекращает синтаксический анализ при обнаруженииэлемент CSRCSBEN (даже если он определен в списке elementType возможных pp.CaselessLiterals !!!).

Если вместо определения синтаксического анализатора elementType с помощью pp.Or ([... список pp.CaselessLiterals ...]) как я делал выше, я определяю elementType просто как:

elementType = pp.Word(pp.alphanums + '_')

, затем я получаю все определения элементов в списке, проанализированном правильно.Но тогда я не могу добиться того, чтобы конкретный тип элемента "LINE" был проанализирован по-разному ...

Кто-нибудь может мне помочь с этим?Почему синтаксический анализатор останавливается на элементе CSRCSBEN, даже если он задан как допустимый ElementType?

Заранее большое спасибо за вашу помощь!

Приветствия, Пау

1 Ответ

0 голосов
/ 22 ноября 2018

Спасибо, что поделились интересной проблемой.Извините, у меня нет "хорошего" решения для вас.(Может быть, если вы потратили немного времени, чтобы свести его к более простой «повторяющейся», более простой грамматике, которая демонстрирует тот же эффект?)

Я предложу это предложение.Рассмотрим предварительную обработку, чтобы (A.) строки продолжения с '&' становились одиночными длинными строками, и что более важно (B.) каждая строка получает префикс типа, основанный на наличии строки, такой как FL2EXTR или CSRCSBEN.Назовите их {TYPE1, TYPE2} или как угодно, и добавьте этот токен в строку.

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

...