あなたの最善の策は、実際にこれを適切なプログラミング言語でコーディングすることです。あなたが言うように、「かなり複雑な」ルールをコーディングするのは非常に難しいので、CFGはやり過ぎです。たとえば、文法は物事の数について話すのにはあまり適していません。
たとえば、そのような言語で「さくらんぼの数は>他のオブジェクトの数」をどのようにコーディングしますか?あなたがプログラムを提供している人はどのようにそうするのでしょうか?CFGはそのような概念を簡単に表現することはできず、正規表現は一気に表現することはできません。
答えは、スロットマシンが英語の文章を作ろうとしない限り、文法はこのタスクには適切ではないということです。
また、2つ以上の「賞品シーケンス」が一致した場合に何が起こるかを考慮する必要があります。あなたが最高の賞品を配りたいと仮定すると、あなたは認識者の順序付けられたリストを必要とします。これは、任意の関数に加えて、(たとえば)正規表現を使用してレコグナイザーをコーディングできないということではありません。一般的なCFG解析はやり過ぎだと言っているだけです。なぜなら、CFGが正規言語(つまり正規表現)を超えるのは、任意の深さの解析ツリー(レベルN以上のネストされた括弧など)を考慮する機能であるためです。あなたが気にしていること。
これは、たとえば正規表現を許可したくないということではありません。パーサジェネレータを使用してチェリーバナナとナシを含む正規表現を認識することで、その作業を簡単に行うことができます。http://en.wikipedia.org/wiki/Comparison_of_parser_generatorsを参照してください。再帰下降パーサー(特にトークンの長さが制限されている場合は、CFGを気にしないと仮定します)。
たとえば、これを擬似コードで実装する方法を次に示します(理想的には、静的に型チェックされた言語を使用し、リストを適切に操作します。これは頭から離れては考えられません)。
rules = []
function Rule(name, code) {
this.name = name
this.code = code
rules.push(this) # adds them in order
}
##########################
Rule("All the same", regex(.*))
Rule("No two-in-a-row", function(list, counts) {
not regex(.{2}).match(list)
})
Rule("More cherries than anything else", function(list, counts) {
counts[cherries]>counts[x] for all x in counts
or
sorted(counts.items())[0]==cherries
or
counts.greatest()==cherries
})
for token in [cherry, banana, ...]:
Rule("At least 50% "+token, function(list, counts){
counts[token] >= list.length/2
})