Я недавно сделал что-то подобное в Python. Я рассмотрю только часть о структурах данных:
Каждая часть речи является либо списком частей речи (нетерминалом), либо просто одним словом (терминалом). Таким образом, вы можете создавать классы что-то вроде:
enum Type {
Sentence,
NounPhrase,
VerbPhrase,
Conjunction,
...
};
interface PartOfSpeech { };
class NonTerminal implements PartOfSpeech {
Type type;
List<PartOfSpeech> subparts;
};
class Terminal implements PartOfSpeech {
String word;
};
Это относительно нетипизированный: вашей программе нужно создавать только правильные их структуры (например, не делать VerbPhrase, состоящий из списка предложений - вы можете сделать это, но это бессмысленно!).
Альтернативный маршрут - определить более явную систему типов. Таким образом, вы можете определить классы для каждого типа части речи, например,
class VerbPhrase {
Verb verb;
AdverbPhrase adverb; /* optional */
...
};
Поскольку существует несколько способов составления глагольной фразы, вместо этого вы можете иметь классы для каждого типа:
interface VerbPhrase { };
class IntransitiveVerbPhrase implements VerbPhrase {
Verb verb;
AdverbPhrase adverb; /* optional */
};
class TransitiveVerbPhrase implements VerbPhrase {
Verb verb;
AdverbPhrase adverb; /* optional */
NounPhrase obj;
};
И так далее. Оптимальная степень явности типов на уровне Java может быть неочевидной с самого начала. Начните с написания чего-то, что обрабатывает простые предложения, и посмотрите, как оно выглядит.
В моем случае я создал классы для каждой части речевого типа, хотя каждый наследовал от Терминала или Нетерминала. Тогда у меня есть правила о том, как вы можете построить каждый тип. Для некоторых из них это немного запутанно, например
add_rule(NounPhrase, [Noun])
add_rule(NounPhrase, [RelativeNounWord])
add_rule(NounPhrase, [Noun, AdjectiveClause])
add_rule(NounPhrase, [Article, Noun])
add_rule(NounPhrase, [Article, Adjectives, Noun])
add_rule(NounPhrase, [Article, Noun, AdjectiveClause])
add_rule(NounPhrase, [Article, Adjectives, Noun, AdjectiveClause])
add_rule(NounPhrase, [Adjectives, Noun])
add_rule(NounPhrase, [Adjectives, Noun, AdjectiveClause])
add_rule(NounPhrase, [Article, Adjectives, Noun])
...
Это код для того, чтобы сказать: «Фраза существительное - это существительное. Или это относительное существительное. Или это существительное, за которым следует прилагательное AdjectiveClause. Или и т. Д.». Есть общий синтаксический анализатор, который пытается применить правила к списку слов, пока не получит дерево. (Вы можете увидеть грязный и недокументированный код на http://code.google.com/p/ejrh/source/browse/trunk/ircbot/nl.py.)
Здесь есть определенное количество комбинаторных взрывов. Возможно, его можно улучшить, введя новые типы частей речи или просто сделав некоторые его части необязательными: наличие правила для каждой возможной комбинации Article / Adjectives / AdjectiveClause / etc. присутствует / отсутствует, вы можете просто сделать их необязательными.