Skip to content

Latest commit

 

History

History
164 lines (129 loc) · 4.18 KB

README.md

File metadata and controls

164 lines (129 loc) · 4.18 KB

SParser

SParser creates easy to use file or string parsers in swift code using a file format that is based on Backus–Naur form

To user Sparser:

  1. Create a .sparser file that describes the file format.
  2. Run SParser 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.

When compiled, Sparser.sparser generates SParser.sparser.swift

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.

imports
  Foundation
  SParserLibs
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.
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.

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.
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.

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

  ::= 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().
  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:

let package = Package(
    name: "MyProject",
    dependencies: [
        .Package(url: "https://github.com/amnykon/SParser.git", majorVersion: 0),
        ...
    ]
    ...
)

Compile a .sparser file

Build Sparser

swift build

Run SParser

This will create a .swift file in the same location.

   SParser Source/SParserPrivate/SParser.sparser