bablr-lang / bablr-vm

A VM for enforcing language rules on agAST trees
MIT License
40 stars 2 forks source link

parse() #27

Closed conartist6 closed 10 months ago

conartist6 commented 1 year ago

I expect many of the innovations I've made so far to be applicable to the parsing process. In a world with perfect support for gaps and fragments the process of parsing a program is no different than the process of building the same program up as the programmer types it.

Take the simple program 2 + 5 and let's see how we would parse it:

// First we parse the `2`
$node = { type: 'Number', value: 2 }`
// Then parse the `+` into an incomplete binary expression
$node = { type: 'BinaryExpression', left: $node, right: gap }
// To continue we move to the gap on the right
stack.push($node);
$node = $node.right; // gap
// Finally we parse the 5
$node.replaceWith({ type: 'Number', value: 5 })
// Exit BinaryExpression.right
$node = stack.pop();
// Exit the now-complete BinaryExpression
$node = stack.pop();
// Nothing more to do

Now of course some big caveats: I'm skipping over all the hard parts of parsing anything. We will need this process to branch so that we can test multiple possible nodes types to resolve ambiguity.

conartist6 commented 1 year ago

That means I'll need to abstract away the differences between creating a new node and capturing values into its properties vs referencing an existing node and validating the values in its properties

conartist6 commented 1 year ago

It's coming -- it's all happening. It turned out to be another complete rewrite more or less, but that is drawing to a close.

conartist6 commented 1 year ago

The rewrite is merged into master and grammar productions are now essentially implemented as mini parsers. This took a whole lot of work, but it should now be relatively easy to implement parse as an algorithm separate from traverse.

conartist6 commented 1 year ago

The design for this is to add a pushNode command to the parse protocol. Pushing a node will demand that the next production consume the pushed node before progressing in the source. Consuming the pushed node will pop it and allow progress in the source to proceed. The effect of this is to ensure that only left-associative productions may match.

conartist6 commented 1 year ago

props.precedence can be used to allow an expression to match only a subset of its overall productions

conartist6 commented 10 months ago

Parsing works and has a public API, though precedence and shift() are not reimplemented yet. They will be!