diff options
| author | Marc Vertes <mvertes@free.fr> | 2025-07-22 23:20:13 +0200 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2025-07-22 23:20:13 +0200 |
| commit | b5d5888c59160f5ab30aaaf0288b6ad6d0a81bdd (patch) | |
| tree | 5963e9bcfe4943c1bfd4f4923f9d35e06763acf6 | |
| parent | 1f563060887b979e0138567fb13bef97dc8fd915 (diff) | |
add other experiments jp and ev
| -rw-r--r-- | ev | 9 | ||||
| -rwxr-xr-x | jp | 218 | ||||
| -rwxr-xr-x | mp | 7 | ||||
| -rwxr-xr-x | tests | 3 |
4 files changed, 234 insertions, 3 deletions
@@ -0,0 +1,9 @@ +#!/usr/bin/env awk -f + +# an evaluator of code + +BEGIN { +} + +eval(mem, src) { +} @@ -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) + } + } +} @@ -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) @@ -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]' |
