Лабораторная работа 8
Символьные преобразования
1. Парсер.
Нижеприведённый парсер преобразует строку, представляющую собой арифметическое выражение, в структуру с польской записью. Например, строка «4+X» парсер преобразует в структуру плюс(число(4),перем(X)). Такое преобразование необходимо осуществлять перед символьными операциями. Например, для калькуляторов, символьного дифференцирования, интегрирования, упрощения выражений, решения уравнений и т.п.
domains выраж = число(real); перем(string); унар_минус(выраж); плюс(выраж,выраж); минус(выраж,выраж); умнож(выраж,выраж); делен(выраж,выраж); степень(выраж,выраж); ln(выраж); cos(выраж);sin(выраж);tan(выраж). class predicates анализ:(string,выраж [out])determ. сканер:(string,string* [out]). парсер:(string*,string*,выраж) determ(i,i,o) (i,o,o). оп3:(string*,string* [out],выраж [out]) determ. опер3:(string*,string* [out],выраж,выраж [out]) determ. оп2:(string*,string* [out],выраж [out])determ. опер2:(string*,string* [out],выраж,выраж [out])determ. оп1:(string*,string*,выраж) determ(i,i,o) (i,o,o). опер1:(string*,string*,выраж,выраж) determ(i,o,i,o) (i,i,i,o). эл_выр:(string*,string* [out],выраж [out]) determ. clauses анализ(Строка,Выражение):-сканер(Строка,Спис), парсер(Спис,[],Выражение). сканер(Строка,[Лексема|Спис]):- fronttoken(Строка,Лексема,Строка1),!, сканер(Строка1,Спис). сканер(_,[]). парсер(Спис,Ост,Выраж):-оп1(Спис,Ост,Выраж). оп1(Спис,Ост,Выраж2):-оп2(Спис,Ост1,Выраж1), опер1(Ост1,Ост,Выраж1,Выраж2). опер1(["+"|Спис],Ост,Выраж1,Выраж3):-!,оп2(Спис,Ост1,Выраж2), опер1(Ост1,Ост,плюс(Выраж1,Выраж2),Выраж3). опер1(["-"|Спис],Ост,Выраж1,Выраж3):-!,оп2(Спис,Ост1,Выраж2), опер1(Ост1,Ост,минус(Выраж1,Выраж2),Выраж3). опер1(Спис,Спис,Выраж,Выраж). оп2(Спис,Ост,Выраж2):-оп3(Спис,Ост1,Выраж1), опер2(Ост1,Ост,Выраж1,Выраж2). опер2(["*"|Спис],Ост,Выраж1,Выраж3):-!, оп3(Спис,Ост1,Выраж2), опер2(Ост1,Ост,умнож(Выраж1,Выраж2),Выраж3). опер2(["/"|Спис],Ост,Выраж1,Выраж3):-!, оп3(Спис,Ост1,Выраж2), опер2(Ост1,Ост,делен(Выраж1,Выраж2),Выраж3). опер2(Спис,Спис,Выраж,Выраж). оп3(Спис,Ост,Выраж2):-эл_выр(Спис,Ост1,Выраж1), опер3(Ост1,Ост,Выраж1,Выраж2),!. опер3(["^"|Спис],Ост,Выраж1,Выраж3):-!, эл_выр(Спис,Ост1,Выраж2), опер3(Ост1,Ост,степень(Выраж1,Выраж2),Выраж3). опер3(Спис,Спис,Выраж,Выраж). эл_выр(["("|Спис],Ост,Выраж):- парсер(Спис,Ост1,Выраж),Ост1=[")"|Ост],!. эл_выр(["ln","("|Спис],Ост,ln(Выраж)):- парсер(Спис,Ост1,Выраж),Ост1=[")"|Ост],!. эл_выр(["sin","("|Спис],Ост,sin(Выраж)):- парсер(Спис,Ост1,Выраж),Ост1=[")"|Ост],!. эл_выр(["cos","("|Спис],Ост,cos(Выраж)):- парсер(Спис,Ост1,Выраж),Ост1=[")"|Ост],!. эл_выр(["tan","("|Спис],Ост,tan(Выраж)):- парсер(Спис,Ост1,Выраж),Ост1=[")"|Ост],!. эл_выр(["-",Лексема|Спис],Спис,число(-Число)):-Число=tryToReal(Лексема),!. эл_выр(["-"|Спис],Ост,унар_минус(Выраж)):-эл_выр(Спис,Ост,Выраж),!. эл_выр([Лексема|Спис],Спис,перем(Лексема)):-isName(Лексема),!. эл_выр([Лексема|Спис],Спис,число(tryToReal(Лексема))). run():-init(), Строка = "-Sin(1.3*X+0.6)", Строка1 = toLowerCase(Строка), анализ(Строка1,Выражение), write(Выражение),nl, _=readchar(),!; write("Ошибка"),nl, _=readchar().
Задание 1. Исследовать парсер на различных входных строках и составить описание каждого предиката.
Задание 2. Написать программу для вычисления выражений, не содержащих переменные. Подсказка: вычислитель имеет следующую логику:
вычислитель(число(Число),Число).
вычислитель(плюс(Выраж1,Выраж2),Значение):-
вычислитель(Выраж1,Значение1),вычислитель(Выраж2,Значение2),
Значение = Значение1 + Значение2.
вычислитель(минус(Выраж1,Выраж2),Значение):-
вычислитель(Выраж1,Значение1),вычислитель(Выраж2,Значение2),
Значение = Значение1 - Значение2.
Задание 3. Написать программу символьного дифференцирования. Подсказка: правила дифференцирования описываются так:
дифф(число(_),0).
дифф(перем(_),1).
дифф(степень(перем(X),число(N)),умнож(число(N), степень(перем(X),число(N-1)))).
дифф(sin(перем(X)), cos(перем(X)).
Здесь первый операнд описывает дифференцируемое выражение, второй операнд – дифференциал.
Задание 5. Написать программу преобразования польской записи в инфиксную запись.
Задание 4. Написать программу символьного интегрирования.