All Projects → rxwei → Parsey

rxwei / Parsey

Licence: MIT license
Swift Parser Combinators

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Parsey

Baby
Create models from a JSON file, even a Baby can do it.
Stars: ✭ 214 (+282.14%)
Mutual labels:  parser-combinators
jasentaa
A parser combinator library for Clojure and ClojureScript
Stars: ✭ 53 (-5.36%)
Mutual labels:  parser-combinators
CombinedParsers.jl
Compiled parser combinators and regular expressions in pure julia
Stars: ✭ 76 (+35.71%)
Mutual labels:  parser-combinators
Funcparserlib
Recursive descent parsing library for Python based on functional combinators
Stars: ✭ 250 (+346.43%)
Mutual labels:  parser-combinators
Kt2Dart
🔦 [Deprecated] Transpile Kotlin codes into Dart, Make Flutter Great Again
Stars: ✭ 84 (+50%)
Mutual labels:  parser-combinators
metal
A Java library for parsing binary data formats, using declarative descriptions.
Stars: ✭ 13 (-76.79%)
Mutual labels:  parser-combinators
Goparsec
Parser combinator in Go. If there are any cross platform issues or backward compatibility issues, please reach out.
Stars: ✭ 198 (+253.57%)
Mutual labels:  parser-combinators
parserz
A purely-functional library for creating both parsers, pretty-printers, and grammar definitions from a single, type-safe specification of a grammar
Stars: ✭ 68 (+21.43%)
Mutual labels:  parser-combinators
mecha
A parser combinator library for Zig
Stars: ✭ 220 (+292.86%)
Mutual labels:  parser-combinators
parser-lang
A parser combinator library with declarative superpowers
Stars: ✭ 25 (-55.36%)
Mutual labels:  parser-combinators
autumn
A Java parser combinator library written with an unmatched feature set.
Stars: ✭ 112 (+100%)
Mutual labels:  parser-combinators
Syntax
Write value-driven parsers quickly in Swift with an intuitive SwiftUI-like DSL
Stars: ✭ 134 (+139.29%)
Mutual labels:  parser-combinators
ParsecSharp
The faster monadic parser combinator library for C#
Stars: ✭ 23 (-58.93%)
Mutual labels:  parser-combinators
Parsica
Parsica - PHP Parser Combinators - The easiest way to build robust parsers.
Stars: ✭ 223 (+298.21%)
Mutual labels:  parser-combinators
parsekt
Parser Combinator library for Kotlin
Stars: ✭ 27 (-51.79%)
Mutual labels:  parser-combinators
Urlformat
Type safe url pattern matching without regular expressions and arguments type mismatches based on parser combinators.
Stars: ✭ 213 (+280.36%)
Mutual labels:  parser-combinators
SuperCombinators
[Deprecated] A Swift parser combinator framework
Stars: ✭ 19 (-66.07%)
Mutual labels:  parser-combinators
maxpc
Max’s Parser Combinators: a simple and pragmatic library for writing parsers and lexers based on combinatory parsing.
Stars: ✭ 42 (-25%)
Mutual labels:  parser-combinators
FLexer
Simple Lexer and Parser in F#
Stars: ✭ 22 (-60.71%)
Mutual labels:  parser-combinators
Ramble
A R parser based on combinatory parsers.
Stars: ✭ 19 (-66.07%)
Mutual labels:  parser-combinators

Parsey

Swift Parser Combinator Framework

In addition to simple combinators, Parsey supports source location/range tracking, backtracking prevention, and custom error messages.

Parsey Playground

Features

  • Combinator interface

    • |, ~~, ~~>, <~~, ^^ combinator operators
  • Lexer primitives:

    • Lexer.whitespace, Lexer.signedInteger, ...
  • Regex-like combinators:

    • Postfix .+ for .many().
      • Example: let arrayLiteral = "[" ~~> expression.+ <~~ "]"
    • Postfix .* for .manyOrNone().
      • Example: let classDef = (attribute | method).*
    • Postfix .? for .optional().
      • Example: let declaration = "let" ~~> id ~~ (":" ~~> type).? ~~ ("=" ~~> expression)
    • Postfix + for .manyConcatenated().
      • Example: let skippedSpaces = (Lexer.space | Lexer.tab)+
    • Infix + for .concatenatingResult(with:).
      • Example: let type = Lexer.upperLetter + Lexer.letter*
    • Lexer.regex(_:) for directly applying regular expressions.
      • Example: let id = Lexer.regex("[a-zA-Z][a-zA-Z0-9]*")
  • Backtracking prevention

    • .! postfix operator or .nonbacktracking()
  • Parser tagging for error messages

    • <!-- operator or .tagged(_:)
  • Rich error messages with source location

    • For example:
    Parse failure at 2:4 ----
    (+ %% 1 -20) 2 3)
       ^~~~~~~~~~~~~~
    Expecting an expression, but found "%"
    
  • Source range tracking

    • ^^^ operator or .mapParse(_:)
    • For example, S-expression \n(+ \n\n(+ +1 -20) 2 3) gets parsed to the following range-tracked AST:
    Expr:(2:1..<4:16):[
        ID:(2:2..<2:3):+,
        Expr:(4:1..<4:11):[
            ID:(4:2..<4:3):+,
            Int:(4:4..<4:6):1,
            Int:(4:7..<4:10):-20],
        Int:(4:12..<4:13):2,
        Int:(4:14..<4:15):3]
    

Requirements

  • Swift 3

  • Any operating system

Package

To use it in your Swift project, add the following dependency to your Swift package description file.

    .Package(url: "https://github.com/rxwei/Parsey", majorVersion: 1)

Examples

0️⃣ An LLVM Compiler Frontend written in Swift using Parsey

The COOL Programming Language

1️⃣ Parse Left-associative Infix Expressions with Operator Precedence

indirect enum Expression {
    case integer(Int)
    case symbol(String)
    case infix(String, Expression, Expression)
}

enum Grammar {
    static let integer = Lexer.signedInteger
        ^^ {Int($0)!} ^^ Expression.integer

    static let symbol = Lexer.regex("[a-zA-Z][0-9a-zA-Z]*")
        ^^ Expression.symbol

    static let addOp = Lexer.anyCharacter(in: "+-")
        ^^ { op in { Expression.infix(op, $0, $1) } }
    
    static let multOp = Lexer.anyCharacter(in: "*/")
        ^^ { op in { Expression.infix(op, $0, $1) } }

    /// Left-associative multiplication
    static let multiplication = (integer | symbol).infixedLeft(by: multOp)

    /// Left-associative addition
    static let addition = multiplication.infixedLeft(by: addOp)

    static let expression: Parser<Expression> = addition
}

try print(Grammar.expression.parse("2"))
/// Output:
/// Expression.integer(2)

try print(Grammar.expression.parse("2+1+2*a"))
/// Output:
/// Expression.infix("+",
///                  .infix("+", .integer(2), .integer(1)),
///                  .infix("*", .integer(2), .symbol("a")))

2️⃣ Parse S-Expressions

indirect enum Expr {
    case sExp([Expr])
    case int(Int)
    case id(String)
}

enum Grammar {
    static let whitespaces = (Lexer.space | Lexer.tab | Lexer.newLine)+
    static let anInt = Lexer.signedInteger ^^ { Int($0)! } ^^ Expr.int
    static let anID = Lexer.regex("[a-zA-Z_+\\-*/][0-9a-zA-Z_+\\-*/]*") ^^ Expr.id
    static let aSExp: Parser<Expr> =
        "(" ~~> (anExp.!).many(separatedBy: whitespaces).amid(whitespaces.?) <~~ ")"
        ^^ Expr.sExp
    static let anExp = anInt | anID | aSExp <!-- "an expression"
}

/// Success
try Grammar.anExp.parse("(+ (+ 1 -20) 2 3)")
/// Output: Expr.sExp(...)

/// Failure
try Grammar.anExp.parse("(+ \n(+ %% 1 -20) 2 3)")
/// Output: Parse failure at 2:4 ----
///         (+ %% 1 -20) 2 3)
///            ^~~~~~~~~~~~~~
///         Expecting an expression, but found "%"

3️⃣ Parse S-Expressions with Source Range Tracking

indirect enum Expr {
    case sExp([Expr], SourceRange)
    case int(Int, SourceRange)
    case id(String, SourceRange)
}

enum Grammar {
    static let whitespaces = (Lexer.space | Lexer.tab | Lexer.newLine)+

    static let anInt = Lexer.signedInteger 
        ^^^ { Expr.int(Int($0.target)!, $0.range) }

    static let anID = Lexer.regex("[a-zA-Z_+\\-*/][0-9a-zA-Z_+\\-*/]*")
        ^^^ { Expr.id($0.target, $0.range) }

    static let aSExp: Parser<Expr> =
        "(" ~~> (anExp.!).many(separatedBy: whitespaces).amid(whitespaces.?) <~~ ")"
        ^^^ { Expr.sExp($0.target, $0.range) }

    static let anExp = anInt | anID | aSExp <!-- "an expression"
}

/// Success
try Grammar.anExp.parse("(+ (+ 1 -20) 2 3)")
/// Output: Expr.sExp(...)

/// Failure
try Grammar.anExp.parse("(+ \n(+ %% 1 -20) 2 3)")
/// Output: Parse failure at 2:4 ----
///         (+ %% 1 -20) 2 3)
///            ^~~~~~~~~~~~~~
///         Expecting an expression, but found "%"

Dependency

License

MIT License

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].