问题描述
您通常使用 Lark/Python 或 DCG/Prolog 等解析器解析文本。
我所拥有的是标记数据字符串,从某种意义上说,它仍然是单词序列,但实际上是元组列表。
示例:
word1 word2 ... ==process==> [(word1,tag1),(word2,tag5),(w3,t3) ...] ==parser==> struct[ predicate1(word2,word5),p2(w2,w1),...]
我想以与普通字符串类似的方式解析它,即使用语法和东西.. 即匹配主要基于标记属性,有时也基于单词本身。
因此,我现在正在构建元组列表,将来它可能是树/ast 列表。 目前我只解析单个句子,一个一个。
这是标记化结构的样子(我通过 spacy 传递它):
You will have to join us before the match starts.
[('You','PRON','nsubj'),('will','VERB','aux'),('have','AUX','ROOT'),('to','PART',('join','xcomp'),('us','dobj'),('before','ADP','mark'),('the','DET','det'),('match','NOUN',('starts','advcl'),('.','PUNCT','punct')]
我将来可能会添加更多标签......这将成为预解析阶段的一部分。
任何适用于 Python 或最终适用于 Prolog 的解决方案。 目前我选择了 Python,但我仍在试验中。
Ex 语法(伪代码):
Sentence : ....
SVO : token.nsubj token*? token.root token*? token.pobj { sent += svo(root,nsubj,pobj) }
adj : token.adj { sent += adj(word) }
解决方法
在 DCG 中,列表元素是通用的,因为它们是 Prolog 变量。然后你可以用最自然的方式表达模式匹配,使用匿名变量_
,你不关心实际值:
% SVO : token.nsubj token*? token.root token*? token.pobj { sent += svo(root,nsubj,pobj) }
svo(svo(Y,X,Z)) -->
[(X,'PRON',nsubj),_,(Y,'ROOT'),(Z,pobj)].
% adj : token.adj { sent += adj(word) }
adj(adj(X)) -->
[(X,'ADJ')].
对不起,我不知道 spacy 格式,请把我上面的猜测视为很可能是错误的......
关于标记的形成,恕我直言,直接将标记化处理到 DCG 中会更容易,而无需依赖词法分析器。当然,如果文件尺寸“合理”。我这样做是为了解析一些 MySQL 备份(普通 SQL,大约 10 ~ 30 MB)并且它在 SWI-Prolog 中运行良好。