Добавление элементов в список - Lisp
Формулировка задачи:
Здравствуйте! Нужно многократно изменять значение списка в цикле (добавлять в него новые списки). Вне цикла данный код работает (формирование новых списков и добавление в главный список), но в цикле - нет (результат NIL).
Подскажите, в чем дело? Спасибо.
Листинг программы
- (defun remove-left-recursion (g &optional g2)
- (setq v '(X Y Z))
- (loop for i in g do
- (if (equal (car i) (cadr i))
- (loop for j in g do
- (cond ((and (not (equal i j)) (equal (car i) (car j)))
- (cons (list (car v) (cddr i) (car v)) (cons (list (car v) (cddr i)) (cons (list (car i) (cdr j) (car v)) g2)))
- (remove (car v) v)
- )
- )
- )
- (cons i g2)
- )
- )
- )
- (remove-left-recursion '((S "a" B D) (S S "b" A) (S "c" C B)))
Решение задачи: «Добавление элементов в список»
textual
Листинг программы
- (defparameter *spare-nonterminals* '(X Y Z) "A stock of unused nonterminals")
- (defun new-nonterminal ()
- "Generate an unused nonterminal"
- (pop *spare-nonterminals*))
- ;;; Утилиты для продукций
- (defun make-production (&key lhs rhs)
- (cons lhs rhs))
- (defun lhs (production)
- (first production))
- (defun rhs (production)
- (rest production))
- ;;; Проба пера -- удаление левой рекурсии для одного-единственного символа S
- (defun remove-left-recursion-s (productions)
- ;; собираю сначала продукции, в которых есть рекурсия, потом с левой частью S, но без рекурсии
- (let ((left-recurrent (remove-if-not (lambda (p)
- (and (eq 's (lhs p))
- (eq (lhs p) (first (rhs p)))))
- productions))
- (associated (remove-if-not (lambda (p)
- (and (eq (lhs p) 's)
- (not (eq (lhs p) (first (rhs p))))))
- productions)))
- (let ((x (new-nonterminal)))
- ;; c1): беру все продукции без рекурсии и к правой части каждой из них добавляю Х
- (let ((c1 (mapcar (lambda (p) (make-production :lhs (lhs p) :rhs (append (rhs p) (list x)))) associated))
- ;; c2): беру все продукции с рекурсией и отбрасываю первый элемент в правой части
- (c2 (mapcar (lambda (p) (make-production :lhs x :rhs (rest (rhs p)))) left-recurrent))
- ;; c3): беру все продукции с рекурсией, отбрасываю первый элемент в правой части и добавляю Х
- (c3 (mapcar (lambda (p) (make-production :lhs x :rhs (append (rest (rhs p)) (list x)))) left-recurrent)))
- ;; объединяю полученное по предыдущим правилам. Мне, helter-у, можно nconc-ем
- (nconc c1 c2 c3)))))
- > (remove-left-recursion-s '((s "a" b d) (s s "b" a) (s "c" c b)))
- ((S "a" B D X) (S "c" C B X) (X "b" A) (X "b" A X))
Объяснение кода листинга программы
В этом коде:
- Создается список
*spare-nonterminals*
со значением(X Y Z)
, который представляет собой запас нетерминалов. - Определена функция
new-nonterminal()
, которая удаляет первый элемент из*spare-nonterminals*
и возвращает его. - Определены функции
make-production()
,lhs()
иrhs()
, которые используются для работы с продукциями. - Определена функция
remove-left-recursion-s()
, которая удаляет левую рекурсию из списка производств. - В функции
remove-left-recursion-s()
сначала создаются два списка:left-recurrent
, содержащий производства с левой рекурсией, иassociated
, содержащий производства с символомs
без рекурсии. - Затем создается новый нетерминал
x
с помощью функцииnew-nonterminal()
. - В функции
remove-left-recursion-s()
создаются три списка:c1
,c2
иc3
, которые содержат производства без рекурсии, с рекурсией без первого элемента в правой части и с рекурсией без первого элемента в правой части, соответственно. - Наконец, списки
c1
,c2
иc3
объединяются с помощью функцииnconc()
, и результат возвращается. Код принимает на вход список(s
ab d) (s s
ba) (s
cc b)
, и после удаления левой рекурсии результат будет(S
aB D X) (S
cC B X) (X
bA) (X
bA X)
.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д