A beginner-friendly, event-driven F# parsing library for language design and implementation.
Writing parsers in F# often requires complex combinator libraries or heavy compiler frameworks. SharpParser.Core takes a different approach: a lightweight, event-driven API that makes building language parsers intuitive, composable, and fun β without sacrificing power. Whether you're building a domain-specific language, configuration parser, or language tool, SharpParser gives you the control and performance you need with an API that feels natural in F#.
- Character, sequence, and pattern handlers - Handle individual characters, multi-character sequences, and regex patterns
- Context-sensitive parsing modes - Use mode stacks for nested parsing contexts
- Optional tokenization and AST construction - Enable automatic token and AST generation
- Enhanced AST types - Support for binary operations, unary operations, variables, numbers, and strings
- Configuration validation - Built-in validation to catch configuration errors early
- Error handling and debugging - Comprehensive error reporting and trace logging
- Parallel parsing - Multi-threaded parsing for improved performance on multi-core systems
- Functional programming - Pure functions, immutable data structures, and no mutable state
- Fluent, chainable API - Easy-to-use functional programming style
- Comprehensive testing - 138 tests covering all functionality and edge cases
Here's your first parser in just 10 lines:
open SharpParser.Core
let parser =
Parser.create()
|> Parser.onSequence "hello" (fun ctx ->
printfn "Hello found at line %d, col %d" ctx.Line ctx.Col
ctx)
Parser.runString "hello world" parser
Output:
Hello found at line 1, col 1
β That's all you need to start building a parser! The next example shows how to handle nested contexts, ASTs, and more advanced features.
open SharpParser.Core
// Create a parser with mode-based handlers
let parser =
Parser.create ()
|> Parser.enableTokens() // Enable automatic tokenization
|> Parser.enableAST() // Enable AST building
|> Parser.onSequence "function" (fun ctx ->
printfn "Found function at line %d, col %d" ctx.Line ctx.Col
ParserContext.enterMode "functionBody" ctx)
|> Parser.inMode "functionBody" (fun config ->
config
|> Parser.onChar '{' (fun ctx ->
printfn "Start function block"
ctx)
|> Parser.onChar '}' (fun ctx ->
printfn "End function block"
ParserContext.exitMode ctx))
// Parse input
let context = Parser.runString "function test() { return 42 }" parser
// Get results
let tokens = Parser.getTokens context
let ast = Parser.getAST context
Sample Output:
Found function at line 1, col 1
Start function block
End function block
Tokens: [Keyword("function"), Identifier("test"), Symbol("("), Symbol(")"), Symbol("{"), Keyword("return"), Number(42.0), Symbol("}")]
AST: [Function("test", [], [Return(Some(Number(42.0)))])]
- .NET 6.0 SDK or later
- F# development environment (Visual Studio, VS Code with Ionide, or Rider)
Install SharpParser.Core from NuGet:
dotnet add package SharpParser.Core
Or add it manually to your .fsproj
:
<PackageReference Include="SharpParser.Core" Version="1.1.0" />
Clone the repository and reference the project directly:
git clone https://github.com/alexzzzs/SharpParser.Core.git
Then add to your .fsproj
:
<ProjectReference Include="path/to/SharpParser.Core/src/SharpParser.Core/SharpParser.Core.fsproj" />
Create a simple test file to verify the installation:
open SharpParser.Core
let parser = Parser.create() |> Parser.onChar 'a' (fun ctx -> printfn "Found 'a'!"; ctx)
let result = Parser.runString "test" parser
printfn "Installation successful!"
SharpParser.Core provides three types of handlers:
- Character handlers (
onChar
) - Handle individual characters - Sequence handlers (
onSequence
) - Handle multi-character sequences like keywords and operators - Pattern handlers (
onPattern
) - Handle regex patterns like identifiers and numbers
Use modes to create context-sensitive parsers:
Parser.create ()
|> Parser.onSequence "function" (fun ctx -> ParserContext.enterMode "functionBody" ctx)
|> Parser.inMode "functionBody" (fun config ->
config
|> Parser.onChar '{' (fun ctx -> printfn "Function start"; ctx)
|> Parser.onChar '}' (fun ctx -> printfn "Function end"; ParserContext.exitMode ctx))
The ParserContext
contains all parsing state:
- Current position (line, column)
- Mode stack
- Collected tokens and AST nodes
- Error and trace information
Enable additional features as needed:
Parser.create ()
|> Parser.enableTokens () // Enable tokenization
|> Parser.enableAST () // Enable AST building
|> Parser.enableTrace true // Enable tracing
For complete API documentation, see docs/API.md.
Parser.create()
- Create new parser configurationParser.onChar char handler
- Register character handlerParser.onSequence sequence handler
- Register sequence handlerParser.onPattern pattern handler
- Register pattern handlerParser.inMode mode nestedConfig
- Set mode context for nested handlersParser.onError handler
- Register global error handlerParser.enableTokens ()
- Enable automatic tokenizationParser.enableAST ()
- Enable automatic AST buildingParser.enableTrace enabled
- Enable or disable tracingParser.run filePath
- Parse file and return contextParser.runString input
- Parse string and return context
Parser.getTokens context
- Extract collected tokensParser.getAST context
- Extract AST nodesParser.getErrors context
- Extract errorsParser.getTrace context
- Extract trace logParser.getUserData key context
- Get user-defined dataParser.setUserData key value context
- Set user-defined data
ParserContextOps.enterMode mode context
- Push mode onto stackParserContextOps.exitMode context
- Pop mode from stackParserContextOps.currentMode context
- Get current modeParserContextOps.addToken token context
- Add token to stateParserContextOps.addASTNode node context
- Add AST node to stateParserContextOps.addError message context
- Record errorParserContextOps.addTrace message context
- Add trace message
Parser.printSummary context
- Print parsing results summaryParser.formatSummary context
- Format parsing results as stringParser.validateConfig config
- Validate parser configurationErrorHandling.formatErrors context
- Format errors as stringTracer.formatTrace context
- Format trace log as string
See the examples/
directory for comprehensive examples:
- BasicExample - Simple character and pattern handlers
- ModeExample - Context-sensitive parsing with modes
- FullExample - All features (tokens, AST, error handling, tracing)
- JsonExample - Parsing JSON-like structured data with modes
- CsvExample - Parsing CSV data with quoted fields and escaping
- ExpressionExample - Parsing arithmetic expressions with operator precedence
- IniExample - Parsing INI configuration files with sections
Run the examples:
dotnet run --project examples/SharpParser.Examples/SharpParser.Examples.fsproj
Check out the tutorials/
directory for step-by-step guides:
- Parsing JSON with SharpParser - Build a complete JSON parser from scratch
- Building a CSV Parser - Handle quoted fields, escaping, and complex CSV structures
- Creating Configuration File Parsers - Parse INI files and other config formats
Each tutorial includes complete working code and builds your understanding progressively.
SharpParser.Core consists of several focused modules:
- Types - Core type definitions (Token, ASTNode, handlers)
- Trie - Efficient sequence matching with prefix tree
- PatternMatcher - Regex-based pattern matching
- HandlerRegistry - Storage and lookup for all handler types
- ParserContext - Parsing state and mode management
- ParserConfig - Parser configuration with fluent API
- ParsingEngine - Core parsing logic and handler dispatch
- Tokenizer - Automatic token generation
- ASTBuilder - Automatic AST construction
- ErrorHandler - Error handling and reporting
- Tracer - Debugging and trace logging
- Parser - Public fluent API
- Trie-based sequence matching for efficient multi-character detection
- Compiled regex patterns for fast pattern matching
- Parallel parsing for improved performance on multi-core systems
- Immutable data structures for thread safety and functional style
- Functional programming patterns with no mutable state for better performance
- Minimal allocations through pure functions and immutability
- Comprehensive test coverage ensuring reliability and performance
The architecture supports several extension points:
- Grammar DSL - Domain-specific language for grammar definition
- Incremental parsing - Parse changes without full reparse
- Custom token types - Extensible token type system
- Plugin system - Load handlers from external assemblies
- Visual debugging - GUI for parsing visualization
We welcome contributions! SharpParser.Core is an open-source project that benefits from community involvement.
- π Bug Reports: Found an issue? Open a GitHub issue
- π‘ Feature Requests: Have an idea? Start a discussion
- π Documentation: Help improve docs, examples, or tutorials
- π§ͺ Testing: Add test cases or improve test coverage
- π§ Code: Submit pull requests for bug fixes or new features
git clone https://github.com/alexzzzs/SharpParser.Core.git
cd SharpParser.Core
dotnet build
dotnet test
β Functional programming - Eliminated mutable state throughout the codebase β Enhanced AST types - Added support for complex expressions and literals β Configuration validation - Built-in validation for parser configurations β Parallel parsing - Multi-threaded parsing for improved performance on multi-core systems β Performance optimizations - Regex anchoring, trie Dictionary optimization, token caching β Comprehensive testing - 138 tests covering all functionality and edge cases β Error handling - Proper invocation of error handlers β Documentation - Updated API docs and README
- Performance optimizations - Continue benchmarking and optimizing hot paths
- Additional examples - More real-world parsing scenarios
- Extensions - Implement planned extension points (grammar DSL, incremental parsing)
- Visual debugging - GUI for parsing visualization
MIT License - see LICENSE file for details.
SharpParser.Core makes parsing fun and accessible while providing the power needed for complex language implementations!