summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Vertes <mvertes@free.fr>2025-07-22 23:20:13 +0200
committerMarc Vertes <mvertes@free.fr>2025-07-22 23:20:13 +0200
commitb5d5888c59160f5ab30aaaf0288b6ad6d0a81bdd (patch)
tree5963e9bcfe4943c1bfd4f4923f9d35e06763acf6
parent1f563060887b979e0138567fb13bef97dc8fd915 (diff)
add other experiments jp and ev
-rw-r--r--ev9
-rwxr-xr-xjp218
-rwxr-xr-xmp7
-rwxr-xr-xtests3
4 files changed, 234 insertions, 3 deletions
diff --git a/ev b/ev
new file mode 100644
index 0000000..b5f178c
--- /dev/null
+++ b/ev
@@ -0,0 +1,9 @@
+#!/usr/bin/env awk -f
+
+# an evaluator of code
+
+BEGIN {
+}
+
+eval(mem, src) {
+}
diff --git a/jp b/jp
new file mode 100755
index 0000000..28cd767
--- /dev/null
+++ b/jp
@@ -0,0 +1,218 @@
+#!/usr/bin/env awk -f
+
+BEGIN {
+ version = "0.1"
+
+ help[""] = "Commands:\n" \
+ " help [cmd] prints cmd help or this help text\n"
+
+ help["help"] = "help [cmd]\n" \
+ " Prints cmd help or general help text.\n" \
+ " Example: help help\n"
+
+ lnum = cnum = 0
+ if (str) {
+ lnum = 1
+ line = ARGV[1]
+ if (err = parse(v, "", line)) print "parse err: " err
+ for (k in v) print k " " v[k]
+ print "---"
+ print format(v, "", 0)
+ exit ERROR != 0
+ } else file = ARGV[1]
+ delete ARGV[1]
+ if (file) parse(v)
+ if (!notty) printf "%s\njp> ", "jp version " version ". Type \"help\" for help."
+}
+{
+ ERROR = ""
+ if ($1 == "help") {
+ printf "%s", help[$2]
+ } else if ($1 == "format") {
+ if ($2 == "\"\"") $2 = ""
+ print format(v, key(v, $2), !raw)
+ } else if ($1 == "key") {
+ print key(v, $2)
+ } else if ($1 == "filter") {
+ filter(v, "", $2)
+ } else if ($1 == "dump") {
+ if ($2 ~ /^\|/) {
+ cmd = substr($0, 1+index($0, "|"))
+ for (k in v) print k " " v[k] | cmd
+ close(cmd)
+ } else for (k in v) print k " " v[k]
+ } else if ($1 == "parse_string") {
+ delete v
+ sub(/^[[:space:]]+/, "")
+ $0 = substr($0, length($1)+2)
+ parse("", v, "", $0)
+ } else if ($1 == "parse") {
+ delete v
+ parse($2, v)
+ } else if (NF) {
+ error("invalid command: " $1)
+ }
+ if (ERROR) print ERROR > "/dev/stderr"
+ if (!notty) printf "%sjp> ", s
+}
+END { exit ERROR != "" }
+
+function error(s, n) { ERROR = s; print "#error: " s >"/dev/stderr"; return n }
+
+function debug(s) { print s > "/dev/stderr" }
+
+function scan( c) {
+ while (c = substr(line, 1, 1)) {
+ if (c == "\n") { lnum++; cnum = 0 }
+ else if (c ~ /[ \t]/) cnum++
+ else break
+ line = substr(line, 2)
+ }
+ if (file) {
+ while (line == "") {
+ if ((getline line < file) <= 0) return
+ lnum++; cnum = 0
+ if (match(line, /^[ \t]+/)) {
+ cnum += RLENGTH
+ line = substr(line, RLENGTH+1)
+ }
+ }
+ }
+ if (match(line, /^(null|true|false|[][}{,:])/)) {
+ tok = substr(line, 1, 1)
+ } else if (match(line, /^[.0-9Ee+-]+/)) {
+ tok = "d" substr(line, 1, RLENGTH)
+ } else if (match(line, /^"(\\.|[^\\"])*"/)) {
+ tok = "s" substr(line, 2, RLENGTH-2)
+ } else {
+ tok = "b" substr(line, 1, 1)
+ }
+ cnum += RLENGTH
+ line = substr(line, RLENGTH+1)
+}
+
+# parse gets the next object from source and return an error if any.
+function parse(values, key, id, ids, i, k, err) {
+ scan()
+ if (tok == "[") {
+ for (i = 0; tok != "]"; i++) {
+ if (i > 0 && tok != ",") return error("not a ',': ", tok)
+ if (err = parse(values, key SUBSEP i)) {
+ if (tok == "]" && i == 0) continue
+ return err
+ }
+ scan()
+ }
+ values[key] = "a" i
+ } else if (tok == "{") {
+ for (i = 0; tok != "}"; i++) {
+ if (i > 0 && tok != ",") return "i: " i ", not a ','"
+ scan()
+ if (i == 0 && tok == "}") break
+ if (tok !~ /^s/) return num ":" cnum ": not a string: " tok
+ k = substr(tok, 2)
+ ids = ids (i ? SUBSEP : "") substr(tok, 2)
+ scan()
+ if (tok != ":") return file ":" lnum ":" cnum -length(tok) ": not a ':'"
+ if (err = parse(values, key SUBSEP i)) return err
+ scan()
+ }
+ values[key] = "o" ids
+ } else if (tok ~ /^[ntfsd]/) {
+ values[key] = tok
+ } else return "unexpected tok: " tok
+}
+
+function format(values, key, indent, id, c, i, s, v, pre, post, sp) {
+ if (! (key in values)) return
+ if (indent) {
+ pre = space(indent * 2)
+ post = "\n"
+ sp = " "
+ }
+ if (id) id = "\"" id "\":" sp
+ v = values[key]
+ c = substr(v, 1, 1)
+ if (c == "n") return id "null"
+ if (c == "t") return id "true"
+ if (c == "f") return id "false"
+ if (c == "d") return id substr(v, 2)
+ if (c == "s") return id "\"" substr(v, 2) "\""
+ if (c == "a") {
+ s = "[" post
+ for (i = 0; ((key, i) in values); i++) {
+ if (i) s = s "," post
+ s = s pre format(values, key SUBSEP i, indent ? indent+1 : 0)
+ }
+ return id s post substr(pre, 3) "]"
+ }
+ if (c == "o") {
+ s = "{" post
+ v = substr(v, 2)
+ for (i = 0; ((key, i) in values); i++) {
+ if (i) s = s "," post
+ v = tail(v, SUBSEP)
+ s = s pre "\"" HEAD "\":" sp format(values, key SUBSEP i, indent ? indent+1 : 0)
+ }
+ return id s post substr(pre, 3) "}"
+ }
+}
+
+function space(n, i, s) {
+ for (i = 0; i < n; i++) s = s " "
+ return s
+}
+
+function tail(str, sep, i) {
+ if (i = index(str, sep)) {
+ HEAD = substr(str, 1, i-1)
+ return substr(str, i+1)
+ } else HEAD = str
+}
+
+function lindex(list, item, i, k) {
+ for (i = 0; list; i++) {
+ list = tail(list, SUBSEP)
+ if (HEAD == item) return i
+ }
+ return -1
+}
+
+# TODO: remove recursivity
+# TODO: handle spaces
+function key(values, pattern, k1, result, i, k, s, w) {
+ if (! (k1 in values)) return
+ gsub(/[.]/, SUBSEP, pattern)
+ pattern = tail(pattern, SUBSEP)
+ k = HEAD
+ if (k ~ /^[0-9]+$/) {
+ result = result SUBSEP k
+ } else {
+ s = substr(values[k1], 2)
+ if ((i = lindex(s, k)) >= 0) result = result SUBSEP i
+ }
+ if (pattern) return key(values, pattern, k1 SUBSEP i, result)
+ return result
+}
+
+function filter(values, key, sk, i, k, n, v) {
+ v = values[key]
+ if (v ~ /^o/) {
+ v = substr(v, 2)
+ for (i = 0; ((key, i) in values); i++) {
+ v = tail(v, SUBSEP)
+ k = HEAD
+ sk = sk ? sk "." k : k
+ print sk
+ filter(values, key SUBSEP i, sk)
+ } while (v)
+ return
+ }
+ if (v ~ /^a/) {
+ for (i = 0; ((key, i) in values); i++) {
+ sk = sk ? sk "." i : i
+ print sk
+ filter(values, key SUBSEP i, sk)
+ }
+ }
+}
diff --git a/mp b/mp
index c8d4bd7..202a6c5 100755
--- a/mp
+++ b/mp
@@ -10,10 +10,11 @@ BEGIN {
" Prints cmd help or general help text.\n" \
" Example: help help\n"
+ print "### argv[1]: " ARGV[1]
if (str) {
str = ARGV[1]
parse("", v, "", str)
- print format(v)
+ print format(v, "", 0)
exit ERROR != 0
} else filename = ARGV[1]
delete ARGV[1]
@@ -26,7 +27,7 @@ BEGIN {
printf "%s", help[$2]
} else if ($1 == "format") {
if ($2 == "\"\"") $2 = ""
- print format(v, key(v, $2), 0+$3)
+ print format(v, key(v, $2), !raw)
} else if ($1 == "key") {
print key(v, $2)
} else if ($1 == "filter") {
@@ -92,7 +93,7 @@ function parse(infile, values, key, line, id, ids, i, k) {
}
line = scan(infile, line)
}
- values[key] = "a"
+ values[key] = "a" i
} else if (TOKEN == "{") {
for (i = 0; TOKEN != "}"; i++) {
if (i > 0 && TOKEN != ",") return error("not a ','", line)
diff --git a/tests b/tests
index 690da7a..070dedb 100755
--- a/tests
+++ b/tests
@@ -24,6 +24,9 @@ run number_1 '12' '12'
run string_1 '"hello"' '"hello"'
run string_2 '"hello \"world\""' '"hello \"world\""'
run string_3 '""' '""'
+run string_4 '"\""' '"\""'
+run string_5 '"\\\\"' '"\\\\"'
+run string_6 '"\\\"\\"' '"\\\"\\"'
run array_1 '[]' '[]'
run array_2 '[null]' '[null]'
run array_3 '[true,false]' '[true,false]'