Parsey alternatives and similar libraries
Based on the "Text" category.
Alternatively, view Parsey alternatives based on common mentions on social networks and blogs.
-
PhoneNumberKit
Swift framework for parsing, formatting and validating international phone numbers. Inspired by Google's libphonenumber. -
TwitterTextEditor
A standalone, flexible API that provides a full featured rich text editor for iOS applications. -
Atributika
Easily build NSAttributedString by detecting and styling HTML-like tags, hashtags, mentions, RegExp or NSDataDetector patterns. -
Mustard
Mustard is a Swift library for tokenizing strings when splitting by whitespace doesn't cut it. -
AttributedTextView
Easiest way to create an attributed UITextView with support for multiple links, hashtags and mentions -
Regex by crossroadlabs
very easy to use, Regular Expressions library with rich functionality. Features both operator =~ and method based APIs. Unit tests covered. -
OysterKit
OysterKit is a framework that provides a native Swift scanning, lexical analysis, and parsing capabilities. In addition it provides a language that can be used to rapidly define the rules used by OysterKit called STLR -
Markdown
Markdown templates for Swift. Based on Discount library (a library used deep down by GitHub markdown) -
PredicateFlow
PredicateFlow is a builder that allows you to write amazing, strong-typed and easy-to-read NSPredicate. -
Regex by brynbellomy
Swift wrapper class for NSRegularExpression. Includes a map() override and an operator (=~) for a more Swift-like API.
Get performance insights in less than 4 minutes
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest. Visit our partner's website for more details.
Do you think we are missing an alternative of Parsey or a related project?
README
Parsey
Swift Parser Combinator Framework
In addition to simple combinators, Parsey supports source location/range tracking, backtracking prevention, and custom error messages.
Features
Combinator interface
|
,~~
,~~>
,<~~
,^^
combinator operators
Lexer primitives:
Lexer.whitespace
,Lexer.signedInteger
, ...
Regex-like combinators:
- Postfix
.+
for.many()
.- Example:
let arrayLiteral = "[" ~~> expression.+ <~~ "]"
- Example:
- Postfix
.*
for.manyOrNone()
.- Example:
let classDef = (attribute | method).*
- Example:
- Postfix
.?
for.optional()
.- Example:
let declaration = "let" ~~> id ~~ (":" ~~> type).? ~~ ("=" ~~> expression)
- Example:
- Postfix
+
for.manyConcatenated()
.- Example:
let skippedSpaces = (Lexer.space | Lexer.tab)+
- Example:
- Infix
+
for.concatenatingResult(with:)
.- Example:
let type = Lexer.upperLetter + Lexer.letter*
- Example:
Lexer.regex(_:)
for directly applying regular expressions.- Example:
let id = Lexer.regex("[a-zA-Z][a-zA-Z0-9]*")
- Example:
- Postfix
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 "%"
- For example:
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
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 all licence references and agreements mentioned in the Parsey README section above
are relevant to that project's source code only.