解析标记数据字符串,而不是纯字符串

问题描述

您通常使用 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 中运行良好。