Skip to content

Commit

Permalink
Create README.MD
Browse files Browse the repository at this point in the history
  • Loading branch information
amnykon authored Sep 5, 2017
1 parent ad15c85 commit 84d0d3c
Showing 1 changed file with 164 additions and 0 deletions.
164 changes: 164 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# SParser
SParser creates easy to use file or string parsers in swift code using a file format that is based on [Backus–Naur form](https://en.wikipedia.org/wiki/Backus–Naur_form)

To user Sparser:
1. Create a .sparser file that describes the file format.
2. Run SParser <filename> to compile the .sparser file to .sparser.swift.
3. compile .sparser.swift with the code that uses the .sparser along with SParserLibs.

## .sparser file format

The SParser parser is written in SParser, which provides an exsample of how to use it. Quotes are from this file. See [SParser.sparser](https://github.com/amnykon/SParser/blob/master/Sources/SParserPrivate/SParser.sparser).

When compiled, Sparser.sparser generates [SParser.sparser.swift](https://github.com/amnykon/SParser/blob/master/Sources/SParserPrivate/SParser.sparser)

The file contains an optinal imports rule and one or more rules.

### Import rule

The import rule converts each import in to a swift import statement, allowing the generated swift code to use other packages.

SParserLibs provides the Parser, Streams objects required to parse the file. This should always be used.

``` SParser
imports
Foundation
SParserLibs
```

``` swift
import Foundation
import SParserLibs
```

### Rules
A SParser file contains rules that describe the file format.

Each rule has the following:
1. Name
2. Type
3. One or more patterns.

``` SParser
rules (1)
type (2)
[Rule] (2)
::= rules rule (3)
return rules + [rule] (3)
::= (3)
return [] (3)
rule (1)
type (2)
Rule (2)
::= name "\n" indent type patterns dedent (3)
return Rule(name: name, type: type, patterns: patterns) (3)
```

Each rule is compiled to a to a Parser typealias of the type, and Parser read function.

``` swift
extension Parser {
public typealias RuleType = [String]
public func readRule() throws -> RuleType? {
```
### Patterns
Patterns describe a expected sequence for the rule and an evaluator to run when the pattern matches what is read from the file.

A pattern consists of:
1. "::="
2. Zero or more terms.
3. A evaluator that is ran when the pattern matches.

``` SParser
patterns
type
[Pattern]
::=(1) pattern(2) patterns(2)
return [pattern] + patterns (3)
::=(1) (2)
return [] (3)
pattern
type
Pattern
::=(1) "::="(2) cws(2) terms(2) "\n"(2) multiLineString(2)
return Pattern(terms: terms, evaluator: multiLineString) (3)
```

Each evaluator is compiled to an eval swift function.

``` swift
fileprivate func evalPatterns(pattern: Parser.PatternType, patterns: Parser.PatternsType) -> Parser.PatternsType {
return [pattern] + patterns
}

fileprivate func evalPatterns() -> Parser.PatternsType {
return []
}
```

### Terms
A Term describes a componet in a pattern. There are two types.
1. String matching terms

string matching terms are strings surounded by ", such as the "::=" term in the pattern rule.
2. Rule matching terms.
Rule matching terms use the name of a rule. This
``` SParser
::= name(1) "\n"(2) indent(2) type(2) patterns(2) dedent(2)
```
Each term calls it's read function calls:
1. Matches(string) for quoted terms
2. The generated by the .cparser file
3. Parser function named read<Type>().
```
public func readType() throws -> TypeType? {
if matches(string: "type\n") {
if let indent = try readIndent() {
if let line = try readLine() {
if let dedent = try readDedent() {
return try recursivelyRead(type: evalType(indent: indent, line: line, dedent: dedent))
}
try throwError(message:"error parsing type. expect dedent")
}
try throwError(message:"error parsing type. expect line")
}
try throwError(message:"error parsing type. expect indent")
}
return nil
}
```
## Include SParser in a package file
set as a dependency in the Package.swift file:
``` swift
let package = Package(
name: "MyProject",
dependencies: [
.Package(url: "https://github.com/amnykon/SParser.git", majorVersion: 0),
...
]
...
)
```

## Compile a .sparser file
Build Sparser

``` bash
swift build
```

Run SParser <filename>

This will create a .swift file in the same location.
``` bash
SParser Source/SParserPrivate/SParser.sparser
```

0 comments on commit 84d0d3c

Please sign in to comment.