Я пишу парсер с 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?
Заранее большое спасибо за вашу помощь!
Приветствия, Пау