University project - weird problem
I've got a university project that demands me to do a program that receive a .c file and analyze its syntax using haskell. There are just a few things that I have to analyze: literal strings, identifiers (in the program: identificadores), constants (constantes), operators (operadores) and reserverd words(palavras reservadas) There are two major problems in the program: (1) I've got this guard in le_bloco: | x `elem` listS = do separador (x:xs) but it doesn't seem to work. Every time I enable it I recieve this in execution time (after calling verifica) ERROR - Cannot find "show" function for: *** Expression : verifica *** Of type : IO a So I've made one workaround that prints the separator but stops the program...I guess the problem is doing the recursivity (2) My second problem is: when I have one identifier or keyword alone in a line or it's the last element of it it just won't print my coment! this is the function: pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)} *Please help me solving those problems as soon as possible!* Here is the whole program: listO = ['+', '-', '*', '/', '%', '^', '=', '>', '<', '.', '|', '&', '!', '~'] listS = [';', '{', '(', ')', '}', '[', ']', ','] listC = ['0','1'..'9'] listCF = listC ++ ['.'] listA = listO ++ listS ++ [' '] listPC = ["auto","double","int","struct","break","else","long","switch","case", "enum","register","typedef","char","extern","return","union","const", "float","short","unsigned","continue","for","signed","void","default", "goto","sizeof","volatile","do","if","static","while"] verifica = do putStr ("Favor visualizar o codigo para ver os bugs e erros do programa\n") putStr ("Digite o nome do arquivo de entrada: ") arqent <- getLine texto <- readFile arqent le_bloco texto le_bloco (x:xs) | x `elem` listO = do operador (x:xs) | x `elem` listC = do cnum (x:xs) -- | x `elem` listS = do separador (x:xs) | x `elem` listS = do{ putStr[x] ; putStr " <separador>\n" } | x == '"' = litstr (xs) | x /= ' ' = pchave (x:xs) [] | x == ' ' = le_bloco xs | otherwise = do { putStr "Outro\n" ; le_bloco xs } separador (x:xs) | x `elem` listS = do{ putStr [x] ; separador xs} | otherwise = do{ putStr " <separador>\n" ; le_bloco xs} cnum (x:xs) | x `elem` listCF = do{ putChar x ; cnum xs} | otherwise = do{ putStr " <cte. numerica>\n" ; le_bloco (x:xs)} operador (x:xs) | x `elem` listO = do{ putChar x ; operador xs} | otherwise = do{ putStr " <operador>\n" ; le_bloco (x:xs)} litstr (x:xs) | x /= '"' = do{ putChar x ; litstr xs} | otherwise = do{ putStr " <literal string>\n" ; le_bloco xs} pchave (x:xs) ys | x `notElem` listA = pchave xs (ys++[x]) | otherwise = pPCouI (x:xs) ys pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)} membroPC x | x `elem` listPC = True | otherwise = False I'm sorry for the bad english, it's been a while since the last time i used it =) Ah, I'm just starting to learn Haskell, first time i've seen it was like a month ago so pretend that I know nothing
Renato, All I did was I added type signatures to your code, and it worked. It is a very good idea to put type signatures on all top-level functions, otherwise you can get confusing errors. It looks like you are using Hugs - It is much better to use GHC. That's what everyone uses now. Another thing: For a program this size it doesn't matter much, but in Haskell we always try to make our functions pure if we can (that is, not IO type). Then you get the best advantage out of using Haskell. Steve listO = ['+', '-', '*', '/', '%', '^', '=', '>', '<', '.', '|', '&', '!', '~'] listS = [';', '{', '(', ')', '}', '[', ']', ','] listC = ['0','1'..'9'] listCF = listC ++ ['.'] listA = listO ++ listS ++ [' '] listPC = ["auto","double","int","struct","break","else","long","switch","case", "enum","register","typedef","char","extern","return","union","const", "float","short","unsigned","continue","for","signed","void","default", "goto","sizeof","volatile","do","if","static","while"] verifica :: IO () verifica = do putStr ("Favor visualizar o codigo para ver os bugs e erros do programa\n") putStr ("Digite o nome do arquivo de entrada: ") arqent <- getLine texto <- readFile arqent le_bloco texto le_bloco :: String -> IO () le_bloco (x:xs) | x `elem` listO = do operador (x:xs) | x `elem` listC = do cnum (x:xs) -- | x `elem` listS = do separador (x:xs) | x `elem` listS = do{ putStr[x] ; putStr " <separador>\n" } | x == '"' = litstr (xs) | x /= ' ' = pchave (x:xs) [] | x == ' ' = le_bloco xs | otherwise = do { putStr "Outro\n" ; le_bloco xs } separador :: String -> IO () separador (x:xs) | x `elem` listS = do{ putStr [x] ; separador xs} | otherwise = do{ putStr " <separador>\n" ; le_bloco xs} cnum :: String -> IO () cnum (x:xs) | x `elem` listCF = do{ putChar x ; cnum xs} | otherwise = do{ putStr " <cte. numerica>\n" ; le_bloco (x:xs)} operador :: String -> IO () operador (x:xs) | x `elem` listO = do{ putChar x ; operador xs} | otherwise = do{ putStr " <operador>\n" ; le_bloco (x:xs)} litstr :: String -> IO () litstr (x:xs) | x /= '"' = do{ putChar x ; litstr xs} | otherwise = do{ putStr " <literal string>\n" ; le_bloco xs} pchave :: String -> String -> IO () pchave (x:xs) ys | x `notElem` listA = pchave xs (ys++[x]) | otherwise = pPCouI (x:xs) ys pPCouI :: String -> String -> IO () pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)} membroPC :: String -> Bool membroPC x | x `elem` listPC = True | otherwise = False Renato dos Santos Leal wrote:
I've got a university project that demands me to do a program that receive a .c file and analyze its syntax using haskell. There are just a few things that I have to analyze: literal strings, identifiers (in the program: identificadores), constants (constantes), operators (operadores) and reserverd words(palavras reservadas)
There are two major problems in the program:
(1) I've got this guard in le_bloco: | x `elem` listS = do separador (x:xs) but it doesn't seem to work. Every time I enable it I recieve this in execution time (after calling verifica)
ERROR - Cannot find "show" function for: *** Expression : verifica *** Of type : IO a
So I've made one workaround that prints the separator but stops the program...I guess the problem is doing the recursivity
(2) My second problem is: when I have one identifier or keyword alone in a line or it's the last element of it it just won't print my coment! this is the function:
pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)}
*Please help me solving those problems as soon as possible!*
Here is the whole program:
listO = ['+', '-', '*', '/', '%', '^', '=', '>', '<', '.', '|', '&', '!', '~'] listS = [';', '{', '(', ')', '}', '[', ']', ','] listC = ['0','1'..'9'] listCF = listC ++ ['.'] listA = listO ++ listS ++ [' '] listPC = ["auto","double","int","struct","break","else","long","switch","case",
"enum","register","typedef","char","extern","return","union","const",
"float","short","unsigned","continue","for","signed","void","default", "goto","sizeof","volatile","do","if","static","while"]
verifica = do putStr ("Favor visualizar o codigo para ver os bugs e erros do programa\n") putStr ("Digite o nome do arquivo de entrada: ") arqent <- getLine texto <- readFile arqent le_bloco texto
le_bloco (x:xs) | x `elem` listO = do operador (x:xs) | x `elem` listC = do cnum (x:xs) -- | x `elem` listS = do separador (x:xs) | x `elem` listS = do{ putStr[x] ; putStr " <separador>\n" } | x == '"' = litstr (xs) | x /= ' ' = pchave (x:xs) [] | x == ' ' = le_bloco xs | otherwise = do { putStr "Outro\n" ; le_bloco xs }
separador (x:xs) | x `elem` listS = do{ putStr [x] ; separador xs} | otherwise = do{ putStr " <separador>\n" ; le_bloco xs}
cnum (x:xs) | x `elem` listCF = do{ putChar x ; cnum xs} | otherwise = do{ putStr " <cte. numerica>\n" ; le_bloco (x:xs)}
operador (x:xs) | x `elem` listO = do{ putChar x ; operador xs} | otherwise = do{ putStr " <operador>\n" ; le_bloco (x:xs)}
litstr (x:xs) | x /= '"' = do{ putChar x ; litstr xs} | otherwise = do{ putStr " <literal string>\n" ; le_bloco xs}
pchave (x:xs) ys | x `notElem` listA = pchave xs (ys++[x]) | otherwise = pPCouI (x:xs) ys
pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)}
membroPC x | x `elem` listPC = True | otherwise = False
I'm sorry for the bad english, it's been a while since the last time i used it =) Ah, I'm just starting to learn Haskell, first time i've seen it was like a month ago so pretend that I know nothing
------------------------------------------------------------------------
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
Thank you Stephen! Yes, I'm using hugs. My teacher told me to use it and he corrects our projects using it, the differece between hugs and GHC, is it large? I don't know if I got what you meant with pure functions, but I'll keep studying. 2010/4/21 Stephen Blackheath [to Haskell-Beginners] < mutilating.cauliflowers.stephen@blacksapphire.com>
Renato,
All I did was I added type signatures to your code, and it worked. It is a very good idea to put type signatures on all top-level functions, otherwise you can get confusing errors.
It looks like you are using Hugs - It is much better to use GHC. That's what everyone uses now.
Another thing: For a program this size it doesn't matter much, but in Haskell we always try to make our functions pure if we can (that is, not IO type). Then you get the best advantage out of using Haskell.
Steve
listO = ['+', '-', '*', '/', '%', '^', '=', '>', '<', '.', '|', '&', '!', '~'] listS = [';', '{', '(', ')', '}', '[', ']', ','] listC = ['0','1'..'9'] listCF = listC ++ ['.'] listA = listO ++ listS ++ [' '] listPC = ["auto","double","int","struct","break","else","long","switch","case",
"enum","register","typedef","char","extern","return","union","const",
"float","short","unsigned","continue","for","signed","void","default", "goto","sizeof","volatile","do","if","static","while"]
verifica :: IO ()
verifica = do putStr ("Favor visualizar o codigo para ver os bugs e erros do programa\n") putStr ("Digite o nome do arquivo de entrada: ") arqent <- getLine texto <- readFile arqent le_bloco texto
le_bloco :: String -> IO ()
le_bloco (x:xs) | x `elem` listO = do operador (x:xs) | x `elem` listC = do cnum (x:xs) -- | x `elem` listS = do separador (x:xs) | x `elem` listS = do{ putStr[x] ; putStr " <separador>\n" } | x == '"' = litstr (xs) | x /= ' ' = pchave (x:xs) [] | x == ' ' = le_bloco xs | otherwise = do { putStr "Outro\n" ; le_bloco xs }
separador :: String -> IO ()
separador (x:xs) | x `elem` listS = do{ putStr [x] ; separador xs} | otherwise = do{ putStr " <separador>\n" ; le_bloco xs}
cnum :: String -> IO ()
cnum (x:xs) | x `elem` listCF = do{ putChar x ; cnum xs} | otherwise = do{ putStr " <cte. numerica>\n" ; le_bloco (x:xs)}
operador :: String -> IO ()
operador (x:xs) | x `elem` listO = do{ putChar x ; operador xs} | otherwise = do{ putStr " <operador>\n" ; le_bloco (x:xs)}
litstr :: String -> IO ()
litstr (x:xs) | x /= '"' = do{ putChar x ; litstr xs} | otherwise = do{ putStr " <literal string>\n" ; le_bloco xs}
pchave :: String -> String -> IO ()
pchave (x:xs) ys | x `notElem` listA = pchave xs (ys++[x]) | otherwise = pPCouI (x:xs) ys
pPCouI :: String -> String -> IO ()
pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)}
membroPC :: String -> Bool
membroPC x | x `elem` listPC = True | otherwise = False
Renato dos Santos Leal wrote:
I've got a university project that demands me to do a program that receive a .c file and analyze its syntax using haskell. There are just a few things that I have to analyze: literal strings, identifiers (in the program: identificadores), constants (constantes), operators (operadores) and reserverd words(palavras reservadas)
There are two major problems in the program:
(1) I've got this guard in le_bloco: | x `elem` listS = do separador (x:xs) but it doesn't seem to work. Every time I enable it I recieve this in execution time (after calling verifica)
ERROR - Cannot find "show" function for: *** Expression : verifica *** Of type : IO a
So I've made one workaround that prints the separator but stops the program...I guess the problem is doing the recursivity
(2) My second problem is: when I have one identifier or keyword alone in a line or it's the last element of it it just won't print my coment! this is the function:
pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)}
*Please help me solving those problems as soon as possible!*
Here is the whole program:
listO = ['+', '-', '*', '/', '%', '^', '=', '>', '<', '.', '|', '&', '!', '~'] listS = [';', '{', '(', ')', '}', '[', ']', ','] listC = ['0','1'..'9'] listCF = listC ++ ['.'] listA = listO ++ listS ++ [' '] listPC = ["auto","double","int","struct","break","else","long","switch","case",
"enum","register","typedef","char","extern","return","union","const",
"float","short","unsigned","continue","for","signed","void","default", "goto","sizeof","volatile","do","if","static","while"]
verifica = do putStr ("Favor visualizar o codigo para ver os bugs e erros do programa\n") putStr ("Digite o nome do arquivo de entrada: ") arqent <- getLine texto <- readFile arqent le_bloco texto le_bloco (x:xs) | x `elem` listO = do operador (x:xs) | x `elem` listC = do cnum (x:xs) -- | x `elem` listS = do separador (x:xs) | x `elem` listS = do{ putStr[x] ; putStr " <separador>\n" } | x == '"' = litstr (xs) | x /= ' ' = pchave (x:xs) [] | x == ' ' = le_bloco xs | otherwise = do { putStr "Outro\n" ; le_bloco xs }
separador (x:xs) | x `elem` listS = do{ putStr [x] ; separador xs} | otherwise = do{ putStr " <separador>\n" ; le_bloco xs} cnum (x:xs) | x `elem` listCF = do{ putChar x ; cnum xs} | otherwise = do{ putStr " <cte. numerica>\n" ; le_bloco (x:xs)} operador (x:xs) | x `elem` listO = do{ putChar x ; operador xs} | otherwise = do{ putStr " <operador>\n" ; le_bloco (x:xs)} litstr (x:xs) | x /= '"' = do{ putChar x ; litstr xs} | otherwise = do{ putStr " <literal string>\n" ; le_bloco xs}
pchave (x:xs) ys | x `notElem` listA = pchave xs (ys++[x]) | otherwise = pPCouI (x:xs) ys pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)} membroPC x | x `elem` listPC = True | otherwise = False
I'm sorry for the bad english, it's been a while since the last time i used it =) Ah, I'm just starting to learn Haskell, first time i've seen it was like a month ago so pretend that I know nothing
------------------------------------------------------------------------
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
Am Donnerstag 22 April 2010 01:29:26 schrieb Renato dos Santos Leal:
Yes, I'm using hugs. My teacher told me to use it and he corrects our projects using it, the differece between hugs and GHC, is it large?
hugs is an interpreter, GHC is a compiler. With GHC comes the interactive interpreter ghci, which is fairly similar to hugs.
I don't know if I got what you meant with pure functions, but I'll keep studying.
pure is "not IO" (side-effect free; expressions of type IO a can have side effects, and it is much easier to reason about things if they don't have side effects).
Renato, GHC and Hugs both comply with the Haskell 98 standard, so the same program will work in both if it's written in Haskell 98. I've never used Hugs so I don't know what your error means. I just tried loading it into GHC with -Wall on (enable all warnings) and I got lots of c.hs:21:0: Warning: Pattern match(es) are non-exhaustive In the definition of `le_bloco': Patterns not matched: [] c.hs:32:0: Warning: Pattern match(es) are non-exhaustive In the definition of `separador': Patterns not matched: [] ... It looks like you are not handling the end-of-list case. This might be related to your problems. If you run in GHC with -Wall, and fix all the warnings, you should find most of your problems go away. (Haskell is truly wonderful in this way.) Steve Renato dos Santos Leal wrote:
Thank you Stephen!
Yes, I'm using hugs. My teacher told me to use it and he corrects our projects using it, the differece between hugs and GHC, is it large?
I don't know if I got what you meant with pure functions, but I'll keep studying.
2010/4/21 Stephen Blackheath [to Haskell-Beginners] <mutilating.cauliflowers.stephen@blacksapphire.com <mailto:mutilating.cauliflowers.stephen@blacksapphire.com>>
Renato,
All I did was I added type signatures to your code, and it worked. It is a very good idea to put type signatures on all top-level functions, otherwise you can get confusing errors.
It looks like you are using Hugs - It is much better to use GHC. That's what everyone uses now.
Another thing: For a program this size it doesn't matter much, but in Haskell we always try to make our functions pure if we can (that is, not IO type). Then you get the best advantage out of using Haskell.
Steve
listO = ['+', '-', '*', '/', '%', '^', '=', '>', '<', '.', '|', '&', '!', '~'] listS = [';', '{', '(', ')', '}', '[', ']', ','] listC = ['0','1'..'9'] listCF = listC ++ ['.'] listA = listO ++ listS ++ [' '] listPC = ["auto","double","int","struct","break","else","long","switch","case",
"enum","register","typedef","char","extern","return","union","const",
"float","short","unsigned","continue","for","signed","void","default", "goto","sizeof","volatile","do","if","static","while"]
verifica :: IO ()
verifica = do putStr ("Favor visualizar o codigo para ver os bugs e erros do programa\n") putStr ("Digite o nome do arquivo de entrada: ") arqent <- getLine texto <- readFile arqent le_bloco texto
le_bloco :: String -> IO ()
le_bloco (x:xs) | x `elem` listO = do operador (x:xs) | x `elem` listC = do cnum (x:xs) -- | x `elem` listS = do separador (x:xs) | x `elem` listS = do{ putStr[x] ; putStr " <separador>\n" } | x == '"' = litstr (xs) | x /= ' ' = pchave (x:xs) [] | x == ' ' = le_bloco xs | otherwise = do { putStr "Outro\n" ; le_bloco xs }
separador :: String -> IO ()
separador (x:xs) | x `elem` listS = do{ putStr [x] ; separador xs} | otherwise = do{ putStr " <separador>\n" ; le_bloco xs}
cnum :: String -> IO ()
cnum (x:xs) | x `elem` listCF = do{ putChar x ; cnum xs} | otherwise = do{ putStr " <cte. numerica>\n" ; le_bloco (x:xs)}
operador :: String -> IO ()
operador (x:xs) | x `elem` listO = do{ putChar x ; operador xs} | otherwise = do{ putStr " <operador>\n" ; le_bloco (x:xs)}
litstr :: String -> IO ()
litstr (x:xs) | x /= '"' = do{ putChar x ; litstr xs} | otherwise = do{ putStr " <literal string>\n" ; le_bloco xs}
pchave :: String -> String -> IO ()
pchave (x:xs) ys | x `notElem` listA = pchave xs (ys++[x]) | otherwise = pPCouI (x:xs) ys
pPCouI :: String -> String -> IO ()
pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)}
membroPC :: String -> Bool
membroPC x | x `elem` listPC = True | otherwise = False
Renato dos Santos Leal wrote:
I've got a university project that demands me to do a program that receive a .c file and analyze its syntax using haskell. There are just a few things that I have to analyze: literal strings, identifiers (in the program: identificadores), constants (constantes), operators (operadores) and reserverd words(palavras reservadas)
There are two major problems in the program:
(1) I've got this guard in le_bloco: | x `elem` listS = do separador (x:xs) but it doesn't seem to work. Every time I enable it I recieve this in execution time (after calling verifica)
ERROR - Cannot find "show" function for: *** Expression : verifica *** Of type : IO a
So I've made one workaround that prints the separator but stops the program...I guess the problem is doing the recursivity
(2) My second problem is: when I have one identifier or keyword alone in a line or it's the last element of it it just won't print my coment! this is the function:
pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)}
*Please help me solving those problems as soon as possible!*
Here is the whole program:
listO = ['+', '-', '*', '/', '%', '^', '=', '>', '<', '.', '|', '&', '!', '~'] listS = [';', '{', '(', ')', '}', '[', ']', ','] listC = ['0','1'..'9'] listCF = listC ++ ['.'] listA = listO ++ listS ++ [' '] listPC = ["auto","double","int","struct","break","else","long","switch","case",
"enum","register","typedef","char","extern","return","union","const",
"float","short","unsigned","continue","for","signed","void","default", "goto","sizeof","volatile","do","if","static","while"]
verifica = do putStr ("Favor visualizar o codigo para ver os bugs e erros do programa\n") putStr ("Digite o nome do arquivo de entrada: ") arqent <- getLine texto <- readFile arqent le_bloco texto le_bloco (x:xs) | x `elem` listO = do operador (x:xs) | x `elem` listC = do cnum (x:xs) -- | x `elem` listS = do separador (x:xs) | x `elem` listS = do{ putStr[x] ; putStr " <separador>\n" } | x == '"' = litstr (xs) | x /= ' ' = pchave (x:xs) [] | x == ' ' = le_bloco xs | otherwise = do { putStr "Outro\n" ; le_bloco xs }
separador (x:xs) | x `elem` listS = do{ putStr [x] ; separador xs} | otherwise = do{ putStr " <separador>\n" ; le_bloco xs} cnum (x:xs) | x `elem` listCF = do{ putChar x ; cnum xs} | otherwise = do{ putStr " <cte. numerica>\n" ; le_bloco (x:xs)} operador (x:xs) | x `elem` listO = do{ putChar x ; operador xs} | otherwise = do{ putStr " <operador>\n" ; le_bloco (x:xs)} litstr (x:xs) | x /= '"' = do{ putChar x ; litstr xs} | otherwise = do{ putStr " <literal string>\n" ; le_bloco xs}
pchave (x:xs) ys | x `notElem` listA = pchave xs (ys++[x]) | otherwise = pPCouI (x:xs) ys pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)} membroPC x | x `elem` listPC = True | otherwise = False
I'm sorry for the bad english, it's been a while since the last time i used it =) Ah, I'm just starting to learn Haskell, first time i've seen it was like a month ago so pretend that I know nothing
------------------------------------------------------------------------
_______________________________________________ Beginners mailing list Beginners@haskell.org <mailto:Beginners@haskell.org> http://www.haskell.org/mailman/listinfo/beginners
I've seen that there is something like hIsEOF that I can use to find EOF to do so I need something like eof <- hIsEOF hdl (hdl: the file that i'm reading) how can I put it as a guard in le_bloco? 2010/4/21 Stephen Blackheath [to Haskell-Beginners] < mutilating.cauliflowers.stephen@blacksapphire.com>
Renato,
GHC and Hugs both comply with the Haskell 98 standard, so the same program will work in both if it's written in Haskell 98.
I've never used Hugs so I don't know what your error means. I just tried loading it into GHC with -Wall on (enable all warnings) and I got lots of
c.hs:21:0: Warning: Pattern match(es) are non-exhaustive In the definition of `le_bloco': Patterns not matched: []
c.hs:32:0: Warning: Pattern match(es) are non-exhaustive In the definition of `separador': Patterns not matched: []
...
It looks like you are not handling the end-of-list case. This might be related to your problems. If you run in GHC with -Wall, and fix all the warnings, you should find most of your problems go away. (Haskell is truly wonderful in this way.)
Steve
Renato dos Santos Leal wrote:
Thank you Stephen!
Yes, I'm using hugs. My teacher told me to use it and he corrects our projects using it, the differece between hugs and GHC, is it large?
I don't know if I got what you meant with pure functions, but I'll keep studying.
2010/4/21 Stephen Blackheath [to Haskell-Beginners] < mutilating.cauliflowers.stephen@blacksapphire.com <mailto: mutilating.cauliflowers.stephen@blacksapphire.com>>
Renato,
All I did was I added type signatures to your code, and it worked. It is a very good idea to put type signatures on all top-level functions, otherwise you can get confusing errors.
It looks like you are using Hugs - It is much better to use GHC. That's what everyone uses now.
Another thing: For a program this size it doesn't matter much, but in Haskell we always try to make our functions pure if we can (that is, not IO type). Then you get the best advantage out of using Haskell.
Steve
listO = ['+', '-', '*', '/', '%', '^', '=', '>', '<', '.', '|', '&', '!', '~'] listS = [';', '{', '(', ')', '}', '[', ']', ','] listC = ['0','1'..'9'] listCF = listC ++ ['.'] listA = listO ++ listS ++ [' '] listPC = ["auto","double","int","struct","break","else","long","switch","case",
"enum","register","typedef","char","extern","return","union","const",
"float","short","unsigned","continue","for","signed","void","default", "goto","sizeof","volatile","do","if","static","while"]
verifica :: IO ()
verifica = do putStr ("Favor visualizar o codigo para ver os bugs e erros do programa\n") putStr ("Digite o nome do arquivo de entrada: ") arqent <- getLine texto <- readFile arqent le_bloco texto
le_bloco :: String -> IO ()
le_bloco (x:xs) | x `elem` listO = do operador (x:xs) | x `elem` listC = do cnum (x:xs) -- | x `elem` listS = do separador (x:xs) | x `elem` listS = do{ putStr[x] ; putStr " <separador>\n" } | x == '"' = litstr (xs) | x /= ' ' = pchave (x:xs) [] | x == ' ' = le_bloco xs | otherwise = do { putStr "Outro\n" ; le_bloco xs }
separador :: String -> IO ()
separador (x:xs) | x `elem` listS = do{ putStr [x] ; separador xs} | otherwise = do{ putStr " <separador>\n" ; le_bloco xs}
cnum :: String -> IO ()
cnum (x:xs) | x `elem` listCF = do{ putChar x ; cnum xs} | otherwise = do{ putStr " <cte. numerica>\n" ; le_bloco (x:xs)}
operador :: String -> IO ()
operador (x:xs) | x `elem` listO = do{ putChar x ; operador xs} | otherwise = do{ putStr " <operador>\n" ; le_bloco (x:xs)}
litstr :: String -> IO ()
litstr (x:xs) | x /= '"' = do{ putChar x ; litstr xs} | otherwise = do{ putStr " <literal string>\n" ; le_bloco xs}
pchave :: String -> String -> IO ()
pchave (x:xs) ys | x `notElem` listA = pchave xs (ys++[x]) | otherwise = pPCouI (x:xs) ys
pPCouI :: String -> String -> IO ()
pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)}
membroPC :: String -> Bool
membroPC x | x `elem` listPC = True | otherwise = False
Renato dos Santos Leal wrote:
I've got a university project that demands me to do a program that receive a .c file and analyze its syntax using haskell. There are just a few things that I have to analyze: literal strings, identifiers (in the program: identificadores), constants (constantes), operators (operadores) and reserverd words(palavras reservadas)
There are two major problems in the program:
(1) I've got this guard in le_bloco: | x `elem` listS = do separador (x:xs) but it doesn't seem to work. Every time I enable it I recieve this in execution time (after calling verifica)
ERROR - Cannot find "show" function for: *** Expression : verifica *** Of type : IO a
So I've made one workaround that prints the separator but stops the program...I guess the problem is doing the recursivity
(2) My second problem is: when I have one identifier or keyword alone in a line or it's the last element of it it just won't print my coment! this is the function:
pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)}
*Please help me solving those problems as soon as possible!*
Here is the whole program:
listO = ['+', '-', '*', '/', '%', '^', '=', '>', '<', '.', '|', '&', '!', '~'] listS = [';', '{', '(', ')', '}', '[', ']', ','] listC = ['0','1'..'9'] listCF = listC ++ ['.'] listA = listO ++ listS ++ [' '] listPC =
["auto","double","int","struct","break","else","long","switch","case",
"enum","register","typedef","char","extern","return","union","const",
"float","short","unsigned","continue","for","signed","void","default", "goto","sizeof","volatile","do","if","static","while"]
verifica = do putStr ("Favor visualizar o codigo para ver os bugs e erros do programa\n") putStr ("Digite o nome do arquivo de entrada: ") arqent <- getLine texto <- readFile arqent le_bloco texto le_bloco (x:xs) | x `elem` listO = do operador (x:xs) | x `elem` listC = do cnum (x:xs) -- | x `elem` listS = do separador (x:xs) | x `elem` listS = do{ putStr[x] ; putStr " <separador>\n" } | x == '"' = litstr (xs) | x /= ' ' = pchave (x:xs) [] | x == ' ' = le_bloco xs | otherwise = do { putStr "Outro\n" ; le_bloco xs }
separador (x:xs) | x `elem` listS = do{ putStr [x] ; separador xs} | otherwise = do{ putStr " <separador>\n" ; le_bloco xs} cnum (x:xs) | x `elem` listCF = do{ putChar x ; cnum xs} | otherwise = do{ putStr " <cte. numerica>\n" ; le_bloco (x:xs)} operador (x:xs) | x `elem` listO = do{ putChar x ; operador xs} | otherwise = do{ putStr " <operador>\n" ; le_bloco (x:xs)} litstr (x:xs) | x /= '"' = do{ putChar x ; litstr xs} | otherwise = do{ putStr " <literal string>\n" ; le_bloco xs}
pchave (x:xs) ys | x `notElem` listA = pchave xs (ys++[x]) | otherwise = pPCouI (x:xs) ys pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)} membroPC x | x `elem` listPC = True | otherwise = False
I'm sorry for the bad english, it's been a while since the last time i used it =) Ah, I'm just starting to learn Haskell, first time i've seen it was like a month ago so pretend that I know nothing
------------------------------------------------------------------------
_______________________________________________ Beginners mailing list Beginners@haskell.org <mailto:Beginners@haskell.org>
Am Donnerstag 22 April 2010 02:09:35 schrieb Renato dos Santos Leal:
I've seen that there is something like hIsEOF that I can use to find EOF
to do so I need something like eof <- hIsEOF hdl (hdl: the file that i'm reading)
how can I put it as a guard in le_bloco?
No, that's not what you want. What you need is le_bloco (x:xs) ... (what you have) le_bloco "" = return () -- when the end of the string is reached, we're done.
Oh, much better, thanks. 2010/4/21 Daniel Fischer <daniel.is.fischer@web.de>
Am Donnerstag 22 April 2010 02:09:35 schrieb Renato dos Santos Leal:
I've seen that there is something like hIsEOF that I can use to find EOF
to do so I need something like eof <- hIsEOF hdl (hdl: the file that i'm reading)
how can I put it as a guard in le_bloco?
No, that's not what you want. What you need is
le_bloco (x:xs) ... (what you have) le_bloco "" = return () -- when the end of the string is reached, we're done.
Right now, my program is ike this listO = ['+', '-', '*', '/', '%', '^', '=', '>', '<', '.', '|', '&', '!', '~'] listS = [';', '{', '(', ')', '}', '[', ']', ','] listC = ['0','1'..'9'] listCF = listC ++ ['.'] listA = listO ++ listS ++ [' '] listPC = ["auto","double","int","struct","break","else","long","switch","case", "enum","register","typedef","char","extern","return","union","const", "float","short","unsigned","continue","for","signed","void","default", "goto","sizeof","volatile","do","if","static","while"] verifica :: IO () verifica = do putStr ("Favor visualizar o codigo para ver os bugs e erros do programa\n") putStr ("Digite o nome do arquivo de entrada: ") arqent <- getLine texto <- readFile arqent le_bloco texto le_bloco :: String -> IO () le_bloco (x:xs) | x `elem` listO = do operador (x:xs) | x `elem` listC = do cnum (x:xs) | x `elem` listS = do separador (x:xs) | x == '\n' = le_bloco xs | x == '"' = litstr (xs) | x /= ' ' = pchave (x:xs) [] | x == ' ' = le_bloco xs | otherwise = do { putStr "Outro\n" ; le_bloco xs } le_bloco [] = return () separador :: String -> IO () separador (x:xs) | x `elem` listS = do{ putStr [x] ; putStr " <separador>\n" ; le_bloco xs} cnum :: String -> IO () cnum (x:xs) | x `elem` listCF = do{ putChar x ; cnum xs} | otherwise = do{ putStr " <cte. numerica>\n" ; le_bloco (x:xs)} operador :: String -> IO () operador (x:xs) | x `elem` listO = do{ putChar x ; operador xs} | otherwise = do{ putStr " <operador>\n" ; le_bloco (x:xs)} litstr :: String -> IO () litstr (x:xs) | x /= '"' = do{ putChar x ; litstr xs} | otherwise = do{ putStr " <literal string>\n" ; le_bloco xs} pchave :: String -> String -> IO () pchave (x:xs) ys | x `notElem` listA = pchave xs (ys++[x]) | otherwise = pPCouI (x:xs) ys pPCouI :: String -> String -> IO () pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)} membroPC :: String -> Bool membroPC x | x `elem` listPC = True | otherwise = False But there is still one problem that I haven't corrected: printing the tag when there is only one keyword or identifier in the line the case of beign the last one of the line is corrected but this one I don't know how to do
Am Donnerstag 22 April 2010 02:30:06 schrieb Renato dos Santos Leal:
But there is still one problem that I haven't corrected: printing the tag when there is only one keyword or identifier in the line the case of beign the last one of the line is corrected but this one I don't know how to do
pchave :: String -> String -> IO () pchave (x:xs) ys | x `notElem` listA = pchave xs (ys++[x]) | otherwise = pPCouI (x:xs) ys
When you're collecting an identifier or keyword, stop when you encounter a newline.
pPCouI :: String -> String -> IO () pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)}
By the way, function :: a -> Bool function x | condition = True | otherwise = False is rather clumsy, function = condition is better.
membroPC :: String -> Bool membroPC x | x `elem` listPC = True | otherwise = False
membroPC = (`elem` listPC)
Thank you Daniel. Thank you everyone that answerd you guys really saved me today =) 2010/4/21 Daniel Fischer <daniel.is.fischer@web.de>
Am Donnerstag 22 April 2010 02:30:06 schrieb Renato dos Santos Leal:
But there is still one problem that I haven't corrected: printing the tag when there is only one keyword or identifier in the line the case of beign the last one of the line is corrected but this one I don't know how to do
pchave :: String -> String -> IO () pchave (x:xs) ys | x `notElem` listA = pchave xs (ys++[x]) | otherwise = pPCouI (x:xs) ys
When you're collecting an identifier or keyword, stop when you encounter a newline.
pPCouI :: String -> String -> IO () pPCouI (x:xs) z | membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco (x:xs)} | otherwise = do{putStr z ; putStr " <identificador>\n" ; le_bloco (x:xs)}
By the way,
function :: a -> Bool function x | condition = True | otherwise = False
is rather clumsy,
function = condition
is better.
membroPC :: String -> Bool membroPC x | x `elem` listPC = True | otherwise = False
membroPC = (`elem` listPC)
On Wed, 2010-04-21 at 20:29 -0300, Renato dos Santos Leal wrote:
Thank you Stephen!
Yes, I'm using hugs. My teacher told me to use it and he corrects our projects using it, the differece between hugs and GHC, is it large?
Yes and no. I've done basic course of Haskell (not beyond pure functions) and as I was more familiar with GHC(i) (not mentioning GHC(i) is a lot faster) I tested using it. Then I changed to hugs and corrected compilation errors. Usually they were small but still.
I don't know if I got what you meant with pure functions, but I'll keep studying.
http://en.wikipedia.org/wiki/Pure_function A function that state depends purely on its arguments and which effect is solely the result. For example this is pure:
add :: [(Int, Int)] -> [Int] add = map (uncurry (+))
is pure. But this is not:
addAndPrint :: [(Int, Int)] -> IO () addAndPrint ((a, b):xs) = do print (a + b) addAndPrint xs addAndPrint [] = return ()
While strict evaluation promotes using impure functions in Haskell pure functions are often better. Consider:
add :: [(Int, Int)] -> [Int] add = map (uncurry (+))
addAndPrint :: [(Int, Int)] -> IO () addAndPrint xs = mapM print (add xs)
If you have strict evaluation you may think that it will be compiled into something like: temportaryList <- add xs mapM print temportaryList Creating temportaryList and hence having O(n) space (too bad if it is infinite list - you will never get the result). However in Haskell (add xs) is evaluated as needed hence there is no (significant) delay between adding and printing. Using the pure functions have significant benefits: - They may not change anything. If compiler (not necessary in Haskell - gcc allows marking function as pure as well) sees some call unnecessary they may be removed. Consider (in C99) for (int i = 0; i < f(); i++) doSomething(); If f is pure it may be compiled into: int f_tmp = f(); // I mean real register but anyway. for (int i = 0; i < f_tmp; i++) doSomething(); We save calling f many times (calculating f may be quite costly - 10000 number of pi is pure calculation but it may take some time). If doSomething is pure we may just not call it (we don't need the result): for (int i = 0; i < f(); i++) {} If both are pure compiler just skips loop. If you consider haskell example: > doSomething :: [Int] -> IO [Int] > doSomething (x:xs) = do xs' <- doSomething' xs > return (x+1):xs' > doSomething [] = return [] > > headOfSomething :: [Int] -> IO Int > headOfSomething xs = do ys <- doSomething > return (head ys) headOfSomething returns the first element increased by one. However it has to iterate through the list making it in O(n) time. > doSomething :: [Int] -> [Int] > doSomething (x:xs) = (x+1):doSomething xs > doSomething [] = [] > > headOfSomething xs = head (doSomething xs) Now we know we can just skip the evaluation of doSomething if we don't need the result. Making it O(1) function. - They are nice to test. Pure function depends only on input so there is no need for setting up environment and checking the environment. What worst the testing may break the encapsulation as it needs to lookup the state (to check if it is correct). - The order does not matter. If you have map f (map g xs) then it is sure that the order of f and g does not matter. Compiler may as well change it into map (f . g) xs (it maye save a little of space and time). However if you consider:
call f g xs = do ys <- mapM g xs mapM f ys
Then the ordering does matter. I tried to not use higher order functions & other scary stuff and I'm sorry if any slipped in. As you probably noticed Haskell syntax encourages the pure functions. While the examples may not make it clear why it is better try to imagine them 10x more complicated ;) As a rule of thumb - from syntax point of view if something has IO in type it is impure. String -> IO (Int) is impure while String -> Int is pure. Regards
Am Donnerstag 22 April 2010 00:42:51 schrieb Renato dos Santos Leal:
I've got a university project that demands me to do a program that receive a .c file and analyze its syntax using haskell. There are just a few things that I have to analyze: literal strings, identifiers (in the program: identificadores), constants (constantes), operators (operadores) and reserverd words(palavras reservadas)
There are two major problems in the program:
(1) I've got this guard in le_bloco: | x `elem` listS = do separador (x:xs) but it doesn't seem to work. Every time I enable it I recieve this in execution time (after calling verifica)
ERROR - Cannot find "show" function for: *** Expression : verifica *** Of type : IO a
I can't reproduce that. It works here (except of the pattern match failure at the end because none of your functions handles an empty String). $ hugs CAnal __ __ __ __ ____ ___ _________________________________________ || || || || || || ||__ Hugs 98: Based on the Haskell 98 standard ||___|| ||__|| ||__|| __|| Copyright (c) 1994-2005 ||---|| ___|| World Wide Web: http://haskell.org/hugs || || Bugs: http://hackage.haskell.org/trac/hugs || || Version: September 2006 _________________________________________ Haskell 98 mode: Restart with command line option -98 to enable extensions Type :? for help CAnal> verifica Favor visualizar o codigo para ver os bugs e erros do programa Digite o nome do arquivo de entrada: hello.c #include <identificador> < <operador> stdio <identificador> . <operador> h <identificador>
<operador>
int <identificador> main <identificador> (){ <separador> printf <identificador> ( <separador> Hello <identificador> World <identificador> ! <operador> \n" <identificador> ); <separador> return <palavra chave> 0 <cte. numerica> ; <separador> } <separador> Program error: pattern match failure: le_bloco [] CAnal> :q [Leaving Hugs]
So I've made one workaround that prints the separator but stops the program...I guess the problem is doing the recursivity
(2) My second problem is: when I have one identifier or keyword alone in a line or it's the last element of it it just won't print my coment!
That's because you don't look for newlines, so int main is considered to be one token, "int\nmain".
this is the function:
pPCouI (x:xs) z
| membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco | (x:xs)} otherwise = do{putStr z ; putStr " <identificador>\n" ; | le_bloco
(x:xs)}
*Please help me solving those problems as soon as possible!*
Here is the whole program:
listO = ['+', '-', '*', '/', '%', '^', '=', '>', '<', '.', '|', '&', '!', '~'] listS = [';', '{', '(', ')', '}', '[', ']', ','] listC = ['0','1'..'9'] listCF = listC ++ ['.'] listA = listO ++ listS ++ [' '] listPC = ["auto","double","int","struct","break","else","long","switch","case",
"enum","register","typedef","char","extern","return","union","const",
"float","short","unsigned","continue","for","signed","void","default", "goto","sizeof","volatile","do","if","static","while"]
verifica = do putStr ("Favor visualizar o codigo para ver os bugs e erros do programa\n") putStr ("Digite o nome do arquivo de entrada: ") arqent <- getLine texto <- readFile arqent le_bloco texto
le_bloco (x:xs)
| x `elem` listO = do operador (x:xs) | x `elem` listC = do cnum (x:xs)
-- | x `elem` listS = do separador (x:xs)
| x `elem` listS = do{ putStr[x] ; putStr " <separador>\n" } | x == '"' = litstr (xs) | x /= ' ' = pchave (x:xs) [] | x == ' ' = le_bloco xs | otherwise = do { putStr "Outro\n" ; le_bloco xs }
separador (x:xs)
| x `elem` listS = do{ putStr [x] ; separador xs} | otherwise = do{ putStr " <separador>\n" ; le_bloco xs}
That should probably be le_bloco (x:xs) in the otherwise-branch, too. Thus it failed to see that "Hello World\n" was a string literal. And it wouldn't treat int x=3,y=4; correctly.
cnum (x:xs)
| x `elem` listCF = do{ putChar x ; cnum xs} | otherwise = do{ putStr " <cte. numerica>\n" ; le_bloco (x:xs)}
operador (x:xs)
| x `elem` listO = do{ putChar x ; operador xs} | otherwise = do{ putStr " <operador>\n" ; le_bloco (x:xs)}
litstr (x:xs)
| x /= '"' = do{ putChar x ; litstr xs} | otherwise = do{ putStr " <literal string>\n" ; le_bloco xs}
pchave (x:xs) ys
| x `notElem` listA = pchave xs (ys++[x]) | otherwise = pPCouI (x:xs) ys
pPCouI (x:xs) z
| membroPC z = do{ putStr (z ++ " <palavra chave>\n") ; le_bloco | (x:xs)} otherwise = do{putStr z ; putStr " <identificador>\n" ; | le_bloco
(x:xs)}
membroPC x
| x `elem` listPC = True | otherwise = False
I'm sorry for the bad english, it's been a while since the last time i used it =) Ah, I'm just starting to learn Haskell, first time i've seen it was like a month ago so pretend that I know nothing
participants (4)
-
Daniel Fischer -
Maciej Piechotka -
Renato dos Santos Leal -
Stephen Blackheath [to Haskell-Beginners]