Repository files navigation

Parsel

SwiftBuild StatusCodecov branchCocoaPodsLicense

Parsel is a parser combinator library that makes it easy to write parsers. Parser combinators lets you create simple parses that can be combined together to very complex ones. Take for example a parser that parses a digit from a given String: (You can use the pre-defined lexical parser for digit: L.digit)

letdigit=Parser<String,Int>{ input inguardlet first = input.first,let number =Int(String(first))else{return.fail(/* some pre-defined error */)}return.success(result: number, rest:String(input.dropFirst()))}

We can now simply extend this to create a parser that parses an addition of two digits from a string:

letaddition=(digit ~ L.plus ~ digit).map{ a, _, b in a + b } // `L.plus` is a predefined parser that parses the `+` sign
letresult= addition.parse("2+4")try! result.unwrap() // Int: 6

Why should I use this?

Parsing is a very common task, it does not always mean to parse source code or JSON strings. Parsing means to transform an unstructured input to a structured output. In case of source code this means to parse a raw string to an AST (abstract syntax tree), in case of an addition it means to parse the result of adding two numbers out of a string. Parsing can always fail, if the input does not match the needed grammer. If the input string in the above example would have been 1+, it would have been failed because the second number is missing. The advantage of parser combinators is that you start with a very basic parser. In the above example digit parses only one digit. But it is not hard, to add a parser that parses more than one digit. A number is a repetition of mulitple digits. For repetition, we can use rep, which tries to apply the parser until it fails and collects the result as an array. Parsing an integer addition is as easy as

func intFromDigits(_ digits:[Int])->Int{return digits.reduce(0){ res, e inreturn res *10+ e
}}letnumber= digit.rep.map(intFromDigits)letaddition= number ~ L.plus ~ number ^^{ a, _, b in // ^^ is convenience for map
return a + b
}letresult= addition.parse("123+456")try! result.unwrap() // Int: 579

(There is also a pre-defined lexical parser for numbers L.number that is able to parse a number in different formats [binary, octal, hexadecimal, decimal])

What are the disadvantages?

Since parser combinators are very high level, they abstract the whole process of parsing a lot. That means it is easier to use but it also means that the performance is not as good as an optimized, handwritten parser.

Installation

Parsel is currently available via Swift Package Manager and Cocoapods. Support for Carthage will come later.

Swift Package Manager

To use Parsel in your project, just add it as a dependency in your Package.swift file and run swift package update.

import PackageDescription
letpackage=Package(
name:"MyAwesomeApp",
dependencies:[.package(url:"https://github.com/BenchR267/Parsel", from:"3.0.2")])

Cocoapods

To use Parsel with Cocoapods, just add this entry to your Podfile and run pod install:

target'MyAwesomeApp'douse_frameworks!pod'Parsel'end

Requirements

  • Swift 4.0
    • Parsel is written in Swift 4.0 development snapshots and will be available when Swift 4.0 is released

Example

Calculator is a small example I wrote with Parsel.

Calculator_GIF

Documentation

Check out the documentation on the Github page.

Author

Contributing

To start contributing to Parsel please clone the project and configure it initially:

$ git clone git@github.com:BenchR267/Parsel.git
$ cd Parsel
$ make initial

Please make sure that all tests are green before you submit a pull request by running make test.

If you experience a bug or have an idea for a feature request but you don't know where to get started: feel free to open an issue with a self-explaining description text.

If you have an idea for a better (more readable and/or faster) implementation for an existing function: feel free to change the code and submit a pull request. I will be more than happy to review the changes to make Parsel the best project it can be!

License

Parsel is under MIT license. See the LICENSE file for more info.

About

Create complex parsers by combining simple ones with Parsel!

Topics

Resources

Code of conduct

Stars

22 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Parsel

SwiftBuild StatusCodecov branchCocoaPodsLicense

Parsel is a parser combinator library that makes it easy to write parsers. Parser combinators lets you create simple parses that can be combined together to very complex ones. Take for example a parser that parses a digit from a given String: (You can use the pre-defined lexical parser for digit: L.digit)

letdigit=Parser<String,Int>{ input inguardlet first = input.first,let number =Int(String(first))else{return.fail(/* some pre-defined error */)}return.success(result: number, rest:String(input.dropFirst()))}

We can now simply extend this to create a parser that parses an addition of two digits from a string:

letaddition=(digit ~ L.plus ~ digit).map{ a, _, b in a + b } // `L.plus` is a predefined parser that parses the `+` sign
letresult= addition.parse("2+4")try! result.unwrap() // Int: 6

Why should I use this?

Parsing is a very common task, it does not always mean to parse source code or JSON strings. Parsing means to transform an unstructured input to a structured output. In case of source code this means to parse a raw string to an AST (abstract syntax tree), in case of an addition it means to parse the result of adding two numbers out of a string. Parsing can always fail, if the input does not match the needed grammer. If the input string in the above example would have been 1+, it would have been failed because the second number is missing. The advantage of parser combinators is that you start with a very basic parser. In the above example digit parses only one digit. But it is not hard, to add a parser that parses more than one digit. A number is a repetition of mulitple digits. For repetition, we can use rep, which tries to apply the parser until it fails and collects the result as an array. Parsing an integer addition is as easy as

func intFromDigits(_ digits:[Int])->Int{return digits.reduce(0){ res, e inreturn res *10+ e
}}letnumber= digit.rep.map(intFromDigits)letaddition= number ~ L.plus ~ number ^^{ a, _, b in // ^^ is convenience for map
return a + b
}letresult= addition.parse("123+456")try! result.unwrap() // Int: 579

(There is also a pre-defined lexical parser for numbers L.number that is able to parse a number in different formats [binary, octal, hexadecimal, decimal])

What are the disadvantages?

Since parser combinators are very high level, they abstract the whole process of parsing a lot. That means it is easier to use but it also means that the performance is not as good as an optimized, handwritten parser.

Installation

Parsel is currently available via Swift Package Manager and Cocoapods. Support for Carthage will come later.

Swift Package Manager

To use Parsel in your project, just add it as a dependency in your Package.swift file and run swift package update.

import PackageDescription
letpackage=Package(
name:"MyAwesomeApp",
dependencies:[.package(url:"https://github.com/BenchR267/Parsel", from:"3.0.2")])

Cocoapods

To use Parsel with Cocoapods, just add this entry to your Podfile and run pod install:

target'MyAwesomeApp'douse_frameworks!pod'Parsel'end

Requirements

  • Swift 4.0
    • Parsel is written in Swift 4.0 development snapshots and will be available when Swift 4.0 is released

Example

Calculator is a small example I wrote with Parsel.

Calculator_GIF

Documentation

Check out the documentation on the Github page.

Author

Contributing

To start contributing to Parsel please clone the project and configure it initially:

$ git clone git@github.com:BenchR267/Parsel.git
$ cd Parsel
$ make initial

Please make sure that all tests are green before you submit a pull request by running make test.

If you experience a bug or have an idea for a feature request but you don't know where to get started: feel free to open an issue with a self-explaining description text.

If you have an idea for a better (more readable and/or faster) implementation for an existing function: feel free to change the code and submit a pull request. I will be more than happy to review the changes to make Parsel the best project it can be!

License

Parsel is under MIT license. See the LICENSE file for more info.

About

Create complex parsers by combining simple ones with Parsel!

Topics

Resources

Code of conduct

Stars

22 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Parsel

SwiftBuild StatusCodecov branchCocoaPodsLicense

Parsel is a parser combinator library that makes it easy to write parsers. Parser combinators lets you create simple parses that can be combined together to very complex ones. Take for example a parser that parses a digit from a given String: (You can use the pre-defined lexical parser for digit: L.digit)

letdigit=Parser<String,Int>{ input inguardlet first = input.first,let number =Int(String(first))else{return.fail(/* some pre-defined error */)}return.success(result: number, rest:String(input.dropFirst()))}

We can now simply extend this to create a parser that parses an addition of two digits from a string:

letaddition=(digit ~ L.plus ~ digit).map{ a, _, b in a + b } // `L.plus` is a predefined parser that parses the `+` sign
letresult= addition.parse("2+4")try! result.unwrap() // Int: 6

Why should I use this?

Parsing is a very common task, it does not always mean to parse source code or JSON strings. Parsing means to transform an unstructured input to a structured output. In case of source code this means to parse a raw string to an AST (abstract syntax tree), in case of an addition it means to parse the result of adding two numbers out of a string. Parsing can always fail, if the input does not match the needed grammer. If the input string in the above example would have been 1+, it would have been failed because the second number is missing. The advantage of parser combinators is that you start with a very basic parser. In the above example digit parses only one digit. But it is not hard, to add a parser that parses more than one digit. A number is a repetition of mulitple digits. For repetition, we can use rep, which tries to apply the parser until it fails and collects the result as an array. Parsing an integer addition is as easy as

func intFromDigits(_ digits:[Int])->Int{return digits.reduce(0){ res, e inreturn res *10+ e
}}letnumber= digit.rep.map(intFromDigits)letaddition= number ~ L.plus ~ number ^^{ a, _, b in // ^^ is convenience for map
return a + b
}letresult= addition.parse("123+456")try! result.unwrap() // Int: 579

(There is also a pre-defined lexical parser for numbers L.number that is able to parse a number in different formats [binary, octal, hexadecimal, decimal])

What are the disadvantages?

Since parser combinators are very high level, they abstract the whole process of parsing a lot. That means it is easier to use but it also means that the performance is not as good as an optimized, handwritten parser.

Installation

Parsel is currently available via Swift Package Manager and Cocoapods. Support for Carthage will come later.

Swift Package Manager

To use Parsel in your project, just add it as a dependency in your Package.swift file and run swift package update.

import PackageDescription
letpackage=Package(
name:"MyAwesomeApp",
dependencies:[.package(url:"https://github.com/BenchR267/Parsel", from:"3.0.2")])

Cocoapods

To use Parsel with Cocoapods, just add this entry to your Podfile and run pod install:

target'MyAwesomeApp'douse_frameworks!pod'Parsel'end

Requirements

  • Swift 4.0
    • Parsel is written in Swift 4.0 development snapshots and will be available when Swift 4.0 is released

Example

Calculator is a small example I wrote with Parsel.

Calculator_GIF

Documentation

Check out the documentation on the Github page.

Author

Contributing

To start contributing to Parsel please clone the project and configure it initially:

$ git clone git@github.com:BenchR267/Parsel.git
$ cd Parsel
$ make initial

Please make sure that all tests are green before you submit a pull request by running make test.

If you experience a bug or have an idea for a feature request but you don't know where to get started: feel free to open an issue with a self-explaining description text.

If you have an idea for a better (more readable and/or faster) implementation for an existing function: feel free to change the code and submit a pull request. I will be more than happy to review the changes to make Parsel the best project it can be!

License

Parsel is under MIT license. See the LICENSE file for more info.

About

Create complex parsers by combining simple ones with Parsel!

Topics

Resources

Code of conduct

Stars

22 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Parsel

SwiftBuild StatusCodecov branchCocoaPodsLicense

Parsel is a parser combinator library that makes it easy to write parsers. Parser combinators lets you create simple parses that can be combined together to very complex ones. Take for example a parser that parses a digit from a given String: (You can use the pre-defined lexical parser for digit: L.digit)

letdigit=Parser<String,Int>{ input inguardlet first = input.first,let number =Int(String(first))else{return.fail(/* some pre-defined error */)}return.success(result: number, rest:String(input.dropFirst()))}

We can now simply extend this to create a parser that parses an addition of two digits from a string:

letaddition=(digit ~ L.plus ~ digit).map{ a, _, b in a + b } // `L.plus` is a predefined parser that parses the `+` sign
letresult= addition.parse("2+4")try! result.unwrap() // Int: 6

Why should I use this?

Parsing is a very common task, it does not always mean to parse source code or JSON strings. Parsing means to transform an unstructured input to a structured output. In case of source code this means to parse a raw string to an AST (abstract syntax tree), in case of an addition it means to parse the result of adding two numbers out of a string. Parsing can always fail, if the input does not match the needed grammer. If the input string in the above example would have been 1+, it would have been failed because the second number is missing. The advantage of parser combinators is that you start with a very basic parser. In the above example digit parses only one digit. But it is not hard, to add a parser that parses more than one digit. A number is a repetition of mulitple digits. For repetition, we can use rep, which tries to apply the parser until it fails and collects the result as an array. Parsing an integer addition is as easy as

func intFromDigits(_ digits:[Int])->Int{return digits.reduce(0){ res, e inreturn res *10+ e
}}letnumber= digit.rep.map(intFromDigits)letaddition= number ~ L.plus ~ number ^^{ a, _, b in // ^^ is convenience for map
return a + b
}letresult= addition.parse("123+456")try! result.unwrap() // Int: 579

(There is also a pre-defined lexical parser for numbers L.number that is able to parse a number in different formats [binary, octal, hexadecimal, decimal])

What are the disadvantages?

Since parser combinators are very high level, they abstract the whole process of parsing a lot. That means it is easier to use but it also means that the performance is not as good as an optimized, handwritten parser.

Installation

Parsel is currently available via Swift Package Manager and Cocoapods. Support for Carthage will come later.

Swift Package Manager

To use Parsel in your project, just add it as a dependency in your Package.swift file and run swift package update.

import PackageDescription
letpackage=Package(
name:"MyAwesomeApp",
dependencies:[.package(url:"https://github.com/BenchR267/Parsel", from:"3.0.2")])

Cocoapods

To use Parsel with Cocoapods, just add this entry to your Podfile and run pod install:

target'MyAwesomeApp'douse_frameworks!pod'Parsel'end

Requirements

  • Swift 4.0
    • Parsel is written in Swift 4.0 development snapshots and will be available when Swift 4.0 is released

Example

Calculator is a small example I wrote with Parsel.

Calculator_GIF

Documentation

Check out the documentation on the Github page.

Author

Contributing

To start contributing to Parsel please clone the project and configure it initially:

$ git clone git@github.com:BenchR267/Parsel.git
$ cd Parsel
$ make initial

Please make sure that all tests are green before you submit a pull request by running make test.

If you experience a bug or have an idea for a feature request but you don't know where to get started: feel free to open an issue with a self-explaining description text.

If you have an idea for a better (more readable and/or faster) implementation for an existing function: feel free to change the code and submit a pull request. I will be more than happy to review the changes to make Parsel the best project it can be!

License

Parsel is under MIT license. See the LICENSE file for more info.

About

Create complex parsers by combining simple ones with Parsel!

Topics

Resources

Code of conduct

Stars

22 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Parsel

SwiftBuild StatusCodecov branchCocoaPodsLicense

Parsel is a parser combinator library that makes it easy to write parsers. Parser combinators lets you create simple parses that can be combined together to very complex ones. Take for example a parser that parses a digit from a given String: (You can use the pre-defined lexical parser for digit: L.digit)

letdigit=Parser<String,Int>{ input inguardlet first = input.first,let number =Int(String(first))else{return.fail(/* some pre-defined error */)}return.success(result: number, rest:String(input.dropFirst()))}

We can now simply extend this to create a parser that parses an addition of two digits from a string:

letaddition=(digit ~ L.plus ~ digit).map{ a, _, b in a + b } // `L.plus` is a predefined parser that parses the `+` sign
letresult= addition.parse("2+4")try! result.unwrap() // Int: 6

Why should I use this?

Parsing is a very common task, it does not always mean to parse source code or JSON strings. Parsing means to transform an unstructured input to a structured output. In case of source code this means to parse a raw string to an AST (abstract syntax tree), in case of an addition it means to parse the result of adding two numbers out of a string. Parsing can always fail, if the input does not match the needed grammer. If the input string in the above example would have been 1+, it would have been failed because the second number is missing. The advantage of parser combinators is that you start with a very basic parser. In the above example digit parses only one digit. But it is not hard, to add a parser that parses more than one digit. A number is a repetition of mulitple digits. For repetition, we can use rep, which tries to apply the parser until it fails and collects the result as an array. Parsing an integer addition is as easy as

func intFromDigits(_ digits:[Int])->Int{return digits.reduce(0){ res, e inreturn res *10+ e
}}letnumber= digit.rep.map(intFromDigits)letaddition= number ~ L.plus ~ number ^^{ a, _, b in // ^^ is convenience for map
return a + b
}letresult= addition.parse("123+456")try! result.unwrap() // Int: 579

(There is also a pre-defined lexical parser for numbers L.number that is able to parse a number in different formats [binary, octal, hexadecimal, decimal])

What are the disadvantages?

Since parser combinators are very high level, they abstract the whole process of parsing a lot. That means it is easier to use but it also means that the performance is not as good as an optimized, handwritten parser.

Installation

Parsel is currently available via Swift Package Manager and Cocoapods. Support for Carthage will come later.

Swift Package Manager

To use Parsel in your project, just add it as a dependency in your Package.swift file and run swift package update.

import PackageDescription
letpackage=Package(
name:"MyAwesomeApp",
dependencies:[.package(url:"https://github.com/BenchR267/Parsel", from:"3.0.2")])

Cocoapods

To use Parsel with Cocoapods, just add this entry to your Podfile and run pod install:

target'MyAwesomeApp'douse_frameworks!pod'Parsel'end

Requirements

  • Swift 4.0
    • Parsel is written in Swift 4.0 development snapshots and will be available when Swift 4.0 is released

Example

Calculator is a small example I wrote with Parsel.

Calculator_GIF

Documentation

Check out the documentation on the Github page.

Author

Contributing

To start contributing to Parsel please clone the project and configure it initially:

$ git clone git@github.com:BenchR267/Parsel.git
$ cd Parsel
$ make initial

Please make sure that all tests are green before you submit a pull request by running make test.

If you experience a bug or have an idea for a feature request but you don't know where to get started: feel free to open an issue with a self-explaining description text.

If you have an idea for a better (more readable and/or faster) implementation for an existing function: feel free to change the code and submit a pull request. I will be more than happy to review the changes to make Parsel the best project it can be!

License

Parsel is under MIT license. See the LICENSE file for more info.

About

Create complex parsers by combining simple ones with Parsel!

Topics

Resources

Code of conduct

Stars

22 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Parsel

SwiftBuild StatusCodecov branchCocoaPodsLicense

Parsel is a parser combinator library that makes it easy to write parsers. Parser combinators lets you create simple parses that can be combined together to very complex ones. Take for example a parser that parses a digit from a given String: (You can use the pre-defined lexical parser for digit: L.digit)

letdigit=Parser<String,Int>{ input inguardlet first = input.first,let number =Int(String(first))else{return.fail(/* some pre-defined error */)}return.success(result: number, rest:String(input.dropFirst()))}

We can now simply extend this to create a parser that parses an addition of two digits from a string:

letaddition=(digit ~ L.plus ~ digit).map{ a, _, b in a + b } // `L.plus` is a predefined parser that parses the `+` sign
letresult= addition.parse("2+4")try! result.unwrap() // Int: 6

Why should I use this?

Parsing is a very common task, it does not always mean to parse source code or JSON strings. Parsing means to transform an unstructured input to a structured output. In case of source code this means to parse a raw string to an AST (abstract syntax tree), in case of an addition it means to parse the result of adding two numbers out of a string. Parsing can always fail, if the input does not match the needed grammer. If the input string in the above example would have been 1+, it would have been failed because the second number is missing. The advantage of parser combinators is that you start with a very basic parser. In the above example digit parses only one digit. But it is not hard, to add a parser that parses more than one digit. A number is a repetition of mulitple digits. For repetition, we can use rep, which tries to apply the parser until it fails and collects the result as an array. Parsing an integer addition is as easy as

func intFromDigits(_ digits:[Int])->Int{return digits.reduce(0){ res, e inreturn res *10+ e
}}letnumber= digit.rep.map(intFromDigits)letaddition= number ~ L.plus ~ number ^^{ a, _, b in // ^^ is convenience for map
return a + b
}letresult= addition.parse("123+456")try! result.unwrap() // Int: 579

(There is also a pre-defined lexical parser for numbers L.number that is able to parse a number in different formats [binary, octal, hexadecimal, decimal])

What are the disadvantages?

Since parser combinators are very high level, they abstract the whole process of parsing a lot. That means it is easier to use but it also means that the performance is not as good as an optimized, handwritten parser.

Installation

Parsel is currently available via Swift Package Manager and Cocoapods. Support for Carthage will come later.

Swift Package Manager

To use Parsel in your project, just add it as a dependency in your Package.swift file and run swift package update.

import PackageDescription
letpackage=Package(
name:"MyAwesomeApp",
dependencies:[.package(url:"https://github.com/BenchR267/Parsel", from:"3.0.2")])

Cocoapods

To use Parsel with Cocoapods, just add this entry to your Podfile and run pod install:

target'MyAwesomeApp'douse_frameworks!pod'Parsel'end

Requirements

  • Swift 4.0
    • Parsel is written in Swift 4.0 development snapshots and will be available when Swift 4.0 is released

Example

Calculator is a small example I wrote with Parsel.

Calculator_GIF

Documentation

Check out the documentation on the Github page.

Author

Contributing

To start contributing to Parsel please clone the project and configure it initially:

$ git clone git@github.com:BenchR267/Parsel.git
$ cd Parsel
$ make initial

Please make sure that all tests are green before you submit a pull request by running make test.

If you experience a bug or have an idea for a feature request but you don't know where to get started: feel free to open an issue with a self-explaining description text.

If you have an idea for a better (more readable and/or faster) implementation for an existing function: feel free to change the code and submit a pull request. I will be more than happy to review the changes to make Parsel the best project it can be!

License

Parsel is under MIT license. See the LICENSE file for more info.

About

Create complex parsers by combining simple ones with Parsel!

Topics

Resources

Code of conduct

Stars

22 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Parsel

SwiftBuild StatusCodecov branchCocoaPodsLicense

Parsel is a parser combinator library that makes it easy to write parsers. Parser combinators lets you create simple parses that can be combined together to very complex ones. Take for example a parser that parses a digit from a given String: (You can use the pre-defined lexical parser for digit: L.digit)

letdigit=Parser<String,Int>{ input inguardlet first = input.first,let number =Int(String(first))else{return.fail(/* some pre-defined error */)}return.success(result: number, rest:String(input.dropFirst()))}

We can now simply extend this to create a parser that parses an addition of two digits from a string:

letaddition=(digit ~ L.plus ~ digit).map{ a, _, b in a + b } // `L.plus` is a predefined parser that parses the `+` sign
letresult= addition.parse("2+4")try! result.unwrap() // Int: 6

Why should I use this?

Parsing is a very common task, it does not always mean to parse source code or JSON strings. Parsing means to transform an unstructured input to a structured output. In case of source code this means to parse a raw string to an AST (abstract syntax tree), in case of an addition it means to parse the result of adding two numbers out of a string. Parsing can always fail, if the input does not match the needed grammer. If the input string in the above example would have been 1+, it would have been failed because the second number is missing. The advantage of parser combinators is that you start with a very basic parser. In the above example digit parses only one digit. But it is not hard, to add a parser that parses more than one digit. A number is a repetition of mulitple digits. For repetition, we can use rep, which tries to apply the parser until it fails and collects the result as an array. Parsing an integer addition is as easy as

func intFromDigits(_ digits:[Int])->Int{return digits.reduce(0){ res, e inreturn res *10+ e
}}letnumber= digit.rep.map(intFromDigits)letaddition= number ~ L.plus ~ number ^^{ a, _, b in // ^^ is convenience for map
return a + b
}letresult= addition.parse("123+456")try! result.unwrap() // Int: 579

(There is also a pre-defined lexical parser for numbers L.number that is able to parse a number in different formats [binary, octal, hexadecimal, decimal])

What are the disadvantages?

Since parser combinators are very high level, they abstract the whole process of parsing a lot. That means it is easier to use but it also means that the performance is not as good as an optimized, handwritten parser.

Installation

Parsel is currently available via Swift Package Manager and Cocoapods. Support for Carthage will come later.

Swift Package Manager

To use Parsel in your project, just add it as a dependency in your Package.swift file and run swift package update.

import PackageDescription
letpackage=Package(
name:"MyAwesomeApp",
dependencies:[.package(url:"https://github.com/BenchR267/Parsel", from:"3.0.2")])

Cocoapods

To use Parsel with Cocoapods, just add this entry to your Podfile and run pod install:

target'MyAwesomeApp'douse_frameworks!pod'Parsel'end

Requirements

  • Swift 4.0
    • Parsel is written in Swift 4.0 development snapshots and will be available when Swift 4.0 is released

Example

Calculator is a small example I wrote with Parsel.

Calculator_GIF

Documentation

Check out the documentation on the Github page.

Author

Contributing

To start contributing to Parsel please clone the project and configure it initially:

$ git clone git@github.com:BenchR267/Parsel.git
$ cd Parsel
$ make initial

Please make sure that all tests are green before you submit a pull request by running make test.

If you experience a bug or have an idea for a feature request but you don't know where to get started: feel free to open an issue with a self-explaining description text.

If you have an idea for a better (more readable and/or faster) implementation for an existing function: feel free to change the code and submit a pull request. I will be more than happy to review the changes to make Parsel the best project it can be!

License

Parsel is under MIT license. See the LICENSE file for more info.

About

Create complex parsers by combining simple ones with Parsel!

Topics

Resources

Code of conduct

Stars

22 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Parsel

SwiftBuild StatusCodecov branchCocoaPodsLicense

Parsel is a parser combinator library that makes it easy to write parsers. Parser combinators lets you create simple parses that can be combined together to very complex ones. Take for example a parser that parses a digit from a given String: (You can use the pre-defined lexical parser for digit: L.digit)

letdigit=Parser<String,Int>{ input inguardlet first = input.first,let number =Int(String(first))else{return.fail(/* some pre-defined error */)}return.success(result: number, rest:String(input.dropFirst()))}

We can now simply extend this to create a parser that parses an addition of two digits from a string:

letaddition=(digit ~ L.plus ~ digit).map{ a, _, b in a + b } // `L.plus` is a predefined parser that parses the `+` sign
letresult= addition.parse("2+4")try! result.unwrap() // Int: 6

Why should I use this?

Parsing is a very common task, it does not always mean to parse source code or JSON strings. Parsing means to transform an unstructured input to a structured output. In case of source code this means to parse a raw string to an AST (abstract syntax tree), in case of an addition it means to parse the result of adding two numbers out of a string. Parsing can always fail, if the input does not match the needed grammer. If the input string in the above example would have been 1+, it would have been failed because the second number is missing. The advantage of parser combinators is that you start with a very basic parser. In the above example digit parses only one digit. But it is not hard, to add a parser that parses more than one digit. A number is a repetition of mulitple digits. For repetition, we can use rep, which tries to apply the parser until it fails and collects the result as an array. Parsing an integer addition is as easy as

func intFromDigits(_ digits:[Int])->Int{return digits.reduce(0){ res, e inreturn res *10+ e
}}letnumber= digit.rep.map(intFromDigits)letaddition= number ~ L.plus ~ number ^^{ a, _, b in // ^^ is convenience for map
return a + b
}letresult= addition.parse("123+456")try! result.unwrap() // Int: 579

(There is also a pre-defined lexical parser for numbers L.number that is able to parse a number in different formats [binary, octal, hexadecimal, decimal])

What are the disadvantages?

Since parser combinators are very high level, they abstract the whole process of parsing a lot. That means it is easier to use but it also means that the performance is not as good as an optimized, handwritten parser.

Installation

Parsel is currently available via Swift Package Manager and Cocoapods. Support for Carthage will come later.

Swift Package Manager

To use Parsel in your project, just add it as a dependency in your Package.swift file and run swift package update.

import PackageDescription
letpackage=Package(
name:"MyAwesomeApp",
dependencies:[.package(url:"https://github.com/BenchR267/Parsel", from:"3.0.2")])

Cocoapods

To use Parsel with Cocoapods, just add this entry to your Podfile and run pod install:

target'MyAwesomeApp'douse_frameworks!pod'Parsel'end

Requirements

  • Swift 4.0
    • Parsel is written in Swift 4.0 development snapshots and will be available when Swift 4.0 is released

Example

Calculator is a small example I wrote with Parsel.

Calculator_GIF

Documentation

Check out the documentation on the Github page.

Author

Contributing

To start contributing to Parsel please clone the project and configure it initially:

$ git clone git@github.com:BenchR267/Parsel.git
$ cd Parsel
$ make initial

Please make sure that all tests are green before you submit a pull request by running make test.

If you experience a bug or have an idea for a feature request but you don't know where to get started: feel free to open an issue with a self-explaining description text.

If you have an idea for a better (more readable and/or faster) implementation for an existing function: feel free to change the code and submit a pull request. I will be more than happy to review the changes to make Parsel the best project it can be!

License

Parsel is under MIT license. See the LICENSE file for more info.

About

Create complex parsers by combining simple ones with Parsel!

Topics

Resources

Code of conduct

Stars

22 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages