Tema 12: Analizadores sintácticos funcionales

Librerías auxiliares

import Test.QuickCheck
import Data.Char

1 Analizadores sintácticos

Analizadores sintácticos

2 El tipo de los analizadores sintácticos

Opciones para el tipo de los analizadores sintácticos

type Analizador = String -> Tree 
type Analizador = String -> (Tree,String)
type Analizador = String -> [(Tree,String)]
type Analizador a = String -> [(a,String)] 

3 Analizadores sintácticos básicos

Analizadores sintácticos básicos: resultado

analiza :: Analizador a -> String -> [(a,String)]
analiza a cs = a cs
ghci> analiza (resultado 1) "abc"
[(1,"abc")]
resultado :: a -> Analizador a
resultado v =  \xs -> [(v,xs)]

Analizadores sintácticos básicos: fallo

ghci> analiza fallo "abc"
[]
fallo :: Analizador a
fallo =  \xs -> []

Analizadores sintácticos básicos: elemento

ghci> analiza elemento ""
[]
ghci> analiza elemento "abc"
[('a',"bc")]
elemento :: Analizador Char
elemento =  \xs -> case xs of
                     [] -> []
                     (x:xs) -> [(x , xs)]

4 Composición de analizadores sintácticos

4.1 Secuenciación de analizadores sintácticos

infixr 5 >*>
(>*>) :: Analizador a -> (a -> Analizador b) -> 
         Analizador b
p >*> f = \ent -> case analiza p ent of
                       []        -> []
                       [(v,sal)] -> analiza (f v) sal
primeroTercero "abel"  ==  [(('a','e'),"l")]
primeroTercero "ab"    ==  []
primeroTercero :: Analizador (Char,Char)
primeroTercero = 
    elemento >*> \x ->
    elemento >*> \_ ->
    elemento >*> \y ->
    resultado (x,y)

4.2 Elección de analizadores sintácticos

Main*> analiza (elemento +++ resultado 'd') "abc"  
[('a',"bc")]
Main*> analiza (fallo +++ resultado 'd') "abc"     
[('d',"abc")]
Main*> analiza (fallo +++ fallo) "abc"             
[]
(+++) :: Analizador a -> Analizador a -> Analizador a
p +++ q = \ent -> case analiza p ent of
                    []        -> analiza q ent
                    [(v,sal)] -> [(v,sal)]

5 Primitivas derivadas

analiza (sat isLower) "hola"  ==  [('h',"ola")]
analiza (sat isLower) "Hola"  ==  []
sat :: (Char -> Bool) -> Analizador Char
sat p = elemento >*> \x ->
        if p x then resultado x else fallo
analiza digito "123"  ==  [('1',"23")]
analiza digito "uno"  ==  []  
digito :: Analizador Char
digito = sat isDigit
analiza minuscula "eva"  ==  [('e',"va")]
analiza minuscula "Eva"  ==  []
minuscula :: Analizador Char
minuscula = sat isLower
analiza mayuscula "Eva"  ==  [('E',"va")]
analiza mayuscula "eva"  ==  []
mayuscula :: Analizador Char
mayuscula = sat isUpper
analiza letra "Eva"  ==  [('E',"va")]
analiza letra "eva"  ==  [('e',"va")]
analiza letra "123"  ==  []
letra :: Analizador Char
letra = sat isAlpha
analiza alfanumerico "Eva"   ==  [('E',"va")]
analiza alfanumerico "eva"   ==  [('e',"va")]
analiza alfanumerico "123"   ==  [('1',"23")]
analiza alfanumerico " 123"  ==  []
alfanumerico :: Analizador Char
alfanumerico = sat isAlphaNum
analiza (caracter 'E') "Eva"  ==  [('E',"va")]
analiza (caracter 'E') "eva"  ==  []
caracter :: Char -> Analizador Char
caracter x = sat (== x)
analiza (cadena "abc") "abcdef"  ==  [("abc","def")]
analiza (cadena "abc") "abdcef"  ==  []
cadena :: String -> Analizador String
cadena []     = resultado []
cadena (x:xs) = caracter x >*> \x  ->
                cadena xs  >*> \xs ->
                resultado (x:xs)
analiza (varios digito) "235abc"  ==  [("235","abc")]
analiza (varios digito) "abc235"  ==  [("","abc235")]
varios :: Analizador a -> Analizador [a]
varios p  = varios1 p +++ resultado []
analiza (varios1 digito) "235abc"  ==  [("235","abc")]
analiza (varios1 digito) "abc235"  ==  []
varios1 :: Analizador a -> Analizador [a]
varios1 p = p        >*> \v  ->
            varios p >*> \vs ->
            resultado (v:vs)
ghci> analiza ident "lunes12 de Ene"  
[("lunes12"," de Ene")]
ghci> analiza ident "Lunes12 de Ene"  
[]
ident :: Analizador String
ident =  minuscula           >*> \x  ->
         varios alfanumerico >*> \xs ->
         resultado (x:xs)
analiza nat "14DeAbril"   ==  [(14,"DeAbril")]
analiza nat " 14DeAbril"  ==  []
nat :: Analizador Int
nat = varios1 digito >*> \xs ->
      resultado (read xs)
analiza espacio "    a b c"  ==  [((),"a b c")]
espacio :: Analizador ()
espacio = varios (sat isSpace) >*> \_ -> 
          resultado ()

6 Tratamiento de los espacios

ghci> analiza (unidad nat) " 14DeAbril"     
[(14,"DeAbril")]
ghci> analiza (unidad nat) " 14   DeAbril"  
[(14,"DeAbril")]
unidad :: Analizador a -> Analizador a
unidad p = espacio >*> \_ ->
           p       >*> \v ->
           espacio >*> \_ ->
           resultado v
ghci> analiza identificador "  lunes12  de Ene"
[("lunes12","de Ene")]  
identificador :: Analizador String
identificador = unidad ident
analiza natural "  14DeAbril"  ==  [(14,"DeAbril")]  
natural :: Analizador Int
natural =  unidad nat
ghci> analiza (simbolo "abc") "  abcdef"  
[("abc","def")]  
simbolo :: String -> Analizador String
simbolo xs =  unidad (cadena xs)
ghci> analiza listaNat " [  2,  3, 5   ]"  
[([2,3,5],"")]
ghci> analiza listaNat " [  2,  3,]"       
[]
listaNat :: Analizador [Int]
listaNat = simbolo "["          >*> \_ ->
           natural              >*> \n ->
           varios (simbolo ","  >*> \_ ->
                   natural)     >*> \ns ->
           simbolo "]"          >*> \_ ->
           resultado (n:ns)

7 Analizador de expresiones aritméticas

Expresiones aritméticas

Gramáticas de las expresiones aritméticas: Gramática 1

expr ::=  expr + expr | expr * expr | (expr) | nat 
nat  ::=  0 | 1 | 2 | ...

Gramáticas de las expresiones aritméticas: Gramática 2

expr    ::=  expr + expr | term 
term    ::=  term * term | factor 
factor  ::=  (expr) | nat 
nat     ::=  0 | 1 | 2 | dots

Árbol de análisis sintáctico de 2*3+5 con la gramática 2

Gramáticas de las expresiones aritméticas: Gramática 3

expr   ::= term + expr | term 
term   ::= factor * term | factor 
factor ::= (expr) | nat 
nat    ::= 0 | 1 | 2 | dots

Árbol de análisis sintáctico de 2+3+5 con la gramática 3

Gramáticas de las expresiones aritméticas: Gramática 4

expr   ::= term (+ expr | epsilon) 
term   ::= factor (* term | epsilon) 
factor ::= (expr) | nat 
nat    ::= 0 | 1 | 2 | dots

donde ε es la cadena vacía.

Analizador de expresiones aritméticas

analiza expr "2*3+5"     ==  [(11,"")]
analiza expr "2*(3+5)"   ==  [(16,"")]
analiza expr "2+3*5"     ==  [(17,"")]
analiza expr "2*3+5abc"  ==  [(11,"abc")]
expr :: Analizador Int
expr = term              >*> \t ->
       (simbolo "+"      >*> \_ ->              
        expr             >*> \e ->
        resultado (t+e))
       +++ resultado t
analiza term "2*3+5"      ==  [(6,"+5")]
analiza term "2+3*5"      ==  [(2,"+3*5")]
analiza term "(2+3)*5+7"  ==  [(25,"+7")]
term :: Analizador Int
term =  factor            >*> \f ->
        (simbolo "*"      >*> \_ ->
         term             >*> \t ->
         resultado (f*t))
        +++ resultado f
analiza factor "2*3+5"      ==  [(2,"*3+5")]
analiza factor "(2+3)*5"    ==  [(5,"*5")]
analiza factor "(2+3*7)*5"  ==  [(23,"*5")]
factor :: Analizador Int
factor =  (simbolo "("  >*> \_ ->
           expr         >*> \e ->
           simbolo ")"  >*> \_ ->
           resultado e)
          +++ natural
valor "2*3+5"      ==  11
valor "2*(3+5)"    ==  16
valor "2 * 3 + 5"  ==  11
valor "2*3x"       ==  *** Exception: sin usar x
valor "-1"         ==  *** Exception: entrada no valida
valor :: String -> Int
valor xs = case (analiza expr xs) of
             [(n,[])]  -> n
             [(_,sal)] -> error ("sin usar " ++ sal)
             []        -> error "entrada no valida"

8 Bibliografía



Universidad de Sevilla

José A. Alonso Jiménez
Grupo de Lógica Computacional
Dpto. de Ciencias de la Computación e I.A.
Universidad de Sevilla