我正在尝试为一组句子编写语法,并使用Pyparsing来解析它。这些句子告诉我们在文本文件中搜索什么以及如何搜索,我需要将它们转换为相应的正则表达式搜索代码。但是,有一些元素并非真正没有上下文,因此,我发现很难为它们编写生产规则。基本上,我的目标是解析这些句子,然后为它们写正则表达式。
在这些句子中找到的一些上下文敏感元素的例子 -
LINE_CONTAINS phrase1 BEFORE {phrase2 AND phrase3}
表示行phrase1
可以在phrase2
和phrase
之前到达。同样适用于AFTER
LINE_CONTAINS abc JOIN xyz
表示搜索abc xyz
和abc-xyz
以及abcxyz
LINE_CONTAINS abcd AND xyzw
表示该行应同时包含abcd
和xyzw
示例 - LINE_CONTAINS we transfected BEFORE {sirna} AND gene AND LINE_STARTSWITH Therefore
这应该转换为re.search(r'(^!Therefore.*?we transfected.*?sirna)' and re.search(r'(gene))
(我相信可以制作更好的正则表达式)
我开始为句子写语法 -
Beginner = LINE_CONTAINS|LINE_STARTSWITH|other line beginners...
Phrase = word+
sentence = Beginner + phrase + AND + Beginner + phrase
这些图案/元素中的任何一个都可以在任何行中出现,也可以组合使用。像
LINE_CONTAINS {x AND y} BEFORE {a letter AND b letter} AND zoo people AND LINE_STARTSWITH dfg
所以我的问题是 -
如何编写可以处理此类上下文敏感元素的语法规则,因为任何句子都可以使用它们(尽管大多数句子不会有多个,但仍然如此)。 我应该为多种句子编写规则,每种句子都包含这些不同类型的元素之一。或者我应该编写一个包含所有这些元素的规则并将它们作为可选项。
我确实理解这些元素可能不完全是上下文相关的,但我的问题在于无法为BEFORE
,JOIN
等元素编写独立的生产规则。我如何最好在生产规则中定义它们的功能?
编辑 - 短语可以是多字
答案 0 :(得分:2)
在我看来,这是一个非常简单的语法。我认为你是“过度思考”这个问题。
看看你的例子,我看到了:
a JOIN b
a BEFORE b
a AND b
a OR b
STARTSWITH a
这些只是运营商。一元运算符(STARTSWITH)类似于python中的~x
或-x
。二元运算符(JOIN,BEFORE,AND,OR)与python中的x + y
或x in y
类似。
我认为CONTAINS
不是一个操作员,而是一个占位符。几乎除了STARTSWITH
之外的所有内容都是隐式包含的。所以这有点像一元加运算符:定义,理解,允许,但没用。
无论如何,弄清楚运营商是什么(列表)。弄清楚它们是一元(startwith)还是二元(和)。然后弄清楚他们的precedence和associativity是什么。
一旦你知道了这些信息,你就可以构建你的解析器:你将知道关键词,并知道如何在语法中安排关键词。
答案 1 :(得分:1)
对你的语法做一些猜测,这是一个粗略的刺。请注意我如何从短语表达式中单独定义行表达式:
LINE_CONTAINS transfected BEFORE {sirna} AND gene AND LINE_STARTSWITH Therefore
[[['LINE_CONTAINS', [[['transfected', 'BEFORE', 'sirna'], 'AND', 'gene']]], 'AND', ['LINE_STARTSWITH', ['Therefore']]]]
[0]:
[['LINE_CONTAINS', [[['transfected', 'BEFORE', 'sirna'], 'AND', 'gene']]], 'AND', ['LINE_STARTSWITH', ['Therefore']]]
[0]:
['LINE_CONTAINS', [[['transfected', 'BEFORE', 'sirna'], 'AND', 'gene']]]
- line_directive: 'LINE_CONTAINS'
- phrase: [[['transfected', 'BEFORE', 'sirna'], 'AND', 'gene']]
[0]:
[['transfected', 'BEFORE', 'sirna'], 'AND', 'gene']
[0]:
['transfected', 'BEFORE', 'sirna']
[1]:
AND
[2]:
gene
[1]:
AND
[2]:
['LINE_STARTSWITH', ['Therefore']]
- line_directive: 'LINE_STARTSWITH'
- phrase: ['Therefore']
将您的样本解析为:
phrase_word
{}
以负向前瞻开头,以避免意外处理类似' LINE_STARTSWITH'作为短语。我还将引用的字符串添加为有效的短语单词,因为您永远不知道您的搜索何时必须实际包含字符串" LINE_STARTSWITH"。
您使用infixNotation
进行短语表达式分组,lpar
具有可选的rpar
和(
参数,以覆盖)
和{{的默认值1}}。
从这里,您可以查看其他infixNotation
示例(例如,在pyparsing wiki示例页面上的SimpleBool.py),将其转换为相应的正则表达式生成代码。