Вопрос

Я использую Pyparding, чтобы разбираться в файлах VCD (Value Change Dump). По сути, я хочу прочитать в файлах, разбирать его во внутренний словарь и манипулировать значениями.

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

В файлах VCD у вас есть «призывы», которые включают провода и, возможно, некоторые более глубокие (вложенные) области. Думайте о них как уровни.

Так что в моем файле у меня есть:

$scope module toplevel $end
$scope module midlevel $end
$var wire a $end
$var wire b $end
$upscope $end
$var wire c $end
$var wire d $end
$var wire e $end
$scope module extralevel $end
$var wire f $end
$var wire g $end
$upscope $end
$var wire h $end
$var wire i $end
$upscope $end

Так что «Toplevel» охватывает все (A - I), «средний этаж» имеет (A - B), «Extralevel» имеет (F - G) и т. Д.

Вот мой код (фрагмент) для анализа этого раздела:

scope_header = Group(Literal('$scope') + Word(alphas) + Word(alphas) + \
                     Literal('$end'))

wire_map = Group(Literal('$var') + Literal('wire') + Word(alphas) + \
                 Literal('$end'))

scope_footer = Group(Literal('$upscope') + Literal('$end'))

scope = Forward()
scope << (scope_header + ZeroOrMore(wire_map) + ZeroOrMore(scope) + \
          ZeroOrMore(wire_map) + scope_footer)

Теперь, что я мысль Бывает, что, поскольку он попадает в каждую область, он отслеживал бы каждый «уровень», и я закончу со структурой, содержащей вложенные области. Тем не менее, это ошибки на

$scope module extralevel $end

говоря, что ожидает «$ USSCOPE».

Так что я знаю, что я не использую рекурсию правильно. Кто-нибудь может мне помочь? Дайте мне знать, если мне нужно будет предоставить больше информации.

Спасибо!!!!

Это было полезно?

Решение

Согласно вашему определению, объем не может содержать другую область, а затем некоторые карты, за которыми следуют другой объем.

Если Parser имеет режим отладки, где он печатает его дерево разбора, вы сможете увидеть это немедленно. Но, короче говоря, вы говорите, что есть ноль или больше карт, за которыми следуют ноль или более спецификаций, а затем ноль или более карт, поэтому, если есть сфера, а затем карту, вы уже пропустили поле области, так Любые еще недействительные. Если язык, используемый Pyparding поддерживает «или», вы можете использовать:

scope << (scope_header + ZeroOrMore((wire_map | scope)) + scope_footer)

Другие советы

Пожалуйста, выберите ответ @ ZackBloom в качестве правильного, он сразу он не устал, даже не зная синтаксис Pyparding.

Всего несколько комментариев / предложений на вашей грамматике:

С ответом, размещенным выше, вы можете визуализировать гнездование, используя PPRINT и Pyparting's asList() Метод на Parseresults:

res = scope.parseString(vcd)

from pprint import pprint
pprint(res.asList())

Давать:

[[['$scope', 'module', 'toplevel', '$end'],
  [['$scope', 'module', 'midlevel', '$end'],
   ['$var', 'wire', 'a', '$end'],
   ['$var', 'wire', 'b', '$end'],
   ['$upscope', '$end']],
  ['$var', 'wire', 'c', '$end'],
  ['$var', 'wire', 'd', '$end'],
  ['$var', 'wire', 'e', '$end'],
  [['$scope', 'module', 'extralevel', '$end'],
   ['$var', 'wire', 'f', '$end'],
   ['$var', 'wire', 'g', '$end'],
   ['$upscope', '$end']],
  ['$var', 'wire', 'h', '$end'],
  ['$var', 'wire', 'i', '$end'],
  ['$upscope', '$end']]]

Так что теперь у вас есть красиво структурированные результаты. Но вы можете немного чистить вещи. Для одной вещи, теперь, когда у вас есть структура, вам не нужны все эти $scope, $end, и т. Д. Токены. Вы, безусловно, можете просто перейти на них, поскольку вы перемещаетесь через анализируемые результаты, но вы также можете иметь Pyparding, просто бросьте их с анализованного выхода (поскольку результаты теперь структурированы, вы на самом деле ничего не теряете). Измените ваши определения парсера к:

SCOPE, VAR, UPSCOPE, END = map(Suppress, 
                                 "$scope $var $upscope $end".split())
MODULE, WIRE = map(Literal, "module wire".split())

scope_header = Group(SCOPE + MODULE + Word(alphas) + END)
wire_map = Group(VAR + WIRE + Word(alphas) + END) 
scope_footer = (UPSCOPE + END) 

(Нет необходимости группировать scope_footer - все в этом выражении подавляется, так Group просто даст вам пустой список.)

И теперь вы можете видеть более четко действительно важные биты:

[[['module', 'toplevel'],
  [['module', 'midlevel'], ['wire', 'a'], ['wire', 'b']],
  ['wire', 'c'],
  ['wire', 'd'],
  ['wire', 'e'],
  [['module', 'extralevel'], ['wire', 'f'], ['wire', 'g']],
  ['wire', 'h'],
  ['wire', 'i']]]

На риск слишком много группировки я бы также предложил Groupсодержание вашего scope Выражение, как это:

scope << Group(scope_header + 
               Group(ZeroOrMore((wire_map | scope))) + 
               scope_footer) 

который дает эти результаты:

[[['module', 'toplevel'],
  [[['module', 'midlevel'], [['wire', 'a'], ['wire', 'b']]],
   ['wire', 'c'],
   ['wire', 'd'],
   ['wire', 'e'],
   [['module', 'extralevel'], [['wire', 'f'], ['wire', 'g']]],
   ['wire', 'h'],
   ['wire', 'i']]]]

Теперь каждый результат объема имеет 2 предсказуемых элемента: заголовок модуля и список проводов или подсветных. Эта предсказуемость сделает намного проще написать рекурсивный код, который будет ориентироваться в результатах:

res = scope.parseString(vcd)
def dumpScope(parsedTokens, indent=''):
    module,contents = parsedTokens
    print indent + '- ' + module[1]
    for item in contents:
        if item[0]=='wire':
            print indent + '  wire: ' + item[1]
        else:
            dumpScope(item, indent+'  ')
dumpScope(res[0])

который выглядит как:

- toplevel
  - midlevel
    wire: a
    wire: b
  wire: c
  wire: d
  wire: e
  - extralevel
    wire: f
    wire: g
  wire: h
  wire: i

Хороший первый вопрос, добро пожаловать в так и Pyparding!

Я знаю, что это старый вопрос, который уже ответил, но просто думал, что добавлю полезную ссылку на пакет Phython VCD Parsing, который может поставить свой VCD в базовую структуру данных Python.

Verilog_vcd 1.0

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top