Parsey alternatives and similar libraries
Based on the "Text" category.
Alternatively, view Parsey alternatives based on common mentions on social networks and blogs.
-
PhoneNumberKit
A 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. -
RichEditorView
DISCONTINUED. RichEditorView is a simple, modular, drop-in UIView subclass for Rich Text Editing. -
Atributika
Convert text with HTML tags, links, hashtags, mentions into NSAttributedString. Make them clickable with UILabel drop-in replacement. -
Mustard
🌭 Mustard is a Swift library for tokenizing strings when splitting by whitespace doesn't cut it. -
PrediKit
An NSPredicate DSL for iOS, OSX, tvOS, & watchOS. Inspired by SnapKit and lovingly written in Swift. -
AttributedTextView
Easiest way to create an attributed UITextView (with support for multiple links and from html) -
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
InfluxDB - Purpose built for real-time analytics at any scale.
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
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.