M.P.I - 1998/99 - Trabalho Prático Nr. 4 | |
---|---|
[ DI/UM ] |
Este trabalho deve ser realizado por grupos com um máximo de três alunos. Deve ser entregue até ao dia 22 de Janeiro de 1999, na recepção do Departamento de Informática , e nele deve constar:
Um compilador é um programa que traduz uma linguagem dita de alto nível numa linguagem (dita de baixo nível ) que seja executável por uma máquina. Por exemplo, o gcc compila C/C++ em código objecto que corre numa variadade de arquitecturas.
Compiladores são normalmente programas complexos. Constam essencialmente de duas partes: o analisador sintático que lê o texto de entrada (o programa fonte a compilar) e cria uma sua representação interna, estruturada em árvore; e o gerador de código que converte essa representação interna em código executável. Note-se que tal representação intermédia pode ser usada para outros fins, por exemplo, para gerar uma listagem de qualidade ('pretty print') do programa fonte.
O projecto de compiladores é um assunto complexo que será assunto de outras disciplinas. Neste trabalho pretende-se apenas fazer uma introdução ao assunto, mostrando como tais programas se podem construir funcionalmente à custa de cata/ana/hilo-morfismos da linguagem em causa.
data Expressao = Num Int | Bop Expressao Op Expressao data Op = Op String
Analise o código apresentado, corra-o e escreva no seu relatório uma explicação do seu funcionamento, que deverá saber defender aquando da apresentação oral do relatório.
Valorização +: exprima este analisador sintático como um anamorfismo de String para Expressao.
Tp4> compile "2+4" ["PUSH 2", "PUSH 4", "ADD"] Tp4> compile "3*(2+4)" ["PUSH 3", "PUSH 2", "PUSH 4", "ADD", "MUL"] Tp4> compile "(3*2)+4" ["PUSH 3", "PUSH 2", "MUL", "PUSH 4", "ADD"] Tp4>
module Combinadores where depois :: (ReadS a) -> (ReadS b) -> ReadS (a,b) depois _ _ [] = [] depois r1 r2 input = [((x,y),i2) | (x,i1) <- r1 input , (y,i2) <- r2 i1] readSeq :: (ReadS a) -> ReadS [a] readSeq r input = case (r input) of [] -> [([],input)] l -> concat (map continua l) where continua (a,i) = map (c a) (readSeq r i) c x (xs,i) = ((x:xs),i) ou :: (ReadS a) -> (ReadS a) -> ReadS a ou r1 r2 input = (r1 input) ++ (r2 input) senao :: (ReadS a) -> (ReadS a) -> ReadS a senao r1 r2 input = case (r1 input) of [] -> r2 input l -> l readConst :: String -> ReadS String readConst c = (filter ((== c).fst)) . lex pcurvos = parentesis '(' ')' prectos = parentesis '[' ']' chavetas = parentesis '{' '}' parentesis :: Char -> Char -> (ReadS a) -> ReadS a parentesis _ _ _ [] = [] parentesis ap pa r input = do ((_,(x,_)),c) <- ((readConst [ap]) `depois` ( r `depois` ( readConst [pa]))) input return (x,c)
import Combinadores data Expressao = Num Int | Bop Expressao Op Expressao deriving Show data Op = Op String deriving Show -- Read para Exp's readOp :: String -> [(Op,String)] readOp input = do (x,y) <- lex input return ((Op x),y) readNum :: ReadS Expressao readNum = (map (\ (x,y) -> ((Num x), y))).reads readBinOp :: ReadS Expressao readBinOp = (map (\ ((x,(y,z)),t) -> ((Bop x y z),t))) . ((readNum `ou` (pcurvos readExp)) `depois` (readOp `depois` readExp)) readExp :: ReadS Expressao readExp = readBinOp `ou` ( readNum `ou` ( pcurvos readExp)) instance Read Expressao where readsPrec _ = readExp