R语言的类Lex和YACC工具是什么?

4
有没有适用于R的解析工具?对于我的情况,它不必是与lex/yacc兼容的工具。(我是一个R新手)
编辑:我想使用R实现另一种语言。

https://dev59.com/ym025IYBdhLWcg3w9qqQ - NickD
1
这是关于定义R语法的语法。我认为海报想要在R中为其他语言编写解析器。 - Spacedman
没错!如果我要使用R实现另一个解释器,是否存在解析工具? - adamo
1
这个帖子似乎表明R语言中没有这样的东西。 - Bart Kiers
我在 CRAN 的软件包列表中快速搜索了“parse”,大多数代码都是用于解析特定文件格式的,没有通用的解析代码。它还匹配了“sparse” :) - Spacedman
请查看dparser软件包。 - G. Grothendieck
4个回答

9

我开发了一个名为rly的Python PLY克隆版。您可以在CRAN上找到它:

install.packages("rly")

以下是使用示例:

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,
    # Parsing rules
    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)
}

2
据我所知,R 没有解析器生成器。
然而,用户可以用 Java、C 或 Fortran(当然还有 R)编写R 中的软件包(也称为“扩展程序”)。因此,您可以使用Lex/YaccBison(针对 C),或JavaCCANTLR(针对 Java)创建您语言的词法分析器和语法分析器,并在您的 R 代码中使用它们。

1

-1
据我所知,R源代码中确实有YACC语法文件。请查看这些文件。

R-2.15.2\src\main\gram.y R-2.15.2\src\main\gramLatex.y R-2.15.2\src\main\gramRd.y

但我不确定这些文件是否在官方发布版中构建......


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接