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:
[EMAIL PROTECTED]:~/Documents/haskell/Reto> cat input
a.n
[EMAIL PROTECTED]:~/Documents/haskell/Reto> reto input
InfixExpr OP_Dot (Ident "a") (Ident "n")
[EMAIL PROTECTED]:~/Documents/haskell/Reto> cat input
a\inn
[EMAIL PROTECTED]:~/Documents/haskell/Reto> reto input
Ident "a"
[EMAIL PROTECTED]:~/Documents/haskell/Reto> cat input
a\in n
[EMAIL PROTECTED]:~/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
---------------------------------------------------------------------
[EMAIL PROTECTED]:~/Documents/haskell/Reto> cat input
a.n
[EMAIL PROTECTED]:~/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


_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to