• Stars
    star
    96
  • Rank 351,245 (Top 7 %)
  • Language
    Objective-C
  • License
    Other
  • Created almost 12 years ago
  • Updated over 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Objective-C Parser Combinators

#Parcoa: Objective-C Parser Combinators Parcoa is a collection of parsers and parser combinators for Objective-C inspired by Haskell's Parsec package and Python's Parcon library. It is released under a MIT license.

Pure Parcoa Parsers

A ParcoaParser * is a lite wrapper around a function block that takes a single NSString * argument, attempts to parse some value from this string, then returns an OK or Fail result. On success, the parser block returns the parsed value, the unconsumed residual input, and a message indicating what input would have allowed the parser to consume more characters. On failure, the parser block returns a string description of what it expected to find in the input.

Parser Diagram

Consider a very simple parser that expects the unicode character 'a'

ParcoaParser *simpleA = [Parcoa unichar:'a'];

If we pass it the string "abcd", it parses the first character and returns an OK result:

ParcoaResult *result = [simpleA parse:@"abcd"];

result.isOK == TRUE
result.value == @"a"

If there's no leading 'a' then parsing fails:

ParcoaResult *result = [simpleA parse:@"bcd"];

result.isFail == TRUE

What the heck is a parser combinator?

Although simple and self-contained, basic Parcoa parsers are useless in isolation. A parser combinator is a function that takes one or more parsers and creates a new parser with added functionality. Combined parsers can be further combined, enabling complex parsing behaviour via composition of parsing primitives.

For example, instead of a single 'a' character, we can match any consecutive sequence of a's

ParcoaParser *manyA = [Parcoa many:simpleA];

ParcoaResult *result = [manyA parse:@"aaaabcd"];

result.isOK == TRUE
result.value == @[@"a", @"a", @"a", @"a"]]

Perhaps we want to match any consecutive sequence of a's or the string "hello"

ParcoaParser *hello = [Parcoa string:@"hello"];
ParcoaParser *manyAConcat = [manyA concat];
ParcoaParser *thisorthat = [manyAConcat or: hello];

ParcoaResult *result = [thisorthat parse:@"helloworld"];

result.isOK == TRUE
result.value == @"hello"

result = [thisorthat parse:@"aaaaaworld"];

result.isOK == TRUE
result.value = @"aaaaa"

A simple JSON parser

Below is a simple JSON Parcoa parser. It currently only supports integral number literals.

ParcoaParser *colon        = [[Parcoa unichar:':'] skipSurroundingSpaces];
ParcoaParser *comma        = [[Parcoa unichar:','] skipSurroundingSpaces];
ParcoaParser *openBrace    = [[Parcoa unichar:'{'] skipSurroundingSpaces];
ParcoaParser *closeBrace   = [[Parcoa unichar:'}'] skipSurroundingSpaces];
ParcoaParser *openBracket  = [[Parcoa unichar:'['] skipSurroundingSpaces];
ParcoaParser *closeBracket = [[Parcoa unichar:']'] skipSurroundingSpaces];

ParcoaParser *quote         = [Parcoa unichar:'"'];
ParcoaParser *notQuote      = [Parcoa noneOf:@"\""];
ParcoaParser *escapedQuote  = [Parcoa string:@"\\\""];
ParcoaParser *stringContent = [Parcoa concatMany:[escapedQuote or: notQuote]];

ParcoaParserForward *json = [ParcoaParserForward forwardWithName:@"json"
                                                         summary:@"json forward declaration"];

ParcoaParser *string  = [stringContent between:quote and: quote];
ParcoaParser *null    = [Parcoa string:@"null"];
ParcoaParser *boolean = [Parcoa bool];
ParcoaParser *integer = [Parcoa integer];
ParcoaParser *pair    = [[string keepLeft: colon] then: json];
ParcoaParser *object  = [[[pair sepBy:comma] between:openBrace   and: closeBrace] dictionary];
ParcoaParser *list    =  [[json sepBy:comma] between:openBracket and: closeBracket];

[json setImplementation:[Parcoa choice:@[object, list, string, integer, boolean, null]]];

If we run the parser on some input

ParcoaResult *result = [json parse:@"[{\"name\" : \"James\", \"age\" : 28, \"active\" : true}]"];
NSLog(@"%@", result.value);

we get native Objective-C objects as output

2013-01-03 11:16:46.666 ParcoaJSONExample[20822:c07] (
        {
        Active = 1;
        Age = 28;
        Name = James;
    }
)

Paroca parsers generate tracebacks when fed invalid input

NSString *input = @"[{\"name\" : \"James\", \"age\" : 28 \"active\" : true}]";
ParcoaResult *result = [json parse:input];
NSLog(@"%@", [result traceback:input]);
2013-01-04 00:20:55.691 ParcoaJSONExample[26758:c07] Line 1 Column 1: Expected one or more matches.
  Line 1 Column 1: Expected all parsers in sequence to match.
    Line 1 Column 2: Expected optional child parser matched.
	  Line 1 Column 2: Expected one or more separated items.
		Line 1 Column 2: Expected all parsers in sequence to match.
		  Line 1 Column 2: Expected one or more matches.
			Line 1 Column 2: Expected all parsers in sequence to match.
              Line 1 Column 31: Expected more matches of delimiter and child parser.
			    Line 1 Column 31: Expected more matches of child parser.
			      Line 1 Column 31: Expected all parsers in sequence to match.
					Line 1 Column 31: Expected all parsers in sequence to match.
				  	  Line 1 Column 32: Expected Character matching predicate inCharacterSet(whitespace).
					  Line 1 Column 32: Expected Character matching predicate isUnichar(',').
			  Line 1 Column 31: Expected all parsers in sequence to match.
			    Line 1 Column 32: Expected Character matching predicate inCharacterSet(whitespace).
				Line 1 Column 32: Expected Character matching predicate isUnichar('}').

The parser encountered invalid input at Line 1 Column 32 and was expecting a space, comma , or close brace }.

Contributing

Parcoa is still in active development. Some current sore points:

  • There is some unit test coverage. Ideally all primitive parsers and combinators will have full unit tests.
  • There are no performance benchmarks.
  • Most of the Parsec combinators are implemented. If you find a recurring primitive pattern or combinator during your parsing travails, feel free to send a pull request.
  • Error reporting and tracebacks are currently programmer and not end user friendly.

Installing

You can clone Parcoa from it's github repository or install it using CocoaPods.

I recommend using CocoaPods because all your linking, build settings, and header includes are set automatically. If you clone from github you'll have to configure these settings manually.

CocoaPod

Install and configure CocoaPods.

In the root of your project create a file named Podfile containing

platform :ios
xcodeproj '<# YOUR PROJECT #>.xcodeproj'
pod 'Parcoa', :git => "https://github.com/brotchie/Parcoa.git"

then run

pod install

Note: After running pod install open <# YOUR PROJECT #>.xcworkspace in xcode, not <# YOUR PROJECT #>.xcodeproj.

Git

Parcoa builds a static library libParcoa.a. The library target is in Parcoa.xcodeproj. To link Parcoa with your target:

  1. Clone the Parcoa github repostiory git clone https://github.com/brotchie/Parcoa.git.
  2. Drag Parcoa.xcodeproj into your XCode project.
  3. Add libParcoa.a (Parcoa OS X.dylib on OSX) to Link Binary With Libraries on your target's Build Phases tab.
  4. Ensure Parcoa (Parcoa) (Parcoa OS X (Parcoa) on OSX) is in Target Dependencies on your target's Build Phases tab.
  5. Add the Parcoa directory as a recursive path to User Header Search Paths and set Always Search User Paths to YES on your target's Build Settings tab.
  6. Add -ObjC to Other Linker Flags on your target's Build Settings tab.

Git Submodule

From the root of your project clone the Parcoa repository into a git submodule

mkdir -p Submodules
git submodule add https://github.com/brotchie/Parcoa.git Submodules/Parcoa
git submodule update --init

then follow the steps under the Git heading above.

More Repositories

1

torch-ubuntu-gpu-ec2-install

Guide for installing Torch machine learning library onto a GPU EC2 instance running Ubuntu
72
star
2

python-sty

Embed Python in LaTeX
Vim Script
50
star
3

ib-zmq

Interactive Brokers API to ZeroMQ proxy
Python
41
star
4

SwiftTableView

Basic example of using the Swift language to populate a UITableView
Swift
39
star
5

py2vba

Converts a restricted subset of Python into Visual Basic for Applications.
Python
35
star
6

eulerianmagnify

Eulerian video magnification in Matlab
MATLAB
29
star
7

howfastisthenbn.com.au

howfastisthenbn.com.au website source
HTML
28
star
8

tradelink

Unofficial tradelink mirror (tradelink.org).
C#
28
star
9

FPMultiFetchedResultsController

An extended NSFetchResultsController that supports multiple underlying NSFetchRequests.
Objective-C
21
star
10

pyrtd

Python client for Excel RealTimeData components.
Python
15
star
11

docker-links

A helper for parsing Docker link environment variables.
JavaScript
14
star
12

protobuf-textformat

Javascript protobuf text format parser and encoder
JavaScript
14
star
13

dogecoin-code-snippets

Code samples for programmatically interacting with dogecoind and various other dogecoin APIs.
JavaScript
13
star
14

keepnote

Unofficial Keepnote fork (http://keepnote.org/)
Python
11
star
15

pyforex

Write Dukascopy JForex trading strategies in Jython.
Python
10
star
16

CocoaFlux

In-progress implementation of the Facebook Flux architectural pattern for iOS.
Objective-C
10
star
17

machine-learning-must-watch

Must-watch videos about Machine Learning
8
star
18

r-zerotws

A R package for communicating with the Interactive Brokers TWS API via a ZeroMQ proxy.
R
8
star
19

bitbucket-github-export

Exports bitbucket repositories to github.
Python
5
star
20

pytrth

Pythonic interface and helpers for the Thomson Reuters Tick History API web service.
Python
5
star
21

roroaring64

Deserialize 64 bit roaring bitmaps into a Python set of integers.
Python
4
star
22

zerotick-ib

ØTick Interactive Brokers interface.
Java
4
star
23

zerotick-oms

The minimalist order management system for the ØTick trading framework.
Scala
4
star
24

excelbt

The Excel Build Toolkit (excelbt) is a collection of Python scripts to manage Excel macros within a Software Engineering Process.
Python
4
star
25

pymendeley

Python library for accessing the local Mendeley sqlite3 database.
Python
3
star
26

pyress

Pythonic wrapper around the IRESS COM interface.
Python
3
star
27

Quality-Mods-Program

Quality-of-Life mods for Dyson Sphere Program
C#
3
star
28

rgmorderbook

Haskell implementation of the RGM Advisors Order Book Programming Problem
Haskell
3
star
29

starpusher

Cheaply drive APA102 / WS2812b LED strips over Ethernet
C
3
star
30

CocoaRoutes

A Minimalist Web Framework for Objective-C inspired by Python's Routes.
Objective-C
2
star
31

matlab-sqlite3

Simple Matlab wrapper for the sqlitejdbc JDBC interface.
MATLAB
2
star
32

gbookscmd

Command line tool for programmatic access to Google books bookshelves.
Python
2
star
33

zerotick-core

ØTick trading framework core.
Haskell
2
star
34

dogetunnel

Prototype of a dogecoin funded on-demand VPN service
JavaScript
2
star
35

brotchie-euler

Project Euler solutions in Python, C, C++, and x86-64 assembly.
Python
2
star
36

openaustralia-node

Node.js bindings for http://openaustralia.org/ API
JavaScript
2
star
37

export_freemind

A plugin for KeepNote that export to FreeMind mind maps.
Python
2
star
38

openyogurt

Open source yogurt maker combining an Arduino with slow cooker.
C++
2
star
39

lambda-sd-webui

Automatically manage an ephemeral instance of stable-diffusion-webui running on LambdaLabs
Python
2
star
40

dcpu16parcon

0x10c DCPU-16 assembler in Python using the parcon parsing library.
Python
2
star
41

keepnote_mendeley

A Keepnote extension that adds Mendeley linking features.
Python
1
star
42

hs-gntp

Haskell library for parsing and encoding the Growl Notification Transport Protocol
Haskell
1
star
43

latex-rubber-makefile

GNU Makefile for building LaTeX documents with Rubber.
1
star
44

brotchie.github.io

Pelican generated website for brotchie.github.io
CSS
1
star
45

quantcodebites

Code posted to my QuantCodeBites blog.
MATLAB
1
star
46

rzmq-reactor

A simple event reactor for ZeroMQ sockets in R.
R
1
star
47

zerotick-ns

ØMQ based name service for the ØTick trading framework.
Objective-C
1
star
48

FacebookTigaseAuthPlugin

Facebook auth plugin for the Tigase XMPP server.
Java
1
star
49

bankcharts

Banking and Finance Related Charts for Excel
Visual Basic
1
star
50

metalit

Tool for writing a marked-up literature review with meta-data. Loads citation information from Mendeley Desktop.
Python
1
star
51

altcoinstatic

Example of using coinyecoind (and dogecoind) JSON-RPC to fetch account balances and generate a static web page.
Python
1
star
52

indexing

Unofficial clone of the R indexing package (http://r-forge.r-project.org/projects/indexing/)
C
1
star
53

iphone-13-pro-max-availability-checker

Simple checker for iPhone 13 Pro Max availability
Python
1
star
54

redsapp

jQuery mobile prototype developed for tracking community sports engagement.
JavaScript
1
star
55

xmobar-mtgox

Quick Python and crude Haskell scripts to get MtGox Bitcoin exchange rates in xmobar.
Haskell
1
star