A lightweight, functional parser combinator library written in F# with a complete JSON parser implementation. This library provides a clean, composable way to build parsers using functional programming principles.
- Parser Combinators: Build complex parsers by combining simple ones
- Position Tracking: Detailed error reporting with line and column information
- Monadic Interface: Supports
>>=,<*>,<|>and other functional operators - Complete JSON Parser: Full JSON specification support including Unicode escapes
- Extensive Primitives: Built-in parsers for common patterns (strings, numbers, whitespace, etc.)
#load "ParserLib.fsx"
open ParserLib
// Simple character parser
let parseA = pchar 'a'
let result = run parseA "abc"
// Success ('a', remaining input)
// Combine parsers
let parseAB = pchar 'a' .>>. pchar 'b'
let result2 = run parseAB "abc"
// Success (('a', 'b'), remaining input)#load "JSONparser.fsx"
open JSONparser
let jsonText = """
{
"name": "John Doe",
"age": 30,
"isActive": true,
"address": {
"street": "123 Main St",
"city": "Anytown"
},
"hobbies": ["reading", "swimming"]
}
"""
let result = run jValue jsonText
match result with
| Success (jsonValue, _) ->
printfn "Parsed successfully: %A" jsonValue
| Failure (label, error, pos) ->
printfn "Parse error at line %d, column %d: %s" pos.line pos.column errortype Parser<'a> = {
parseFn : (Input -> ParseResult<'a * Input>)
label : ParserLabel
}type ParseResult<'a> =
| Success of 'a
| Failure of ParserLabel * ParserError * ParserPositiontype JValue =
| JString of string
| JNumber of float
| JBool of bool
| JNull
| JObject of Map<string, JValue>
| JArray of JValue list| Combinator | Description | Example |
|---|---|---|
pchar |
Parse a specific character | pchar 'a' |
pstring |
Parse a specific string | pstring "hello" |
satisfy |
Parse character matching predicate | satisfy Char.IsDigit "digit" |
anyOf |
Parse any character from list | anyOf ['a'; 'b'; 'c'] |
| Operator | Description | Example |
|---|---|---|
.>>. |
Parse both, return both | pchar 'a' .>>. pchar 'b' |
.>> |
Parse both, return first | pchar 'a' .>> pchar 'b' |
>>. |
Parse both, return second | pchar 'a' >>. pchar 'b' |
<|> |
Try first, if fails try second | pchar 'a' <|> pchar 'b' |
<*> |
Apply parser to function parser | returnP (+) <*> pint <*> pint |
| Function | Description | Example |
|---|---|---|
many |
Zero or more occurrences | many (pchar 'a') |
many1 |
One or more occurrences | many1 digitChar |
sepBy |
Separated by delimiter | sepBy pint (pchar ',') |
opt |
Optional parser | opt (pchar '-') |
| Function | Description |
|---|---|
between |
Parse between delimiters |
choice |
Choose from list of parsers |
sequence |
Parse sequence of parsers |
spaces |
Parse zero or more whitespace |
spaces1 |
Parse one or more whitespace |
pint- Parse integers (with optional minus sign)pfloat- Parse floating-point numbersdigitChar- Parse single digit
quotedString- Parse quoted strings with escape sequencesmanyChars- Convert character parser to string parserwhitespaceChar- Parse single whitespace character
The JSON parser supports the complete JSON specification:
- Strings: With full Unicode escape sequence support (
\uXXXX) - Numbers: Integer and floating-point with scientific notation
- Booleans:
trueandfalseliterals - Null:
nullliteral - Arrays: Nested arrays with proper comma separation
- Objects: Key-value pairs with string keys
- Whitespace: Flexible whitespace handling
\"- Quote\\- Backslash\/- Forward slash\b- Backspace\f- Form feed\n- Newline\r- Carriage return\t- Tab\uXXXX- Unicode code point
The library provides detailed error information including:
- Line and column numbers for error location
- Parser labels for context about what was expected
- Error messages describing what went wrong
- Visual error display with caret pointing to error location
let result = run jValue "{ invalid json }"
printResult result
// Output:
// Line:0 Col:2 Error parsing object
// { invalid json }
// ^Unexpected 'i'let numberList =
pchar '[' >>.
sepBy pint (pchar ',' .>> spaces) .>>
pchar ']'
let result = run numberList "[1, 2, 3, 4]"let keyValue =
manyChars1 (satisfy Char.IsLetter "letter") .>>
pchar '=' .>>.
pint
let result = run keyValue "count=42"type Person = { Name: string; Age: int }
let personParser =
pipe2
(quotedString .>> pchar ',')
pint
(fun name age -> { Name = name; Age = age })- Copy
ParserLib.fsxto your F# project - Copy
JSONparser.fsxfor JSON parsing functionality - Load the files using
#loaddirective:
#load "ParserLib.fsx"
#load "JSONparser.fsx" // Optional, for JSON parsingContributions are welcome! Please feel free to submit issues and enhancement requests.
This project is open source. Please add your preferred license here.
The library is built around these core concepts:
- Input State Tracking: Maintains position information for error reporting
- Parser Composition: Small parsers combine to create complex ones
- Monadic Design: Supports functional composition patterns
- Forward References: Handles recursive grammar rules (like JSON objects containing objects)
The JSON parser demonstrates advanced usage including forward references for recursive data structures and comprehensive string parsing with Unicode support.