Skip to content

Instantly share code, notes, and snippets.

@Xliff
Last active December 12, 2016 21:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xliff/840123313a6318b5fc42eb81394f3e70 to your computer and use it in GitHub Desktop.
Save Xliff/840123313a6318b5fc42eb81394f3e70 to your computer and use it in GitHub Desktop.

I have this thing I want to try, but it requires a bit of runtime smarts, since I don't know ahead of time what some of the inputs are. So I figured I would try to write a grammar capable of learning or...being dynamic.

However I've run into a bit of a snag.

Code:

use v6.c;

use Grammar::Tracer;

class UnitParser {
  has @.defUnits;
  has $.parser;

  grammar UnitParserGrammar {
    regex TOP { <num> [ '/' <den> ]? }

    regex num { ( <expr> \s* )+ }

    regex den { <expr> }

    token expr {
      <mag> <unit> [ '^' (\d+) ]?
    }

    token mag {
      T || G || M || k || h || da || d || c || m || u || µ || n || dn || p || f
    }

    proto token unit { * }

    token unit:sym<xxx> { <sym> }
  }

  submethod BUILD {
    $!parser = UnitParserGrammar.new;
  }

  method addUnit(Str $unit) {
    # @.defUnits.push: $unit;
    $.parser.HOW.^add_method("unit:sym<$unit>", token { <sym> });
    $.parser.HOW.^compose;
  }

  # method refresh {
  #   @!defUnits = Units.enum.keys, %formulas.keys;
  # }

  method parse($s) {
    #self.refresh;
    $.parser.parse($s);
    say $.parser.^methods».name;
  }
}

sub MAIN {
  my $up = UnitParser.new;
  $up.addUnit('ft');
  $up.addUnit('s');

  say $up.parse('ft/s');
  say $up.parse('Mft/ks');
}

Output:

$ perl6 scripts/testGrammar.pl6
===SORRY!===
Substring length (-5) cannot be negative

So what is rakudo telling me I'm doing wrong?

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment