Note that there are some explanatory texts on larger screens.

plurals
  1. POParsing: Lazy initialization and mutually recursive monads in F#
    primarykey
    data
    text
    <p>I've been writing a little monadic parser-combinator library in F# (somewhat similar to <a href="http://www.quanttec.com/fparsec/" rel="nofollow noreferrer">FParsec</a>) and now tried to implement a small parser for a programming language.</p> <p>I first implemented the code in Haskell (with Parsec) which ran perfectly well. The parsers for infix expressions are designed mutually recursive.</p> <pre><code>parseInfixOp :: Parser String -&gt; Parser Expression -&gt; Parser Expression parseInfixOp operatorParser subParser = ignoreSpaces $ do x &lt;- ignoreSpaces $ subParser do op &lt;- ignoreSpaces $ operatorParser y &lt;- parseInfixOp operatorParser subParser return $ BinaryOp op x y &lt;|&gt; return x parseInfix :: [String] -&gt; Parser Expression -&gt; Parser Expression parseInfix list = parseInfixOp (foldl1 (&lt;|&gt;) $ map string list) parseExpr :: Parser Expression parseExpr = parseInfix0 parseInfix0 = parseInfix ["==", "&lt;&gt;", "And", "Or", "Xor", "&lt;", "&gt;", "&lt;=", "&gt;="] parseInfix1 parseInfix1 = parseInfix ["+", "-", "Mod"] parseInfix2 parseInfix2 = parseInfix ["*", "/", "\\"] parseInfix3 parseInfix3 = parseInfix ["^"] parseInfix4 parseInfix4 = parseFactor parseFactor :: Parser Expression parseFactor = parseFactor' &lt;|&gt; (betweenChars '(' ')' parseExpr) parseFactor' :: Parser Expression parseFactor' = parseString &lt;|&gt; parseBool &lt;|&gt; parseNumber &lt;|&gt; parseVariable &lt;|&gt; (try parseFunCall) &lt;|&gt; parseIdentifier </code></pre> <p>Since the order of functions doesn't matter and Haskell is evaluating in a non-strict way, this is OK, but F# is evaluating strictly.</p> <pre><code>let rec parseExpr = parseInfix0 and parseFactor = (parseFactor') &lt;|&gt; (betweenChars '(' ')' parseExpr) and parseInfix2 = parseInfix ["^"] parseFactor BinaryOp and parseInfix1 = parseInfix ["*"; "/"] parseInfix2 BinaryOp and parseInfix0 = parseInfix ["+"; "-"] parseInfix1 BinaryOp and parseFunCall = parser { let! first = letter let! rest = many (letter &lt;|&gt; digit) let funcName = toStr $ first::rest do! ignoreSpace let! args = betweenChars '(' ')' $ sepBy (parseExpr) "," return FunCall(funcName, args) } and parseFactor' = parseNumber &lt;|&gt; parseString &lt;|&gt; parseBool &lt;|&gt; parseFunCall &lt;|&gt; parseIdentifier </code></pre> <p>F# now either complains about recursive objects and just throws a <code>StackOverflowException</code> at runtime due to an infinite loop or it even doesn't compile the source because "a value would be part of its own definion".</p> <p>What's the best way to prevent this errors. The debugger advices me to make use functions or <code>lazy</code>s instead but what should I make lazy here? </p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload