changeset 154:6e579a75a0a9

Add JSON parser and sample
author Mike Pavone <pavone@retrodev.com>
date Sat, 10 Aug 2013 11:51:47 -0700
parents 075b1e71feff
children 9de2572a34a7
files modules/json.tp modules/string.tp samples/json.tp
diffstat 3 files changed, 160 insertions(+), 3 deletions(-) [+]
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
+		}
+	}
+}
--- a/modules/string.tp	Fri Aug 09 21:01:11 2013 -0700
+++ b/modules/string.tp	Sat Aug 10 11:51:47 2013 -0700
@@ -94,16 +94,17 @@
 		intret
 	}
 
-	llMessage: find:else withVars: {
+	llMessage: find:startingAt:else withVars: {
 		intret <- obj_int32 ptr
 		oneedle <- object ptr
+		startpos <- obj_int32 ptr
 		ifNotFound <- object ptr
 		sneedle <- string ptr
 		i <- uint32_t
 		notFound <- uint32_t
-	} andCode: :oneedle :ifNotFound {
+	} andCode: :oneedle :startpos :ifNotFound {
 		sneedle <- mcall: string 1 oneedle
-		i <- 0
+		i <- startpos num
 		notFound <- 1
 		while: { notFound && i + (sneedle bytes) <= bytes} do: {
 			if: (memcmp: data + i (sneedle data) (sneedle bytes)) = 0 {
@@ -121,6 +122,10 @@
 		}
 	}
 
+	find:else <- :toFind :orElse {
+		find: toFind startingAt: 0 else: orElse
+	}
+
 	llMessage: from:withLength withVars: {
 		from <- obj_int32 ptr
 		tocopy <- obj_int32 ptr
@@ -183,4 +188,5 @@
 	}
 
 	isInteger? <- { false }
+	isString? <- { true }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/json.tp	Sat Aug 10 11:51:47 2013 -0700
@@ -0,0 +1,12 @@
+#{
+	main <- {
+		arr <- json decode: "[\"foo\",  \"bar\", 13245, \"baz\"   ]"
+		foreach: arr :idx val {
+			print: (string: idx) . ": " . (string: val) . "\n"
+		}
+		obj <- json decode: "{\"foo\":    \"bar\",  \"baz\": \"qux\", \"meaningOfLife\": 42   }"
+		foreach: obj :idx val {
+			print: (string: idx) . ": " . (string: val) . "\n"
+		}
+	}
+}