
I'm trying to do a simple lex analyser in haskell I defined the function lexi that is intended to break a string into tokens returning them as a list but I received the following error: ERROR "TesteEval.hs":20 - Syntax error in input (unexpected symbol "restante") isLetter:: Char -> Bool isLetter c = or [isLower (c), isUpper (c)] isLetterorDigit:: Char -> Bool isLetterorDigit c = or [isLetter (c), isDigit (c)] main = lexi lexi " "= [] lexi (a:x) | isLetter a = token: lexi restante where S = takeWhile isLetterorDigit x line 20 ------> restante = dropWhile isLetterorDigit x token = 'Id' ++ S _________________________________________________________________ Chat with friends online, try MSN Messenger: http://messenger.msn.com

There are three basic problems here. The first is the syntax error you see, the second and third will become available once you fix the syntax error.
lexi (a:x) | isLetter a = token: lexi restante where S = takeWhile isLetterorDigit x line 20 ------> restante = dropWhile isLetterorDigit x token = 'Id' ++ S
So, Haskell uses a system of "layout". THis saves us from writing lots of braces and parentheses (some people don't like layout and you're free to do without it -- Ashley will probably post something along these lines). The basic idea is that without layout, you would have to write: "... where { S = takeWhile isLetterorDigit x ; restante = dropWhile isLetterorDigit x ... }" what layout allows you to do is tell the compiler where to insert these braces and semicolons implicitly. You do this by verical alignment. Basically, if a keywords like 'where' (or 'let' or 'do') is not followed by a brace, the column number at which the next identifier is found is remembered. Henceforth, as long as columns begin at that column number, they are part of the same where clause. This might be a bit tricky to grasp, but the moral is: make sure the starting column for the definition of each element in a where clause is the same. so you would write:
lexi (a:x) | isLetter a = token: lexi restante where S = takeWhile isLetterorDigit x restante = dropWhile isLetterorDigit x token = 'Id' ++ S
now, the second problem. identifiers must begin with lowercase letters, so this "S" will not do. According to haskell, things that begin with a capital letter are type constructors, types, classes. So you must you "s" instead of "S". Finally, the third problem. You define:
main = lexi
But this won't work. The type of lexi (once you get it working) is 'String -> [String]' but the type of main must be 'IO ()'. Presumably, you want to apply the lexer to stdin and then print the identifiers out one per line. You can do this with something like: main = interact (unlines . lexi) The function 'interact' has type (String -> String) -> IO () and what it does is read from stdin, run what it reads through the string processing function, and prints the results to stdout. Now, your function lexi has type 'String -> [String]', so this won't do. The function 'unlines' has type: [String] -> String and basically takes the list of strings, puts newlines between them, and catenates them. Finally, '.', the composition operator composes the two functions, thus producing a function of type 'String -> String' as required by interact. I hope this has made some sense. - Hal
participants (2)
-
Hal Daume III
-
Jonata Goulart