Make the ParseContext trait more ergonomic #4

Closed
opened 2023-03-19 02:04:35 +00:00 by zyxw59 · 2 comments
zyxw59 commented 2023-03-19 02:04:35 +00:00 (Migrated from github.com)

Currently, implementing the ParseContext trait is somewhat awkward — the get_prefix and get_postfix functions have a lot of overlap, especially for delimiters, and it's easy to add a delimiter to one of them without remembering to add it to the other, or to add its matching delimiter, etc.

Maybe this just means providing a useful impl of ParseContext that can be constructed without these problems, or maybe it means redesigning the trait itself.

Currently, implementing the `ParseContext` trait is somewhat awkward — the `get_prefix` and `get_postfix` functions have a lot of overlap, especially for delimiters, and it's easy to add a delimiter to one of them without remembering to add it to the other, or to add its matching delimiter, etc. Maybe this just means providing a useful impl of `ParseContext` that can be constructed without these problems, or maybe it means redesigning the trait itself.
zyxw59 commented 2023-08-26 21:34:00 +00:00 (Migrated from github.com)

State transition table:

State Prefix operator Term Left delimiter Right delimiter End of input Binary operator Mixed operator Postfix operator
PostTerm Initial1 PostTerm2 Done3 PostOperator Initial PostOperator
Initial PostOperator PostTerm Initial PostTerm2 Done3
PostOperator PostOperator PostTerm Initial
  1. Fails if the left delimiter does not have an operator
  2. Fails if the right delimiter does not match the most recent left delimiter
  3. Fails if any delimiters remain on the stack

A "—" indicates that a token is not valid in that context

State transition table: State | Prefix operator | Term | Left delimiter | Right delimiter | End of input | Binary operator | Mixed operator | Postfix operator -|-|-|-|-|-|-|-|- **PostTerm** | — | — | Initial<sup>1</sup> | PostTerm<sup>2</sup> | Done<sup>3</sup> | PostOperator | Initial | PostOperator **Initial** | PostOperator | PostTerm | Initial | PostTerm<sup>2</sup> | Done<sup>3</sup> | — | — | — **PostOperator** | PostOperator | PostTerm | Initial | — | — | — | — | — 1. Fails if the left delimiter does not have an operator 2. Fails if the right delimiter does not match the most recent left delimiter 3. Fails if any delimiters remain on the stack A "—" indicates that a token is not valid in that context
zyxw59 commented 2023-08-26 21:51:56 +00:00 (Migrated from github.com)

It's tempting for a ParseContext to have a single lookup function, but that's not sufficient, since some tokens could have different meanings in different contexts — for example (in a prototypical arithmetic language):

  • - is a prefix operator in Initial and PostOperator states, but a binary operator in PostTerm state
  • e is a term in Initial and PostOperator states, but a binary operator in PostTerm state

Maybe the lookup function can return a type like

enum Element {
    Delimiter(Delimiter),
    Prefix(Prefix),
    Postfix(Postfix),
    Both(Prefix, Postfix),
}

For example:

  • - -> Element::Both(Prefix::Unary(..), Postfix::Binary(..))
  • e -> Element::Both(Prefix::Term(..), Postfix::Binary(..))
  • ! -> Element::Both(Prefix::Unary(..), Postfix::Postfix(..))
  • ( -> Element::Delimiter(Delimiter::Left(..))
  • * -> Element::Postfix(Postfix::Binary)
  • foobar -> Element::Prefix(Prefix::Term(..))
It's tempting for a `ParseContext` to have a single lookup function, but that's not sufficient, since some tokens could have different meanings in different contexts — for example (in a prototypical arithmetic language): - `-` is a prefix operator in `Initial` and `PostOperator` states, but a binary operator in `PostTerm` state - `e` is a term in `Initial` and `PostOperator` states, but a binary operator in `PostTerm` state Maybe the lookup function can return a type like ```rust enum Element { Delimiter(Delimiter), Prefix(Prefix), Postfix(Postfix), Both(Prefix, Postfix), } ``` For example: - `-` -> `Element::Both(Prefix::Unary(..), Postfix::Binary(..))` - `e` -> `Element::Both(Prefix::Term(..), Postfix::Binary(..))` - `!` -> `Element::Both(Prefix::Unary(..), Postfix::Postfix(..))` - `(` -> `Element::Delimiter(Delimiter::Left(..))` - `*` -> `Element::Postfix(Postfix::Binary)` - `foobar` -> `Element::Prefix(Prefix::Term(..))`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
mle/selkirk#4
No description provided.