Advertisement
Guest User

Untitled

a guest
Apr 16th, 2019
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 15.01 KB | None | 0 0
  1. (define lexical-spec
  2. '((white-sp (whitespace) skip)
  3.   (comment ("#" (arbno (not #\newline))) skip)
  4.   (identifier ((arbno "@") letter (arbno (or letter digit "_" "?" "=" ))) symbol)
  5.   (number (digit (arbno digit)) number)
  6.   (number ("-" digit (arbno digit)) number)
  7.   (text ("\"" (or letter whitespace)
  8.               (arbno (or letter digit whitespace ":" "?" "=" "'")) "\"") string)
  9.   )
  10. )
  11.  
  12. (define grammar-spec
  13.   '( ;;Representa un programa de ruby    
  14.      (ruby-program ("ruby" exp-batch "end") a-program)
  15.      ;; Parte 2: Ruby con objetos
  16.      ;; cambiar a: (ruby-program ("ruby" (arbno class-decl) exp-batch "end") a-program)
  17.      
  18.      ;;Exp-batch: Representa una cerradura de expresiones
  19.      (exp-batch (expression (arbno expression)) a-batch)
  20.  
  21.      ;;Expresión:
  22.      (expression (simple-exp) a-simple-exp)
  23.      ;Declare-exp: al menos uno o más identificadores (deben inicializarse en 'nil)
  24.      (expression ("declare" identifier (arbno "," identifier) ";") declare-exp)
  25.      ;Puts-exp: al menos un valor compuesto para imprimir
  26.      (expression ("puts" (separated-list comp-value ",") ";") puts-exp)
  27.  
  28.      (expression ("if" comp-value (arbno "then") exp-batch
  29.                        (arbno "elsif" comp-value (arbno "then") exp-batch)
  30.                        (arbno "else" exp-batch) "end") if-exp)
  31.      
  32.      (expression ("unless" comp-value (arbno "then")
  33.                            exp-batch
  34.                            (arbno "else" exp-batch) "end") unless-exp)
  35.  
  36.      (expression ("while" comp-value (arbno "do") exp-batch "end") while-exp)
  37.      (expression ("until" comp-value (arbno "do") exp-batch "end") until-exp)
  38.  
  39.      (expression ("for" identifier "in" comp-value (arbno "do") exp-batch "end") for-exp)
  40.  
  41.      (expression ("def" identifier "(" (separated-list identifier ",") ")"
  42.                   exp-batch                  
  43.                   "end") function-exp)
  44.      (expression ("return" comp-value ";") return-exp)
  45.  
  46.      ;;Expresión simple
  47.      (simple-exp (simple-value complement ";") val-exp)
  48.      
  49.      ;;Complemento
  50.      (complement ("=" comp-value calls) assign)
  51.      (complement (assign-op comp-value calls) assign-and)
  52.      (complement (calls) comp-calls)
  53.  
  54.      ;;Calls
  55.      ;; 0 o muchas llamadas
  56.      (calls ((arbno call)) some-calls)
  57.  
  58.      ;;Call
  59.      (call (arguments) arguments-call)
  60.      ;; (call ("." identifier arguments) a-method-call) ;; Parte 2: Ruby con Objetos
  61.  
  62.      ;;Argumentos
  63.      ;; llamar una función puede tener 0 argumentos o muchos
  64.      (arguments ("(" (separated-list comp-value ",") ")") some-arguments)
  65.      ;; almenos 1 argumento para llamar acceder a un elemento en un arreglo
  66.      ;; máximo 2, ejemplo: a=[1,2,3]; a[1] #output 2; a[1,2] #output [2,3];
  67.      ;;                    a[1,2,3] #output Error
  68.      (arguments ("[" comp-value (arbno "," comp-value) "]") arr-arguments)
  69.  
  70.      ;;Valores compuestos
  71.      (comp-value (value) a-value)
  72.      (comp-value (un-op comp-value) unop-value)
  73.      
  74.      (value (simple-value) a-s-val)
  75.      (value ("(" comp-value val-compl ")") compl-val)
  76.  
  77.      ;;Complemento para valores
  78.      ;; llamadas a un valor:
  79.      ;; Ejemplo: sirve para ("hola"+(mundo())) donde mundo() retorna "mundo"
  80.      (val-compl (calls) val-call)
  81.      ;; operacion inorden con otro valor
  82.      (val-compl (bin-op comp-value) binop-val)
  83.  
  84.      ;; Valores simples
  85.      (simple-value (identifier) id-val)
  86.      (simple-value (number) int-val)
  87.      (simple-value (text) str-val) ;; recordar hacer string-trim cuando se evalue
  88.      (simple-value ("true") true-val)
  89.      (simple-value ("false") false-val)
  90.      (simple-value ("nil") nil-val)
  91.      ;; arreglo con 0 o muchos valores
  92.      (simple-value ("["(separated-list comp-value ",")"]") arr-val)
  93.      
  94.      ;;Operacion Inorden
  95.      (bin-op ("+") add)
  96.      (bin-op ("-") diff)
  97.      (bin-op ("*") mult)
  98.      (bin-op ("/") div)
  99.      (bin-op ("%") mod)
  100.      (bin-op ("**") pow)
  101.      (bin-op (">") great)
  102.      (bin-op (">=") great-eq)
  103.      (bin-op ("<") less)
  104.      (bin-op ("<=") less-eq)
  105.      (bin-op ("==") equal)
  106.      (bin-op ("!=") not-equal)
  107.      (bin-op ("and") and-op)
  108.      (bin-op ("&&") and-op)
  109.      (bin-op ("or") or-op)
  110.      (bin-op ("||") or-op)
  111.      ;;Rangos:
  112.      ;; Solo admite 2 argumentos, no se puede operar más de 1 vez
  113.      ;;Inclusivo: va hasta el limite superior
  114.      (bin-op ("..") in-range)
  115.      ;;Exclusivo: va hasta un step antes del limite superior
  116.      (bin-op ("...") ex-range)
  117.      ;; Ejemplo: (1..5) => (1 2 3 4 5)
  118.      ;; Ejemplo: (1...5) => (1 2 3 4)
  119.      ;; Ejemplo: ((1..5) .. 6) => Error
  120.      (bin-op ("step") st-range)
  121.      ;; Ejemplo: ((1..5) step 2) => (1 3 5)
  122.      ;; Ejemplo: ((1..5) step -1) => Error
  123.      ;; Ejemplo: ((-1..-5) step -2) => (-1 -3 -5)
  124.      ;; Ejemplo: ((1..-5) step 2) => Error
  125.      
  126.      ;;Operación asignación
  127.      (assign-op ("+=") add-eq)
  128.      (assign-op ("-=") diff-eq)
  129.      (assign-op ("*=") mult-eq)
  130.      (assign-op ("/=") div-eq)
  131.      (assign-op ("**=") pow-eq)
  132.  
  133.      ;;Operación unitaria
  134.      (un-op ("not") not-op)
  135.      (un-op ("!") not-op)
  136.  
  137.      ;;##############################################
  138.      ;; Parte 2: Ruby con objetos
  139.      ;(class-decl ("class" identifier
  140.      ;                     (arbno "<" identifier)
  141.      ;                     "attr" (separated-list ":" identifier ",") ";"
  142.      ;                     (arbno method-decl) "end") a-class-decl)
  143.  
  144.      ;(method-decl ("def" identifier "(" (separated-list identifier ",") ")"
  145.      ;             exp-batch                  
  146.      ;             "end") a-method-decl)
  147.  
  148.   )
  149. )
  150.  
  151. ;Construidos automáticamente:
  152.  
  153.  
  154. (sllgen:make-define-datatypes lexical-spec grammar-spec)
  155.  
  156. (define show-the-datatypes
  157.   (lambda () (sllgen:list-define-datatypes lexical-spec grammar-spec)))
  158.  
  159. ;*******************************************************************************************
  160. ;Parser, Scanner, Interfaz
  161.  
  162. ;El FrontEnd (Análisis léxico (scanner) y sintáctico (parser) integrados)
  163.  
  164. (define scan&parse
  165.   (sllgen:make-string-parser lexical-spec grammar-spec))
  166.  
  167. ;El Analizador Léxico (Scanner)
  168.  
  169. (define scan
  170.   (sllgen:make-string-scanner lexical-spec grammar-spec))
  171.  
  172. ;El Interpretador (FrontEnd + Evaluación + señal para lectura )
  173.  
  174. (define interpretador
  175.   (sllgen:make-rep-loop  "--> "
  176.     (lambda (pgm) (eval-program pgm))
  177.     (sllgen:make-stream-parser
  178.       lexical-spec
  179.       grammar-spec)))
  180.  
  181. ;*******************************************************************************************
  182. ;*******************************************************************************************
  183. ;Procedimientos
  184. (define-datatype procval procval?
  185.   (closure
  186.    (ids (list-of symbol?))
  187.    (body exp-batch?)
  188.    (env environment?)
  189.    ))
  190.  
  191. ;apply-procedure: evalua el cuerpo de un procedimientos en el ambiente extendido correspondiente
  192. (define apply-procedure
  193.   (lambda (proc args env)
  194.     (cases procval proc
  195.       (closure (ids body env)
  196.                ; |Evaluar el cuerpo de una función
  197. ;;quitar '
  198.                '(eval-exp-batch body (extend-env ids args env))
  199.                )
  200.       )
  201.     )
  202.   )
  203. ;*******************************************************************************************
  204.  
  205. (define (eval-program pgm)
  206.   (cases ruby-program pgm
  207.     (a-program (a-batch) (eval-exp-batch a-batch (empty-env)))
  208.     )
  209.   )
  210.  
  211. (define (eval-exp-batch batch env)
  212.   (cases exp-batch batch
  213.     (a-batch (exp exps) (eval-expressions exp exps env))
  214.     )
  215.   )
  216. ; eval-a-batch: exp exps env
  217. (define (eval-expressions exp exps env)
  218.   (let loop ((acc (eval-expression exp env))
  219.                              (exps exps))
  220.                     (if (null? exps)
  221.                         acc
  222.                         (loop (eval-expression (car exps)
  223.                                                env)
  224.                               (cdr exps)))))
  225.  
  226. (define (eval-expression exp env)
  227.   (cases expression exp
  228.     (puts-exp (vals)
  229.               ;TO-DO;
  230.               ; map: evaluar valores en la lista | for-each: imprimir valores evaluados
  231.               (eopl:pretty-print vals))
  232.     (else "TO DO")
  233.     ;simple-exp
  234.     ;declare-exp
  235.     ;if-exp
  236.     ;unless-exp
  237.     ;while-exp
  238.     ;until-exp
  239.     ;for-exp
  240.     ;function-exp
  241.     ;return-exp
  242.     )
  243.   )
  244.  
  245. ; eval-comp-value c-value env => (cases comp-value c-value (a-value ...) (unop-value ...))
  246. ;   evalúa un valor compuesto,
  247. ;     1) si es a-value llamaría eval-value,
  248. ;     2) si es unop-value: evaluaría la un-op y aplicaría sobre el llamado recursivo de eval-comp-value
  249. (define (eval-comp-value c-value env)
  250.   (cases comp-value c-value
  251.     (a-value (value) (eval-value value env))
  252.     (unop-value (un-op comp-value) (eval-comp-value (eval-value un-op env) env))))
  253.  
  254.  
  255. ; eval-value a-value env => (cases value a-value (simple-val ...) (compl-val ...))
  256. ;   evalúa un valor, tiene 2 casos:
  257. ;     1) un valor simple que se evaluaría con eval-simple-value
  258. ;     2) un valor con complemento, se llama eval-val-compl con c-val evaluado y
  259. ;        a-val-compl (c-val es un comp-value, a-val-compl es un val-compl)
  260.  
  261. ; eval-val-compl a-val a-val-compl env => (cases val-compl a-val-compl (val-call ...) (binop-val ...))
  262. ;  evalúa un complemento sobre un c-val, tiene 2 casos:
  263. ;    1) val-call(some-calls) entonces se tienen que aplicar los argumentos
  264. ;    2) binop-val(binop c-val) entonces se aplica una bin-op entre a.val y la evaluacion
  265. ;       de c-val (c-val es un comp-value)
  266.  
  267. ; eval-simple-value s-val env (cases simple-value s-val (id-val ...) (num-val ...) (true-val ...))
  268. ;   evalúa un valor simple, comprende los casos desde id-val hasta arr-val
  269. ;   para el caso de id-val se debe hacer apply-env
  270. (define (eval-simple-value s-val env)
  271.    (cases simple-value s-val
  272.     (id-val (identifier) (apply-env env identifier))
  273.     (int-val (number) number)
  274.     (str-val (text) text)
  275.     (true-val () 'true)
  276.     (false-val () 'false)
  277.     (nil-val () 'nil)
  278.     (arr-val (comp-values)(eval-comp-value (car comp-value) env))))
  279.  
  280. ;*******************************************************************************************
  281. ;Referencias
  282. (define-datatype reference reference?
  283.   (a-ref (position integer?)
  284.          (vec vector?)))
  285.  
  286. (define deref
  287.   (lambda (ref)
  288.     (primitive-deref ref)))
  289.  
  290. (define primitive-deref
  291.   (lambda (ref)
  292.     (cases reference ref
  293.       (a-ref (pos vec)
  294.              (vector-ref vec pos)))))
  295.  
  296. (define setref!
  297.   (lambda (ref val)
  298.     (primitive-setref! ref val)))
  299.  
  300. (define primitive-setref!
  301.   (lambda (ref val)
  302.     (cases reference ref
  303.       (a-ref (pos vec)
  304.              (vector-set! vec pos val)))))
  305.  
  306. ;*******************************************************************************************
  307. ;*******************************************************************************************
  308. ;Ambientes
  309.  
  310. ;definición del tipo de dato ambiente
  311. (define-datatype environment environment?
  312.   (empty-env-record)
  313.   (extended-env-record
  314.    (syms (list-of symbol?))
  315.    (vec vector?)
  316.    (env environment?)))
  317.  
  318. (define scheme-value? (lambda (v) #t))
  319.  
  320. ;empty-env:      -> enviroment
  321. ;función que crea un ambiente vacío
  322. (define empty-env  
  323.   (lambda ()
  324.     (empty-env-record)))       ;llamado al constructor de ambiente vacío
  325.  
  326.  
  327. ;extend-env: <list-of symbols> <list-of numbers> enviroment -> enviroment
  328. ;función que crea un ambiente extendido
  329. (define extend-env
  330.   (lambda (syms vals env)
  331.     (extended-env-record syms (list->vector vals) env)))
  332.  
  333. ;extend-env-recursively: <list-of symbols> <list-of <list-of symbols>> <list-of expressions> environment -> environment
  334. ;función que crea un ambiente extendido para procedimientos recursivos
  335. (define extend-env-recursively
  336.   (lambda (proc-names idss bodies old-env)
  337.     (let ((len (length proc-names)))
  338.       (let ((vec (make-vector len)))
  339.         (let ((env (extended-env-record proc-names vec old-env)))
  340.           (for-each
  341.             (lambda (pos ids body)
  342.               (vector-set! vec pos (closure ids body env)))
  343.             (iota len) idss bodies)
  344.           env)))))
  345.  
  346. ; |Ambiente recursivo para un solo procedimiento
  347.  
  348. (define (a-recursive-env a-proc-name ids body env)
  349.   (let ((vec (make-vector 1)))
  350.     (let ((env (extended-env-record (list a-proc-name) vec env)))
  351.           (vector-set! vec 0 (closure ids body env))
  352.           env)
  353.     )
  354.   )
  355.  
  356. ;iota: number -> list
  357. ;función que retorna una lista de los números desde 0 hasta end
  358. (define iota
  359.   (lambda (end)
  360.     (let loop ((next 0))
  361.       (if (>= next end) '()
  362.         (cons next (loop (+ 1 next)))))))
  363.  
  364. ;función que busca un símbolo en un ambiente
  365. (define apply-env
  366.   (lambda (env sym)
  367.     (deref (apply-env-ref env sym))))
  368.  
  369. (define apply-env-ref
  370.   (lambda (env sym)
  371.     (cases environment env
  372.       (empty-env-record ()
  373.                         (eopl:error 'Error "undefined local variable or method ~s" sym))
  374.       (extended-env-record (syms vals env)
  375.                            (let ((pos (rib-find-position sym syms)))
  376.                              (if (number? pos)
  377.                                  (a-ref pos vals)
  378.                                  (apply-env-ref env sym)))))))
  379.  
  380. ;*******************************************************************************************
  381. ;*******************************************************************************************
  382. ;Ambiente inicial
  383.  
  384. (define (init-env) (empty-env))
  385. ;*******************************************************************************************
  386. ;*******************************************************************************************
  387. ;Funciones Auxiliares
  388.  
  389. ; funciones auxiliares para encontrar la posición de un símbolo
  390. ; en la lista de símbolos de un ambiente
  391.  
  392. (define rib-find-position
  393.   (lambda (sym los)
  394.     (list-find-position sym los)))
  395.  
  396. (define list-find-position
  397.   (lambda (sym los)
  398.     (list-index (lambda (sym1) (eqv? sym1 sym)) los)))
  399.  
  400. (define list-index
  401.   (lambda (pred ls)
  402.     (cond
  403.       ((null? ls) #f)
  404.       ((pred (car ls)) 0)
  405.       (else (let ((list-index-r (list-index pred (cdr ls))))
  406.               (if (number? list-index-r)
  407.                 (+ list-index-r 1)
  408.                 #f))))))
  409.  
  410. ;*******************************************************************************************
  411. ;*******************************************************************************************
  412. ;;;Rangos
  413. (define-datatype range range?
  414.   (inclusive (start number?) (end number?) (step number?))
  415.   (exclusive (start number?) (end number?) (step number?))
  416.   )
  417.  
  418. (define (eval-range a-range)
  419.   (cases range a-range
  420.     (inclusive (start end step) (iota-range start end step))
  421.     (exclusive (start end step) (iota-range start (- end 1) step))
  422.     )
  423.   )
  424.  
  425. ;;Función que retorna una lista dado un inicio, un final, y un incremento
  426. (define iota-range
  427.   (lambda (start end step)
  428.     (cond [(or
  429.             (and (< start end) (> 0 step))
  430.             (and (> start end) (< 0 step)))
  431.            (eopl:error 'Step "bad step")]
  432.           [else
  433.            (let loop ((next start))
  434.              (if (= 0 (abs (- next end)))
  435.                  (list next)
  436.                  (cons next (loop (+ next step)))))]
  437.           )
  438.     ))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement