R: add step4_if_fn_do and step5_tco.
[jackhill/mal.git] / r / reader.r
CommitLineData
4d1456b9
JM
1..reader.. <- TRUE
2
3if(!exists("..types..")) source("types.r")
4
5new.Reader <- function(tokens) {
6 e <- structure(new.env(), class="Reader")
7 e$tokens <- tokens
8 e$position <- 1
9 e
10}
11
12Reader.peek <- function(rdr) {
13 if (rdr$position > length(rdr$tokens)) return(NULL)
14 rdr$tokens[[rdr$position]]
15}
16
17Reader.next <- function(rdr) {
18 if (rdr$position > length(rdr$tokens)) return(NULL)
19 rdr$position <- rdr$position + 1
20 rdr$tokens[[rdr$position-1]]
21}
22
23tokenize <- function(str) {
24 re <- "[\\s,]*(~@|[\\[\\]\\{\\}\\(\\)'`~^@]|\"(?:\\\\.|[^\\\\\"])*\"|;.*|[^\\s\\[\\]\\{\\}\\('\"`,;\\)]*)"
25 m <- lapply(regmatches(str, gregexpr(re, str, perl=TRUE)),
26 function(e) sub("^[\\s,]+", "", e, perl=TRUE))
27 res <- list()
28 i <- 1
29 for(v in m[[1]]) {
30 if (v == "") next
31 res[[i]] <- v
32 i <- i+1
33 }
34 res
35}
36
37re_match <- function(re, str) { length(grep(re, c(str))) > 0 }
38
39read_atom <- function(rdr) {
40 token <- Reader.next(rdr)
41 if (re_match("^-?[0-9][0-9.]*$", token)) {
42 as.numeric(token)
43 } else if (substr(token,1,1) == "\"") {
01feedfe
JM
44 gsub("\\\\n", "\\n",
45 gsub("\\\\\"", "\"",
46 substr(token, 2, nchar(token)-1)))
4d1456b9 47 } else if (token == "nil") {
01feedfe 48 nil
4d1456b9
JM
49 } else if (token == "true") {
50 TRUE
51 } else if (token == "false") {
52 FALSE
53 } else {
54 as.symbol(token)
55 }
56}
57
58read_seq <- function(rdr, start="(", end=")") {
59 lst <- list()
60 token <- Reader.next(rdr)
61 if (token != start) {
62 throw(concat("expected '", start, "'"))
63 }
64 repeat {
65 token <- Reader.peek(rdr)
66 if (is.null(token)) {
67 throw(concat("expected '", end, "', got EOF"))
68 }
69 if (token == end) break
70 lst[[length(lst)+1]] <- read_form(rdr)
71 }
72 Reader.next(rdr)
73 new.listl(lst)
74}
75
76read_form <- function(rdr) {
77 token <- Reader.peek(rdr)
78 if (token == ")") {
79 throw("unexpected ')'")
80 } else if (token == "(") {
81 new.listl(read_seq(rdr))
82 } else if (token == "]") {
83 throw("unexpected ']'")
84 } else if (token == "[") {
85 new.vectorl(read_seq(rdr, "[", "]"))
86 } else {
87 read_atom(rdr)
88 }
89}
90
91read_str <- function(str) {
92 tokens <- tokenize(str)
01feedfe 93 if (length(tokens) == 0) return(nil)
4d1456b9
JM
94 return(read_form(new.Reader(tokens)))
95}
96
97#cat("---\n")
98#print(tokenize("123"))
99#cat("---\n")
100#print(tokenize(" ( 123 456 abc \"def\" ) "))
101
102#rdr <- new.reader(tokenize(" ( 123 456 abc \"def\" ) "))
103#Reader.peek(rdr)
104#Reader.next(rdr)
105#Reader.next(rdr)
106#Reader.next(rdr)
107#Reader.next(rdr)
108#Reader.next(rdr)
109#Reader.next(rdr)
110#Reader.next(rdr)