
Great! Thanks for the revision Daniel. If you're ever in San Francisco, please do ping me - I sure owe you lunch! - Reto On Mar 31, 2006, at 3:14 PM, Daniel Fischer wrote:
Am Freitag, 31. März 2006 15:24 schrieb Daniel Fischer:
Hi,
probably somebody else has already come up with something better, but still...
I surmise that you have two kinds of infix-operators, 1. dot-like operators, made up entirely of symbols (^!$%&/\,.:;#+- ~* ...) 2. LaTeX-command-like operators, starting with a backslash and then followed by a nonempty sequence of letters (or possibly alphanumeric characters).
Then the following helps:
import Data.Char (isAlpha)
lexer = lexer0{P.reservedOp = rOp} where lexer0 = P.makeTokenParser testdef resOp0 = P.reservedOp lexer0 resOp1 name = case name of ('\\':cs@(_:_))
| all isAlpha cs -> do string name
notFollowedBy letter > ("end of " ++ show name) _ -> fail (show name ++ " no good reservedOp") rOp name = lexeme $ try $ resOp0 name <|> resOp1 name lexeme p = do { x <- p; P.whiteSpace lexer0; return x }
Noho, that's not right, that parses "a\inn" as InfixExpr OP_In (Ident "a") (Ident "n"), because resOp1 is never used, which we don't want, so:
lexer = lexer0{P.reservedOp = rOp} where lexer0 = P.makeTokenParser testdef resOp0 = P.reservedOp lexer0 resOp1 name = do string name notFollowedBy letter > ("end of " ++ show name) rOp name = lexeme $ try $ case name of ('\\':cs@(_:_)) | all isAlpha cs -> resOp1 name _ -> resOp0 name lexeme p = do { x <- p; P.whiteSpace lexer0; return x }
Now: dafis@linux:~/Documents/haskell/Reto> cat input a.n dafis@linux:~/Documents/haskell/Reto> reto input InfixExpr OP_Dot (Ident "a") (Ident "n") dafis@linux:~/Documents/haskell/Reto> cat input a\inn dafis@linux:~/Documents/haskell/Reto> reto input Ident "a" dafis@linux:~/Documents/haskell/Reto> cat input a\in n dafis@linux:~/Documents/haskell/Reto> reto input InfixExpr OP_In (Ident "a") (Ident "n")
That's better.
testdef = emptyDef { P.identStart = letter <|> char '_' , P.identLetter = alphaNum <|> char '_' , P.opStart = oneOf $ nub $ map (\s -> head s) $ P.reservedOpNames testdef -- , P.opLetter = oneOf (concat (P.reservedOpNames testdef)) , P.opLetter = oneOf symbs , P.reservedOpNames = [ ".", "\\in" ] } where symbs = filter (not . isAlpha) . concat $ P.reservedOpNames testdef --------------------------------------------------------------------- dafis@linux:~/Documents/haskell/Reto> cat input a.n dafis@linux:~/Documents/haskell/Reto> reto input InfixExpr OP_Dot (Ident "a") (Ident "n")
If you have more complicated infix operators (e.g. \foo#bar:, :ouch:), it won't be so easy, anyway, you have to change the definition of reservedOp.
Cheers, Daniel
--
"In My Egotistical Opinion, most people's C programs should be indented six feet downward and covered with dirt." -- Blair P. Houghton