diff modules/json.tp @ 154:6e579a75a0a9

Add JSON parser and sample
author Mike Pavone <pavone@retrodev.com>
date Sat, 10 Aug 2013 11:51:47 -0700
parents
children fe816637fcc4
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/json.tp	Sat Aug 10 11:51:47 2013 -0700
@@ -0,0 +1,139 @@
+{
+	startArr <- "[" byte: 0
+	endArr <- "]" byte: 0
+	startObj <- "{" byte: 0
+	endObj <- "}" byte: 0
+	quote <- "\"" byte: 0
+	esc <- "\\" byte: 0
+	zero <- "0" byte: 0
+	nine <- "9" byte: 0
+	neg <- "-" byte: 0
+	space <- " " byte: 0
+	comma <- "," byte: 0
+	tab <- "\t" byte: 0
+	colon <- ":" byte: 0
+
+	parseNumAt <- :str :at :recvResult {
+		num <- 0
+		l <- str length
+		minus <- false
+		aft <- -1
+		while: { at < l } do: {
+			b <- str byte: at
+			if: b = neg {
+				minus <- true
+			} else: {
+				if: b >= zero && b <= nine {
+					num <- num * 10 + (str byte: at) - zero
+				} else: {
+					aft <- at
+					at <- l
+				}
+			}
+			at <- at + 1
+		}
+		if: aft < 0 {
+			aft <- at
+		}
+		if: minus {
+			num <- 0 - num
+		}
+		#{
+			value <- num
+			after <- aft
+		}
+	}
+
+	parseStrAt <- :src :at :recvResult {
+		//TODO: Deal with escaped characters
+		end <- src find: "\"" startingAt: at + 1 else: { src length }
+		#{
+			value <- src from: (at + 1) withLength: (end - at - 1)
+			after <- end + 1
+		}
+	}
+
+	_decode:at <- :text :cur {
+		ret <- false
+		b <- text byte: cur
+		if: b = neg || b >= zero && b <= nine {
+			text parseNumAt: cur
+		} else: {
+			if: b = quote {
+				text parseStrAt: cur
+			} else: {
+				if: b = startArr {
+					len <- text length
+					val <- #[]
+					cur <- cur + 1
+					aft <- -1
+					while: { cur < len } do: {
+						b <- text byte: cur
+						if: b = endArr {
+							aft <- cur + 1
+							cur <- len
+						} else: {
+							if: b = comma || b = space || b = tab {
+								cur <- cur + 1
+							} else: {
+								el <- _decode: text at: cur
+								cur <- el after
+								val append: (el value)
+							}
+						}
+					}
+					#{
+						value <- val
+						after <- aft
+					}
+				} else: {
+					if: b = startObj {
+						len <- text length
+						val <- dict linear
+						cur <- cur + 1
+						aft <- -1
+						expectKey <- true
+						key <- ""
+						while: { cur < len } do: {
+							b <- text byte: cur
+							if: b = comma || b = space || b = tab || b = colon {
+								cur <- cur + 1
+							} else: {
+								if: expectKey {
+									if: b = endObj {
+										aft <- cur + 1
+										cur <- len
+									} else: {
+										kd <- _decode: text at: cur
+										key <- kd value
+										cur <- kd after
+										expectKey <- false
+									}
+								} else: {
+									el <- _decode: text at: cur
+									val set: key (el value)
+									cur <- el after
+									expectKey <- true
+								}
+							}
+						}
+						#{
+							after <- aft
+							value <- val
+						}
+					} else: {
+						#{
+							value <- "foobar"
+							after <- (text length)
+						}
+					}
+				}
+			}
+		}
+	}
+	#{
+		decode <- :text {
+			(_decode: text at: 0) value
+		}
+	}
+}