-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.R
89 lines (85 loc) · 3.25 KB
/
parser.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# parser.R
# Define a parser for the REDCap equation syntax.
#
# Copyright (c) 2021, Michael Pascale.
library(R6)
library(rly)
source('functions.R')
parser <- rly::yacc(R6Class("Parser",
public = list(
tokens = TOKENS,
literals = LITERALS,
# Parsing rules
precedence = list(c('left','+','-'),
c('left','*','/'),
c('right','UMINUS')),
p_statement_expr = function(doc='statement : expression', p) {
cat(p$get(2))
cat('\n')
},
# Binary arithmetic operations.
p_expression_binop = function(doc="expression : expression '+' expression
| expression '-' expression
| expression '*' expression
| expression '/' expression
| expression '^' expression
| expression '%' expression
| expression '=' expression
| expression '<' expression
| expression '>' expression
| expression LTEQ expression
| expression GTEQ expression
| expression NEQ expression", p) {
p$set(1, switch(p$get(3),
'+'=p$get(2) + p$get(4),
'-'=p$get(2) - p$get(4),
'*'=p$get(2) * p$get(4),
'/'=p$get(2) / p$get(4),
'^'=p$get(2) ^ p$get(4),
'%'=p$get(2) %% p$get(4),
'='=ifelse(p$get(2) == p$get(4), 1, 0),
'<'=ifelse(p$get(2) < p$get(4), 1, 0),
'>'=ifelse(p$get(2) > p$get(4), 1, 0),
'<='=ifelse(p$get(2) <= p$get(4), 1, 0),
'>='=ifelse(p$get(2) >= p$get(4), 1, 0),
'<>'=ifelse(p$get(2) != p$get(4), 1, 0)
))
},
p_function_call = function(doc="function_call : FUNCTION '(' exprlist ')'", p) {
cat(sprintf('function called: %s\n', p$get(4)))
p$set(1, do.call(paste0('rc_', p$get(2)), as.list(p$get(4))))
},
p_expr_list = function(doc="exprlist : exprlist ',' expression
| expression", p) {
if (p$length() > 2) {
p$set(1, c(p$get(2), p$get(4)))
} else {
p$set(1, c(p$get(2)))
}
},
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_string = function(doc="expression : STRING", p) {
p$set(1, p$get(2))
},
p_expression_call = function(doc="expression : function_call", p) {
p$set(1, p$get(2))
},
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, RECORDS[[as.character(p$get(3))]])
},
p_error = function(p) {
if(is.null(p))
cat("Syntax error at EOF.\n")
else
cat(sprintf("Syntax error at: %s.\n", p$value))
}
)
))