systemincloud / rly

Other
37 stars 5 forks source link

Error with Environment? #11

Open billdenney opened 5 years ago

billdenney commented 5 years ago

When running the code below, I get an error about trying to index into an environment. I think that a safety check is needed in the p$callable() function, but I'm not sure what.

library(rly)

TOKENS <- c("MONTH", "WEEK", "DAY", "HOUR", "MINUTE", "SECOND",
            "INTEGER", "PREPOST")
LITERALS <- c(".", "-")

Lexer <- R6::R6Class(
  "Lexer",
  public=list(
    tokens=TOKENS,
    literals=LITERALS,
    t_MONTH="(?:mon(?:th)?|MON(?:TH)?)",
    t_WEEK="(?:W(?:EE)?K|w(?:ee)?k)",
    t_DAY="(?:D(?:A)?Y|d(?:a)?y)",
    t_HOUR="(?:H(?:(?:OU)?R)?|h(?:(?:ou)?r)?)",
    t_MINUTE="(?:M(?:IN(?:UTE)?)?|m(?:in(?:ute)?)?)",
    t_SECOND="(?:S(?:EC(?:OND)?)?|s(?:ec(?:ond)?)?)",
    t_INTEGER="[0-9]+",

    t_ignore=" \t",
    t_error=function(t) {
      cat(sprintf("Illegal character '%s'", t$value[1]))
      t$lexer$skip(1)
      return(t)
    }
  )
)

Parser <- R6::R6Class(
  "Parser",
  public = list(
    tokens = TOKENS,
    literals = LITERALS,
    # Parsing rules
    precedence = list(),
    # dictionary of names
    names = new.env(hash=TRUE),
    p_valueunit_prepost=function(doc="valueunit : valueunit PREPOST", p) {
      p$set(1, self$names[[as.character(p$get(2))]])
    },
    p_valueunit_base=function(doc="valueunit : value timeunit
                                        | timeunit value", p) {
      p$set(1, self$names[[as.character(p$get(2))]])
    },
    p_value_negative=function(doc="value : '-' value", p) {
      p$set(1, self$names[[as.character(p$get(2))]])
    },
    p_value_float=function(doc="value : INTEGER '.' INTEGER", p) {
      p$set(1, self$names[[as.character(p$get(2))]])
    },
    p_value_integer=function(doc="value : INTEGER", p) {
      p$set(1, self$names[[as.character(p$get(2))]])
    },
    p_time_unit=function(doc="timeunit : MONTH
                                       | WEEK
                                       | DAY
                                       | HOUR
                                       | MINUTE
                                       | SECOND", p) {
      p$set(1, self$names[[as.character(p$get(2))]])
    },
    p_error = function(p) {
      if(is.null(p)) cat("Syntax error at EOF")
      else           cat(sprintf("Syntax error at '%s'", p$value))
    }
  )
)

lexer  <- rly::lex(Lexer)
parser <- rly::yacc(Parser)

parser$parse("15min", lexer)
#> Error in value[[3L]](cond): wrong arguments for subsetting an environment

Created on 2018-12-08 by the reprex package (v0.2.0).

marekjagielski commented 5 years ago

Can you investigate it a little more? I will not be able to check this issue for couple of days.

billdenney commented 5 years ago

My immediate fix was to use a regexp. I don't think I understand the p$set function sufficiently.

Could you perhaps add documentation of the functions in the parser and lexer objects (like p$set())? I think that would help me with my issue.

marekjagielski commented 5 years ago

Can you check your example with https://github.com/dabeaz/ply ? rly is more or less a one to one clone of python ply.