Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expressions are evaluated right to left instead of left to right. #2

Open
HeardACat opened this issue Dec 8, 2014 · 2 comments
Open

Comments

@HeardACat
Copy link
Owner

See example.r

@HeardACat HeardACat added the bug label Dec 8, 2014
@HeardACat
Copy link
Owner Author

HeardACat commented Oct 28, 2016

To solve this we need to implement an alternative version to alt which does sequencing of recognizers (see wiki: https://en.wikipedia.org/wiki/Parser_combinator)

The sequencing of recognizers is done with the ⊛ parser combinator. Like ⊕, it is used as an infix operator between p and q. But it applies the first recognizer p to the input position j, and if there is any successful result of this application, then the second recognizer q is applied to every element of the result set returned by the first recognizer. ⊛ ultimately returns the union of these applications of q.

Instead what we're after is this one:

The ‘alternative’ parser combinator, ⊕, applies both of the recognizers on the same input position j and sums up the results returned by both of the recognizers, which is eventually returned as the final result. It is used as an infix operator between p and q as follows:

@HeardACat HeardACat added enhancement and removed bug labels Dec 26, 2016
@pkri0
Copy link

pkri0 commented Apr 22, 2024

This can be done using chainl1. To implement that, a monadic bind would be nice. Like this:

library(Ramble)

bind <- function(p,f) {
  function(string) {
    result <- p(string)
    if (length(result) == 0) {
      list()
    }
    else {
      (f(result$result))(result$leftover)
    }
  }
}

`%bind%` <- bind

chainl1 <- function(p, op) {
  rest <- \(x) (op %bind% \(f) p %bind% \(y) rest(f(x,y))) %alt% succeed(x)
  p %bind% rest
}

skip <- function(p) {
  p %using% \(x) list()
}

between <- function(open, p, close) {
  skip(open) %then% p %then% skip(close)
}

sumop <- (literal('+') %using% \(s) \(x,y) x+y) %alt%
  (literal('-') %using% \(s) \(x,y) x-y)
mulop <- (literal('*') %using% \(s) \(x,y) x*y) %alt%
  (literal('/') %using% \(s) \(x,y) x/y)
expr <- chainl1(term, sumop)
term <- chainl1(factor, mulop)
factor <- between(literal('('), expr, literal(')')) %alt%
  natural() %using% as.numeric

expr("4-2+3") # order is done correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants