2013-05-01 66 views
4

我想使用NTLK语法和分析算法,因为它们看起来很简单。虽然,我不能找到一种方法来正确地匹配字母数字串,像:在nltk语法中匹配字母数字字符串

import nltk 
grammar = nltk.parse_cfg (""" 
# Is this possible? 
TEXT -> \w* 
""") 

parser = nltk.RecursiveDescentParser(grammar) 

print parser.parse("foo") 

是否有一个简单的方法来实现这一目标?

+0

我不知道这是可能的,但并不实现CFG子文法匹配字母数字字符。试图做到这一点的背景是什么? – dmh 2013-07-03 15:04:36

+1

NLTK的'parse_cfg'不够健壮,无法让你做'\ w *' – alvas 2013-12-15 13:28:35

回答

2

这将是非常困难干净。基本解析器类依赖于精确匹配或生产RHS来弹出内容,所以它需要子类化和重写解析器类的大部分。我刚才尝试了一下功能语法课,然后放弃了。

我所做的更多的是黑客行为,但基本上,我首先从文本中提取正则表达式匹配,然后将它们作为生成语句添加到语法中。如果您使用的是大文法,它会很慢,因为它需要重新计算每个调用的语法和解析器。

import re 

import nltk 
from nltk.grammar import Nonterminal, Production, ContextFreeGrammar 

grammar = nltk.parse_cfg (""" 
S -> TEXT 
TEXT -> WORD | WORD TEXT | NUMBER | NUMBER TEXT 
""") 

productions = grammar.productions() 

def literal_production(key, rhs): 
    """ Return a production <key> -> n 

    :param key: symbol for lhs: 
    :param rhs: string literal: 
    """ 
    lhs = Nonterminal(key) 
    return Production(lhs, [rhs]) 

def parse(text): 
    """ Parse some text. 
""" 

    # extract new words and numbers 
    words = set([match.group(0) for match in re.finditer(r"[a-zA-Z]+", text)]) 
    numbers = set([match.group(0) for match in re.finditer(r"\d+", text)]) 

    # Make a local copy of productions 
    lproductions = list(productions) 

    # Add a production for every words and number 
    lproductions.extend([literal_production("WORD", word) for word in words]) 
    lproductions.extend([literal_production("NUMBER", number) for number in numbers]) 

    # Make a local copy of the grammar with extra productions 
    lgrammar = ContextFreeGrammar(grammar.start(), lproductions) 

    # Load grammar into a parser 
    parser = nltk.RecursiveDescentParser(lgrammar) 

    tokens = text.split() 

    return parser.parse(tokens) 

print parse("foo hello world 123 foo") 

这里有更多的背景,其中这是在NLTK用户群在谷歌组讨论:https://groups.google.com/d/topic/nltk-users/4nC6J7DJcOc/discussion