On 4/11/07, Stefan O'Rear <[EMAIL PROTECTED]> wrote:
Your use of 'have' is slightly suspicious here. That said, the rest of your problem looks very un-homework-y, so I'll look at it.
It's for my masters thesis (big piece of badly-specified homework if you want to think about it like that :)). I used "have" cause I'm coding an embedded VHDL compiler and I really "have" to pretty print VHDL in the backend :) (the more readable the code I get the better).
"Associativity" is ambiguous here. Do you mean: 1 + 2 + 3 => (1 + 2) + 3 (Associativity of parsing)
This is what I mean. Say "-" is right associative in the target language, that allows to remove the parenthesis of the following expression "1 - (1 - 2)" and just write "1 - 1 - 2", but probably the code would be less readable since a human doesn't normally take that in account (I tend to forget those things and keep writing parenthesis all the time anyway).
(1 + 2) + 3 == 6 == 1 + (2 + 3) (Associativity of functions)
I don't see how taking this in account would make the output more readable.
> data Expr = Val String | > -- Binary operators (using infix constructors) > Expr :+: Expr | Expr :-: Expr | > Expr :*: Expr | Expr :/: Expr | > Expr :^: Expr | > -- Unary operators > Negate Expr > > > I'm using HughesPJ for the rest of my AST (not just expressions) but > the library doesn't provide any mechanism to help coding this kind of > prettyprinter so I decided to simply use the standard showsPrec and > then feed HughesPJ with the obtained text. That seems very counter-productive. By using showsPrec, you lose all the information that could be used to guide line breaks.
Yes, you're totally right. Thanks a lot for your code :)
It would be far better to do it yourself. Note that the method I am about to show is exactly the same as that used by the standard showsPrec: -- let +, - have infixl 1 -- let *, / have infixl 2 -- let ^ have infixr 3 -- let uminus have (nofix) 4 pprExpr :: Int -- ^ Precedence context - if you're like me no -- explanation of this will make more sense than the -- code -> Expr -> Doc pprExpr cx (Val str) = text str pprExpr cx (a :+: b) = cparen (cx >= 1) $ pprExpr 1 a <+> char '+' <+> pprExpr 1 b pprExpr cx (a :-: b) = cparen (cx >= 1) $ pprExpr 1 a <+> char '+' <+> pprExpr 1 b pprExpr cx (a :*: b) = cparen (cx >= 2) $ pprExpr 2 a <+> char '+' <+> pprExpr 2 b pprExpr cx (a :/: b) = cparen (cx >= 2) $ pprExpr 2 a <+> char '+' <+> pprExpr 2 b pprExpr cx (a :^: b) = cparen (cx >= 3) $ pprExpr 3 a <+> char '+' <+> pprExpr 3 b pprExpr cx (Negate a) = cparen (cx >= 4) $ char '-' <+> pprExpr 4 a -- this is provided for ShowS under the name showsParen, but -- unfortunately does not exist for Doc standardly cparen :: Bool -> Doc -> Doc cparen False = id cparen True = parens > showsPrec helps to take advantage of the precedence information. > However, I don't find a way to remove parenthesis according to > associativity. A simple modification of the above code will do it: pprExpr cx (Val str) = text str pprExpr cx (a :+: b) = cparen (cx >= 1) $ pprExpr 0 a <+> char '+' <+> pprExpr 1 b pprExpr cx (a :-: b) = cparen (cx >= 1) $ pprExpr 0 a <+> char '-' <+> pprExpr 1 b pprExpr cx (a :*: b) = cparen (cx >= 2) $ pprExpr 1 a <+> char '*' <+> pprExpr 2 b pprExpr cx (a :/: b) = cparen (cx >= 2) $ pprExpr 1 a <+> char '/' <+> pprExpr 2 b pprExpr cx (a :^: b) = cparen (cx >= 3) $ pprExpr 3 a <+> char '^' <+> pprExpr 2 b pprExpr cx (Negate a) = cparen (cx >= 4) $ char '+' <+> pprExpr 4 a Handling line breaks is left as an excercise for the reader. > I'm sure this kind of prettyprinting has been already done zillions of > times in Haskell. Any suggestions? Stefan
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe