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