It's time for my weekly post to this old thread.  The grammar has
grown enough to deserve more than one file, and is starting to change
in new directions.  For example, it's now Turing-complete, if you have
a Parrot engine and a bit of spare time.  Call it a primitive "demo
version" of some of Perl 6's features.  If nothing else, it will let
you start training your fingers to 'concatenate' _$like _$this.

What's currently "supported":

- most binary operators
- arithmetic hyper-operators
- chained comparisons
- the ternary operator (both r- and l-value)
- if/elsif/else (even "unless" and the feared "elsunless";)
- void subroutines with declared parameter lists (only)
- local variables (only -- i.e. "use UberStrict").
- arrays and scalars (only -- no hashes, closures, references)

The fact that I've been able to whip this up in a couple thousand
lines of code is a remarkable testament to Parrot's maturity, and to
the wealth of tools available in Perl 5.  In particular, without The
Damian's Parse::RecDescent, Melvin Smith's IMCC, and Sarathy's
Data::Dumper, it never would have been possible.

Grammar fixes:

- Fixed a bug with parameter initializers: "sub f($x = 23, $y)" now
  parses as "f(($x = 23), ($y))", not "f($x = (23, $y))"

- Fixed a number of bugs sent in by Jonh Kingsley:

  - "sub f($a; $b, *@c)" (i.e. a sub with both optional and slurping
    parameters) now parses.

  - low-precedence 'and', 'or', 'xor' are now allowed within
    suitably-parenthesized expressions, such as "if (1 and 2)".
    Interestingly, you can now put a multi-dimensional array as the
    test of an "if".  This is probably a feature that will go away at
    some point in the future.

  - "if (a && b)" is parsed correctly, not as "if (a & (&b))"

  - "f(2,3),4" reverts to "(f(2,3)),4" rather than "f((2,3),4)"
    through a bit of chicanery that allows "if" and other control
    structures to take parens around their first arguments.

  - "%a{somefunction($withargs)}" is legal.  It used to see
    'somefunction' and treat it as a bare hash key, then freak out
    about the open paren.

  - "last if $foo" and related cases where a guard was parsed as a
    label name.

  - empty programs and blocks

  - "stmt until expr"

Changes:

- Kingsley's changes:

  - handles comments

  - foreach decl(?) '(' expr ')' block

- statement guards (e.g. "do_something() unless $foo") cannot be used
  with functions taking a closure as their last argument (e.g. "for",
  "elsunless").  This avoids a nasty ambiguity with things like this:

    if 1 { A }
    if foo { B }

        ==> guarded_stmt("if(1, {A})", if, "foo({B})")
or      ==> stmts("if(1, {A})", "if(foo(), {B})")

- significant reorganization and tidying of files.  The grammar now
  lives in its own module, and doesn't stomp on main's namespace with
  wild abandon.  It's not a simple one-file install anymore, but it's
  getting big enough to maybe justify jumping through more hoops.

- "Human-readable" output is gone, as it was more trouble than it was
  worth to maintain.  The default now is to output the parse tree
  through Data::Dumper (there may be other tools to inspect Perl data
  structures in a more legible format).

Next to do:

- Function return values.

- More informative error messages.  They're currently... cryptic.

- Having no built-in functions is kind of frustrating.  Adding a few
  more things would be nice.

- sub declarations.  A standard function for turning a prototype into
  an argument context rule is needed eventually, and would eliminate
  the current nasty builtin hack in the compiler and parser.

- rip out

- Globals.

- Handling of "closures" for if-blocks is completely bogus now --
  they're always inlined, as there are no nested scopes.  Once these
  are in, the current closure-handling will go away.

(If you've read this far, I'm impressed.  It took me several tries to get
here myself)

/s

Attachment: grammar.tgz
Description: Binary data

Reply via email to