sqlparse - python-dateutil pypi



Pyparsing:白色空间有时很重要......有时候不会 (1)

我想为包含几个部分的文件创建一个语法(如下面的PARAGRAPH)。

一个部分以其关键字(例如PARAGRAPH)开头,后跟一个标题(此处为标题),其内容在以下行中,一行内容是该部分的一行。 它就像一个带有标题,列和行的表。

在下面的示例(tablefile)中,我将限制部分包含一列和一行。

Tablefile的自上而下的BNF:

tablefile := paragraph*
paragraph := PARAGRAPH title CR
             TAB content
title, content := \w+

Pyparsing语法:

由于我需要处理换行符和表格,我需要将默认空格设置为''。

def grammar():
    '''
    Bottom-up grammar definition
    '''

    ParserElement.setDefaultWhitespaceChars(' ')
    TAB = White("\t").suppress()
    CR = LineEnd().setName("Carriage Return").suppress()
    PARAGRAPH = 'PARAGRAPH'

    title = Word(alphas)
    content = Word(alphas)
    paragraph = (PARAGRAPH + title + CR
                 + TAB + content)

    tablefile = OneOrMore(paragraph)
    tablefile.parseWithTabs()

    return tablefile

应用于示例

这个虚拟示例很容易匹配:

PARAGRAPH someTitle
          thisIsContent

另外这个:

PARAGRAPH someTitle
          thisIsContent
PARAGRAPH otherTitle
          thisIsOtherContent

它在第一个内容之后等待PARAGRAPH ,并偶然发现换行符(请记住setDefaultWhitespaceChars(' ') )。 我是否被迫加入CR?paragraph的末尾? 什么是忽略这种最后换行符的更好方法?

此外,我想允许选项卡和空格在文件中的任何位置没有干扰。 唯一需要的行为是使用TAB启动段落内容,使用PARAGRAPH启动该行。 这也意味着在段落中和段落之间跳过空白行(带有制表符和空格或没有)。

因此我添加了这一行:

tablefile.ignore(LineStart() + ZeroOrMore(White(' \t')) + LineEnd())

但是我刚刚曝光的每一个要求似乎都违背了我将默认空格设置为' '并让我走入死胡同的需要。

实际上,这会导致一切崩溃:

tablefile.ignore(CR)
tablefile.ignore(TAB)

将PARAGRAPH和TAB粘贴到行首

如果我想要被忽略的话 文本中的任何地方,但在行的开头。 我将不得不将它们添加到默认的空格字符。

因此,我找到了一种在行首开始禁止每个空格字符的方法。 通过使用leaveWhitespace方法。 此方法在匹配令牌之前保留它遇到的空格。 因此,我可以将一些令牌粘贴到行首。

ParserElement.setDefaultWhitespaceChars('\t ')
SOL = LineStart().suppress()
EOL = LineEnd().suppress()

title = Word()
content = Word()
PARAGRAPH = Keyword('PARAGRAPH').leaveWhitespace()
TAB = Literal('\t').leaveWhitespace()

paragraph = (SOL + PARAGRAPH + title + EOL
             + SOL + TAB + content + EOL)

有了这个解决方案,我在文本中的任何地方都用TAB解决了我的问题。

分开段落

经过一番思考后,我达到了PaulMcGuire( delimitedList )的解决方案。 我遇到了一些问题。

实际上,这里有两种不同的方式来声明两段之间的换行符分隔符。 在我看来,它们应该是等价的。 在实践中,他们不是?

崩溃测试(如果你运行它,不要忘记用标签更改空格):

PARAGRAPH titleone
          content1
PARAGRAPH titletwo
          content2

两个例子之间的共同点:

ParserElement.setDefaultWhitespaceChars('\t ')
SOL = LineStart().suppress()
EOL = LineEnd().suppress()

title = Word()
content = Word()
PARAGRAPH = Keyword('PARAGRAPH').leaveWhitespace()
TAB = Literal('\t').leaveWhitespace()

第一个例子,工作一个:

paragraph = (SOL + PARAGRAPH + title + EOL
            + SOL + TAB + content + EOL)

tablefile = ZeroOrMore(paragraph)

第二个例子,不工作:

paragraph = (SOL + PARAGRAPH + title + EOL
            + SOL + TAB + content)

tablefile = delimitedList(paragraph, delim=EOL)

它们不应该是等价的吗? 第二次提出异常:

Expected end of text (at char 66), (line:4, col:1)

这对我来说不是一个大问题,因为我终于可以退出,将EOL放在我语法的每个段落的末尾。 但我想突出这一点。

忽略包含空格的空行

我的另一个要求是忽略空行,包含空格( ' \t' )。

一个简单的语法是:

ParserElement.setDefaultWhitespaceChars(' \t')
SOL = LineStart().suppress()
EOL = LineEnd().suppress()

word = Word('a')
entry = SOL + word + EOL

grammar = ZeroOrMore(entry)
grammar.ignore(SOL + EOL)

最后,文件每行可以包含一个单词,任何地方都有空格。 它应该忽略空白行。

幸运的是,确实如此。 但它不受默认空格声明的影响。 包含空格或制表符的空行将导致解析器引发解析异常。

这种行为绝对不是我所期望的。 是指定的吗? 这个简单的尝试有没有错误?

我可以在这个帖子中看到PaulMcGuire并没有试图忽略空行,而是在类似makefile的语法分析器( NL = LineEnd().suppress() )中对它们进行标记化。

任何用于自定义BNF解析器的python模块?

makefile_parser = ZeroOrMore( symbol_assignment
                             | task_definition
                             | NL )

我现在唯一的解决方案是预处理文件并删除空白行中包含的空格,因为pyparsing正确地忽略空白行,其中没有空格。

import os
preprocessed_file = os.tmpfile()    
with open(filename, 'r') as file:
    for line in file:
        # Use rstrip to preserve heading TAB at start of a paragraph line
        preprocessed_file.write(line.rstrip() + '\n')
preprocessed_file.seek(0)

grammar.parseFile(preprocessed_file, parseAll=True)

您的BNF仅包含CR,但您解析代码以使用LF终止。 这是有意的吗? BNF支持 LF(Unix),CR(Mac)和CRLF(Win)EOL:

Rule_|_Def.__|_Meaning___
CR   | %x0D  | carriage return
LF   | %x0A  | linefeed
CRLF | CR LF | Internet standard newline




pyparsing