Parsing and evaluating typed expressions (BNF-like grammar for earley / Nearley.js)

43 Views Asked by At

I'm playing with nearley.js and moo at the Nearley Parser Playground to learn about parsing.

I understand the calculator example but can't wrap my head around the recursion when trying to write grammar in support of multiple types and operations that affect type (i.e. multiplication of two lengths results in area).

Neither can ChatGPT, which needs some manual correction to get working syntax, e.g.:

@{%
const moo = require('moo');
const lexer = moo.compile({
  number: /[0-9]+(?:\.[0-9]+)?/,
  lengthUnit: /m/,
  areaUnit: /m²/,
  plus: /\+/,
  times: /\*/,
  lparen: /\(/,
  rparen: /\)/,
  whitespace: { match: /\s+/, lineBreaks: true },
});
%}

@lexer lexer

expression -> 
    addition {% d => d[0] %}

addition -> 
      addition %plus multiplication {% d => d[0] + d[2] %}
    | multiplication {% d => d[0] %}

multiplication ->
      multiplication %times atom {% d => d[0] * d[2] %}
    | atom {% d => d[0] %}

atom -> 
       %number %lengthUnit {% d => d[0] %}
     | %number %areaUnit {% d => d[0] %}
     | %lparen addition %rparen {% d => d[1] %}
     | %number {% d => d[0] %}

fails on (2m*2m)+2*2m². And it seems this would allow multiplication of lengthUnit and areaUnit.

Generally speaking, I suspect the type needs to be handled in the corresponding processing function or can the grammar be written such that it only "matches" the allowed (resulting) types?

0

There are 0 best solutions below