OMeta/Squeak 2

This is the current version of OMeta/Squeak. It is available as a Monticello package from the OMeta Squeaksource project page.

Getting Started

A good place to start is the OMeta2Examples class. Look at the class comment — it contains a few examples that illustrate, among other things, the new public interface of the OMeta/Squeak grammars.

Syntax and New Features

OMeta/Squeak 2 has all of the features of the original OMeta/Squeak and then some, but its syntax is closer to that of OMeta/JS. As a result, porting old OMeta/Squeak grammars to the new version will take a little bit of editing. I believe the new, more light-weight syntax is well worth the trouble.

Rule Applications

... are now written without the pointy brackets (<>), e.g., expr. Arguments should be passed using parentheses, e.g., listOf(#expr. ','). Note that (i) the arguments are separated by periods, not commas (because comma is a valid message name is Smalltalk), and (ii) there should be no spaces between the rule name and the open parenthesis.

Super rule applications are now written using the caret symbol (^), e.g., ^digit invokes the super-grammar's version of the digit rule. You can also pass arguments to a super rule application, e.g., ^rrr(a1. a2).

Rule declarations

The new syntax for rule declarations uses = instead of ::=, e.g.,

     identifier = letter (letter | digit)*

Semantic Actions and Predicates

In the previous version of OMeta/Squeak, the syntax for semantic actions was

     ![...squeak expr...]

and

     => [...squeak expr...]

The new syntax for semantic actions is

     [...squeak expr..]

(note that there's no "!") and

     -> [...squeak expr...]

The syntax for semantic predicates has not changed:

     ?[...squeak expr...]

New Feature: "Consumed-By" Operators

The new consumed-by operator (<...>), inspired by a similar feature in Ian's COLA parser framework, returns a sub-sequence of the input that contains the elements matched by the enclosed OMeta/Squeak expression. This can be really convenient — for example, instead of writing

     letter:x (letter | digit)*:xs -> [String withAll: (xs addFirst: x; yourself)]

you can now write

     <letter (letter | digit)*>

And since result is always a SequenceableCollection of the same species as the one underlying the input stream, this works equally well for Strings, Arrays, OrderedCollections, etc.

There is also a new index-consumed-by operator (@<...>) that returns an association with the start and end indices of the elements consumed by the enclosed expression (i.e., startIdx -> endIdx).

Other Changes / New Features?

I believe this covers all the changes and new features; please let me know if you notice that I've missed something.

Known Issues

  • This implementation uses Squeak's array literals ({...}), so it won't work on other flavors of Smalltalk. I'll fix this over the next few days.
  • The Squeak debugger complains about OMeta rules — syntax error — because it doesn't know about OMeta syntax. I have a plan to fix this, but it's part of a bigger project (the OmniDebugger) which will take some time to implement. Please let me know if you know of any quick fixes.