5

我正在创建一种支持重要空格的语法(最像 Python 或 yaml 的“Z”lisp 变体,但相同的想法)

我遇到了这篇关于如何在 pegasus 中进行重要的空白解析的文章,这是 C# 的 PEG 解析器

但是我在将其转换为欧芹方面不太成功,看起来 Pegasus 中的#STATE# 变量以某种方式跟随回溯。

这是我最接近简单解析器的方法,如果我使用indentwith look ahead 的版本,它就无法解析孩子,如果我使用没有的版本,它就无法解析兄弟姐妹。

如果这是欧芹的限制并且我需要使用 PyPEG 或 Parsimonious 或其他东西,我对此持开放态度,但看起来如果内部缩进变量可以跟随 PEG 内部回溯,这一切都会奏效。

import parsley

def indent(s):
    s['i'] += 2
    print('indent i=%d' % s['i'])


def deindent(s):
    s['i'] -= 2
    print('deindent i=%d' % s['i'])


grammar = parsley.makeGrammar(r'''
id = <letterOrDigit+>
eol = '\n' | end
nots = anything:x ?(x != ' ')

node =  I:i id:name eol !(fn_print(_state['i'], name)) -> i, name

#I = !(' ' * _state['i'])
I = (' '*):spaces ?(len(spaces) == _state['i'])
#indent = ~~(!(' ' * (_state['i'] + 2)) nots) -> fn_indent(_state)
#deindent = ~~(!(' ' * (_state['i'] - 2)) nots) -> fn_deindent(_state)

indent = -> fn_indent(_state)
deindent = -> fn_deindent(_state)

child_list = indent (ntree+):children deindent -> children

ntree = node:parent (child_list?):children -> parent, children
nodes = ntree+

''', {
    '_state': {'i': 0},
    'fn_indent': indent,
    'fn_deindent': deindent,
    'fn_print': print,
})

test_string = '\n'.join((
    'brother',
    '  brochild1',
    #'    gchild1',
    #'  brochild2',
    #'    grandchild',
    'sister',
    #'  sischild',
    #'brother2',
))

nodes = grammar(test_string).nodes()
4

0 回答 0