Skip to content
This repository has been archived by the owner on Oct 28, 2023. It is now read-only.

Parsing DSL

Christophe VG edited this page Mar 6, 2017 · 1 revision

During the development of v1.1 a Fluid Parsing API, eliminating explicit try { ... } catch { ... }-blocks was introduced to make the generated parsers more "human readable":

An example of a v1.0 generated parser:

public Program ParseProgram() {
  Identifier identifier = null;
  List<Assignment> assignments = new List<Assignment>();
  this.Log("ParseProgram");
  int pos = this.source.position;
  try {
    this.source.Consume("PROGRAM");
    identifier = this.ParseIdentifier();
    this.source.Consume("BEGIN");
    {
      Assignment temp;
      while(true) {
        try {
          temp = this.ParseAssignment();
        } catch(ParseException) {
          break;
        }
        assignments.Add(temp);
      }
    }
    this.source.Consume("END.");
  } catch(ParseException e) {
    this.source.position = pos;
    throw this.source.GenerateParseException(
      "Failed to parse Program.", e
    );
  }
  return new Program() {
    Identifier  = identifier,
    Assignments = assignments
  };
}

In v1.1 this was implemented as such:

// program ::= "PROGRAM" identifier "BEGIN" { assignment } "END." ;
public Program ParseProgram() {
  Program program = new Program();
  this.Log( "ParseProgram" );
  Parse( () => {
    Consume("PROGRAM");
    program.Identifier = ParseIdentifier();
    Consume("BEGIN");
    program.Assignments = Many<Assignment>(ParseAssignment);
    Consume("END.");
  }).OrThrow("Failed to parse Program");
  return program;
}

Although it violates some of my personal code style rules, in this case the inner-DSL is dominant and requires as little as possible normal C# code ;-) The first results of this change are nice. I'm continuing to investigate possibilities down this road.

Clone this wiki locally