kach / nearley

πŸ“œπŸ”œπŸŒ² Simple, fast, powerful parser toolkit for JavaScript.
https://nearley.js.org
MIT License
3.57k stars 231 forks source link

Change the postprocess data parameter type on the NearleyRule interface #637

Open misdocumeno opened 1 year ago

misdocumeno commented 1 year ago

the interface currently looks like this

interface NearleyRule {
    name: string
    symbols: NearleySymbol[]
    postprocess?: (d: any[], loc?: number, reject?: {}) => any
}

I suggest this small change

interface NearleyRule {
    name: string
    symbols: NearleySymbol[]
    postprocess?: (d: any, loc?: number, reject?: {}) => any
}

from d: any[] to d: any, so you can use a tuple to define the type of the parameter, which makes much more sense, instead of an array, since production rules match a specific sequence of tokens, in a particular order, for example, with a grammar like this:

ReturnStatement -> %RETURN Expression %SEMICOLON {% returnStatement %}

and a postprocessor like this:

interface ReturnStatement {
  type: 'ReturnStatement'
  expression: Expression
}

function returnStatement(data: [ReturnToken, Expression, Semicolon]): ReturnStatement {
  return {
    type: 'ReturnStatement',
    expression: data[1], // no errors
  }
}

that tuple is not assignable to any[], since the any[] array could be any length, less than 3, but that will never happen. for it to be assignable to any[], the postprocessor should look like this:

function returnStatement(data: (ReturnToken | Expression | Semicolon)[]): ReturnStatement {
  return {
    type: 'ReturnStatement',
    expression: data[1], // error, data[1] could be any of those 3 types
  }
}

which adds the need for runtime type checking with type predicates or something.

this change wouldn't cause any compilation error on existing grammars because any[] is assignable to any, so any code assuming d is an array, will still work!