-2

私は文脈自由文法に取り組んでおり、(文法の最終値)を返す関数があります

例:私は、say((A cat)(B happy np)(AB sad))を呼び出すことにより、(AB)になる非終端関数を持っているため、技術的にはAとBは文法の非終端記号です。今、私はターミナルを手に入れたいです(猫幸せnp悲しい)

(define terminals
  (lambda (lsts)
    (cond
     ((null? lsts) lsts)
     ((not(member? (car(car lsts)) (n-terminals lsts)))
      (cons (car(car lsts)) (terminals (car (cdr lsts)))))
     (else (terminals (cdr lsts))))))

PS:n端子の機能は上で説明されています。メンバー?アイテムがリストのメンバーである場合はtrueを返し、それ以外の場合はfalseを返すブール関数です。私の関数は空のlstを返します。ここで何が欠けていますか?

4

1 に答える 1

1

問題は、終端記号を見つけたときに何をするかです。ここには、実際には 2 つの別個の問題があります。

まず、各ルールの最初のシンボルだけを見ます。変数lstsはルールのリストです。各ルールはシンボルのリストです。したがって(car (car lsts))、最初のルールの最初のシンボルを取得します。

2 番目の問題は、終端記号を見つけた後に再帰する方法です。通常、terminalsリストのリストを渡します。ただし、終端記号 (つまり、で始まる記号) を見つけた後は、(member? ...)それを渡します(car (cdr lsts))lstsがリストのリストであることはわかっています。リスト(cdr lsts)のリスト (またはもちろん空のリスト) も同様です。これ(car (cdr lsts))は単なる通常のリストであることを意味します。

この問題を解決する最も簡単な方法は、2 つの関数に分割することだと思います。まず、単一のルールから端末を取得する関数を作成します。つまり、入力全体に注目するのではなく、 の((A cat) (B happy np) (A B sad))ように一度に 1 つのルールに注目し(B happy np)ます。したがって、 が与えられたときに が得られる関数を書き(B happy np)ます(happy np)。次に、この関数をすべてのルールに適用しlsts、すべての出力を結合する関数を作成します。(appendここで関数が役立つ場合があります。)

これを 2 つの別個の関数で記述すると、問題を検討しやすくなります。結果のコードもよりシンプルで読みやすくなり、これはおまけです。

また、スタイルとは関係のない問題:書くことができます(そして書くべきです)

(define foo
  (lambda (args) ...))

なので

(define (foo args)
  ...)

これら 2 つの表現は同じ意味を持ちますが、2 番目の方が読みやすく、より頻繁に使用されます。

編集:コメントで言ったように、最初に非端末のリストを計算し、それを一度に1行ずつ実行する関数に使用します。2 つの関数をネストし、Scheme のレキシカル スコープを利用することで、これを簡単に使用できます。

(define (terminals rules)
  (let ((non-terminals (n-terminals rules)))
    (define (helper rule) ; this takes a rule and returns all its terminal symbols
       ... ; you can use non-terminals in here
    )
    ; now here you have to call helper on every rule and combine the results
  ))

別のオプションは、ネストされていない 2 つの関数に分割し、非終端記号のリストを渡すことです。

(define (terminals-from-rule rule non-terminals)
  ... ; implement, using non-terminals as the list of non-terminal symbols
)
(define (terminals rules)
  ... ; here you need to calculate the list of non-terminals and pass
      ; it into each call to terminals-from-rule along with the rule.
)
于 2012-10-12T16:59:49.557 に答える