R implementation of the common parsing tools 'lex' and 'yacc'.
RLY is a 100% R implementation of the common parsing tools lex and yacc. This project is a R clone of Ply.
RLY consists of two files : lex.R and yacc.R.
library(rly)
The examples directory contains several different examples.
A simple example is found at the end of this document
The GitHub page for RLY can be found at:
https://github.com/systemincloud/rly
Here is a simple example showing a RLY implementation of a calculator with variables.
library(rly) TOKENS = c('NAME', 'NUMBER')LITERALS = c('=','+','-','*','/', '(',')') Lexer <- R6Class("Lexer", public = list( tokens = TOKENS, literals = LITERALS, t_NAME = '[a-zA-Z_][a-zA-Z0-9_]*', t_NUMBER = function(re='\\d+', t) { t$value <- strtoi(t$value) return(t) }, t_ignore = " \t", t_newline = function(re='\\n+', t) { t$lexer$lineno <- t$lexer$lineno + nchar(t$value) return(NULL) }, t_error = function(t) { cat(sprintf("Illegal character '%s'", t$value[1])) t$lexer$skip(1) return(t) } )) Parser <- R6Class("Parser", public = list( tokens = TOKENS, literals = LITERALS, precedence = list(c('left','+','-'), c('left','*','/'), c('right','UMINUS')), # dictionary of names names = new.env(hash=TRUE), p_statement_assign = function(doc='statement : NAME "=" expression', p) { self$names[[as.character(p$get(2))]] <- p$get(4) }, p_statement_expr = function(doc='statement : expression', p) { cat(p$get(2)) cat('\n') }, p_expression_binop = function(doc="expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression", p) { if(p$get(3) == '+') p$set(1, p$get(2) + p$get(4)) else if(p$get(3) == '-') p$set(1, p$get(2) - p$get(4)) else if(p$get(3) == '*') p$set(1, p$get(2) * p$get(4)) else if(p$get(3) == '/') p$set(1, p$get(2) / p$get(4)) }, p_expression_uminus = function(doc="expression : '-' expression %prec UMINUS", p) { p$set(1, -p$get(3)) }, p_expression_group = function(doc="expression : '(' expression ')'", p) { p$set(1, p$get(3)) }, p_expression_number = function(doc='expression : NUMBER', p) { p$set(1, p$get(2)) }, p_expression_name = function(doc='expression : NAME', 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) while(TRUE) { cat('calc > ') s = readLines(file("stdin"), n=1) if(s == 'exit') break parser$parse(s, lexer)}
Fix: Error: object 'rprec_rlevel' not found.
Fix: could not find function "appender.console".
Refactor demos.
Declare Depends: R (>= 3.3.0) in DESCRIPTION file.
Error when no literals defined at all.
YaccProduction : Function get don't accept negative arguments.
YaccProduction : add length function to the class (ex. p$length() ).
Implement tracking. YaccProduction new methods: p$linespan(n) and p$lexspan(n).
Implement error recovery.
Use CRAN template of MIT license.
Add author of PLY python library as one of the authors of this extension.
Add BSD license of PLY to file inst/COPYRIGHTS.