Преобразование определения одной из функций в определение эквивалентной функции - Lisp
Формулировка задачи:
Есть грамматика некоторого языка
функция ::= имя_функции "(" список_параметров ")" "=>" "{" выражение "}"
список_параметров ::= параметр | параметр "," список_параметров
выражение ::= терм | условный_оператор
условный_оператор ::= условие "?" выражение ":" выражение
условие ::= терм ( "<" | "=" | ">" ) терм
терм ::= параметр | целое_число
Имя функции и название параметра состоят из латинских символов.
Обратите внимание, что количество параметров функции и глубина вложения условных операторов не ограничены.
На языке, который описывается данной грамматикой, можно определять различные функции.
Ваша задача состоит в том, что бы написать на языке Лисп программу, преобразующую определение одной из таких функций (заранее неизвестно, какой) в определение эквивалентной функции на языке Лисп.
Результирующая функция для каждого набора аргументов должна выдавать тот же результат, что и исходная функция - в этом смысл эквивалентности.
Например, для исходной функции f( x ) => {10} определение эквивалентной функции будем таким: (defun f (x) 10) .
Определение исходной функции будет передано в виде списка, для вышеприведённого примера такого: ( f \( x \) => { 10 } ) . Каждая лексема будет представлять отдельный элемент списка, так что лексическим анализом заниматься не нужно.
Для простоты давайте считать, что определение исходной функции не содержит ошибок и может быть успешно преобразовано в описание Лисп-функции.
Примеры входных и выходных данных
>>> (tt '( func \( x \, y \) => { x > y ? -1 \: 1 } ) ) ; "func(x, y) => { x>y ? -1 : 1 }"
( defun func ( x y ) ( if ( > x y ) -1 1 ) )
>>> ( tt '( max \( x \, y \, z \) => { x > y ? x > z ? x \: z \: y > z ? y \: z } ) ); "max( x, y, z ) => { x > y ? x > z ? x : z : y > z ? y : z }"
( defun max (x y z) ( if (> x y) (if ( > x z ) x z) ( if (> y z) y z) ))
Решение задачи: «Преобразование определения одной из функций в определение эквивалентной функции»
textual
Листинг программы
(ns aeon.core (:require [instaparse.core :as insta])) (def parser (insta/parser "function = name <'('> params <')'> <'=>'> <'{'> expr <'}'> name = #'\\p{Alpha}+' params = param | param <','> params param = #'\\p{Alpha}+' expr = term | cond cond = clause <'?'> expr <':'> expr clause = term ('<' | '=' | '>') term <term> = param | int int = #'[-]?\\d+'" :auto-whitespace :standard)) (defn transform [s] (let [clause (fn [x op y] (case op "<" `(< ~x ~y) ">" `(> ~x ~y) "=" `(= ~x ~y))) transform-map {:int read-string :clause clause :cond (fn [clause x y] `(if ~clause ~x ~y)) :expr identity :param read-string :params vector :name read-string :function (fn [name args body] `(fn ~name ~((comp vec flatten) args) ~body))}] (->> (parser s) (insta/transform transform-map) eval))) ((transform "func(x, y) => {x < y ? x : y}") 2 10) ;; => 2 ((transform "func(x, y) => {x > y ? 1 : -1}") 2 10) ;; => -1 ((transform "func(x) => {10}") 5) ;; => 10 ((transform "func(x,y,z) => {x > y ? x > z ? x : z : y > z ? y : z}") 1 7 4) ;; => 7
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д