<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On 26 jul 2010, at 03:51, Jason Dagit wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">Hello,<div><br></div><div>I find that parser correctness is often hard to verify. &nbsp;Therefore, I'm interested in techniques that others have used successfully, especially with Haskell.</div></blockquote><div><br></div>It seems to me that you are not so much trying to verify parsers, but more specifically Parsec parsers. Since in Parsec-based parsers you control the backtracking explicitly such parsers can get very complicated semantics. Now the question arises: what does it mean for a (Parsec) parser to be correct? Do you have another description of the &nbsp;language which is to be recognised, e.g. a context-free grammar. Only then can you give meaning to the word "correctness".</div><div><br></div><div>In general I think that the more your parser combinators deviate from context-free grammars in terms of expressiveness, the more problems you will encounter. If you make heavy use of the monadic part, you will not only have to prove the correctness of static parsers, but even of parsers which are generated dynamically. If you use the backtrack-controlling features, your proofs will become even more complicated, since it is unlikely that your more abstract formalism in which you have specified your language does not have a similar construct: here comes in about 50 years on research on parsing techniques and grammar analysis. If your grammar is e.g. LL(1) then you can verify that some of the back-tracking-controlling features in your Parser parser have been used in a sound way, i.e., that you will be able to parse any sentence that your grammar describes.</div><div><br></div><div>If you have a context-free grammar, and you want to be relatively sure that the parser is correct and you do not want to go through large verification efforts I suggest you use the uu-parsinglib; the only restriction there is is that your grammar should fulfill certain modest "well-formedness" criteria, such as being non-left-recursive and non-ambiguous. Then &nbsp;the semantics of the combinators are exactly what you want, i.e. your parsers and your grammars are isomorphic. If you have however an "incorrect formal specification", i.e., a specification which contains ambiguous non-terminals like p* constructs where p can reduce to an empty string &nbsp; things break. The first problem one is not recognised and will lead to a non-terminating parser, whereas the second problem is detected by the grammars analysing themselves while being used, and leading to a run-time error message once you reach that part of the grammar during parsing.</div><div><br></div><div>If you insist on using left-recursive parsers you may use the left-corner transform from the&nbsp;</div><div><br></div><div><a href="http://hackage.haskell.org/packages/archive/ChristmasTree/0.2/doc/html/Text-GRead-Transformations-LeftCorner.html">http://hackage.haskell.org/packages/archive/ChristmasTree/0.2/doc/html/Text-GRead-Transformations-LeftCorner.html</a></div><div><br></div><div>package, or use a parser generator like happy; parser generators usually do some form of analysis (i.e. proving properties), which captures many mistakes in the design of a language.</div><div><br></div><div>Furthermore you may take a look at:&nbsp;</div><div><span class="Apple-style-span" style="font-family: 'Times New Roman'; "><pre>@inproceedings{<a href="http://dblp.uni-trier.de/db/about/bibtex.html" style="color: rgb(0, 0, 0); ">DBLP</a>:conf/mpc/BrinkHL10,
  author    = {Kasper Brink and
               Stefan Holdermans and
               Andres L{\"o}h},
  title     = {Dependently Typed Grammars},
  booktitle = {MPC},
  year      = {2010},
  pages     = {58-79},
  ee        = {http://dx.doi.org/10.1007/978-3-642-13321-3_6},
  crossref  = {DBLP:conf/mpc/2010},
  bibsource = {DBLP, http://dblp.uni-trier.de}</pre><pre><br></pre><pre>Doaitse Swierstra</pre></span><div><br></div></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br><blockquote type="cite"><div><br></div><div>Techniques I'm aware of:</div>
<div>&nbsp;&nbsp;* Round trip checks: Generate a datastructure, render as a string, parse back, and compare. &nbsp;Quickcheck can be used to automate this.</div><div>&nbsp;&nbsp;* Fuzz testing: &nbsp;What tools exist to help me?</div><div>&nbsp;&nbsp;* Formal verification: Has anyone been using this with Haskell parsers? &nbsp;Other than general theorem provers, say Isabelle, what tools exist?</div>
<div><br></div><div>My specific need:</div><div>The immediate challenge I have is that I'm modifying the parser that Darcs uses and we would like to improve the parser's test suite as well. &nbsp;The parser abstraction used in this case follows parsec's API. &nbsp;Left to my own devices I would use round trip checks, written with quickcheck, for this exercise. &nbsp;Because we're using a parsec style parser, I don't have a nice neat grammar handy.</div>
<div><br></div><div>Thanks in advance for any advice you have!</div><div><br></div><div>Thanks,</div><div>Jason</div>
_______________________________________________<br>Haskell-Cafe mailing list<br><a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>http://www.haskell.org/mailman/listinfo/haskell-cafe<br></blockquote></div><br></body></html>