I'm writing a recursive parser with FParsec, so I'm creating a dummy parser and reference cell with createParserForwardedToRef
like so:
let pstatement, pstatementref = createParserForwardedToRef<Statement, Unit>()
The reference cell is eventually "assigned" the following:
do pstatementref := choice [
pread
pdisplay
pset
pcompute
pif
pwhile
]
When I test the parser pstatement
from within the file in which the reference cell is created and assigned the above value with the following code ...
let test p str =
match runParserOnFile p () str Encoding.ASCII with
| Success(result, _, _) -> printfn "Success: %A" result
| Failure(errorMsg, _, _) -> printfn "Failure: %s" errorMsg
[<EntryPoint>]
let main argv =
argv
|> String.concat "+"
|> test (manyTill pstatement (pword "HALT"))
0
... it works well, and I get the successful results.
However, when I try to run the exact same test function, this time from another project (called Interpreter) that has referenced the project wherein pstatement
is defined (called Parser, after removing the main function from Program.fs in Parser), I receive the following error:
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
at FParsec.Primitives.manyTill@890.Invoke(CharStream`1 stream)
at FParsec.CharParsers.applyParser[Result,UserState](FSharpFunc`2 parser, CharStream`1 stream)
at FParsec.CharParsers.runParserOnFile[a,u](FSharpFunc`2 parser, u ustate, String path, Encoding encoding)
at Program.test[a](FSharpFunc`2 p, String str) in /home/rosalogia/Projects/FSharp/PCParser/src/Interpreter/Program.fs:line 16
at Program.main(String[] argv) in /home/rosalogia/Projects/FSharp/PCParser/src/Interpreter/Program.fs:line 32
... which implies that the reference cell is never assigned any value, however the code which does so has not been removed from the Parser project.
Is there a limitation of reference cells I'm not aware of that's causing this problem? Since everything works fine within the file where the reference cell is defined, it seems safe to conclude that the problem is with accessing its value from a file or project outside of the one in which it's defined.
EDIT:
Here is a more complete example of how things are set up
Parser/Library.fs
namespace PCParser
module Parser =
let pstatement, pstatementref = createParserForwardedToRef<Statement, Unit>()
let pread = ...
let pdisplay = ...
...
do pstatementref := choice [
pread
pdisplay
pset
pcompute
pif
pwhile
]
Interpreter/Program.fs
open PCParser.Parser
open FParsec
open System.Text
let test p str =
match runParserOnFile p () str Encoding.ASCII with
| Success(result, _, _) -> printfn "Success: %A" result
| Failure(errorMsg, _, _) -> printfn "Failure: %s" errorMsg
[<EntryPoint>]
let main argv =
argv
|> String.concat "+"
|> test (manyTill pstatement (pword "HALT"))
0