🐛 fix bug in json.cpp & add std/argparse.nas

This commit is contained in:
ValKmjolnir 2023-12-07 00:04:41 +08:00
parent a2c738d4c7
commit 8e0d1e18e1
26 changed files with 115 additions and 16 deletions

View File

@ -237,6 +237,7 @@ clean:
.PHONY: test
test:nasal
@ ./nasal test/argparse_test.nas
@ ./nasal -e test/ascii-art.nas
@ ./nasal -t -d test/bfs.nas
@ ./nasal -t test/bigloop.nas

View File

@ -69,7 +69,7 @@ private:
bool check(char c) {
return c=='{' || c=='}' || c=='[' || c==']' ||
c==':' || c==',' || c=='"' || c=='\'' ||
is_num(c) || is_id(c);
c=='-' || c=='+' || is_num(c) || is_id(c);
}
void next();
void match(token_type);
@ -155,10 +155,10 @@ void json::next() {
while(ptr<text.length() && !check(text[ptr])) {
if (text[ptr]=='\n') {
++line;
} else if (text[ptr]!=' ' && text[ptr]!='\t') {
} else if (text[ptr]!=' ' && text[ptr]!='\t' && text[ptr]!='\r') {
error_info() += "json::parse: line " + std::to_string(line);
error_info() += ": invalid character `";
error_info() += text[ptr];
error_info() += ": invalid character `0x";
error_info() += char_to_hex(text[ptr]);
error_info() += "`\n";
}
++ptr;
@ -177,7 +177,7 @@ void json::next() {
case ':': this_token = {token_type::tok_colon, ":"}; ++ptr; return;
default: break;
}
if (is_num(c)) {
if (is_num(c) || c=='-' || c=='+') {
auto temp = std::string(1, c);
++ptr;
while(ptr<text.length() && (

View File

@ -314,7 +314,8 @@ std::string vm::report_lack_arguments(u32 argc, const nas_func& func) const {
}
result += ") ";
std::stringstream out;
out << "{entry: 0x" << std::hex << func.entry << std::dec << "}";
const auto& code = bytecode[func.entry];
out << "{ entry: " << files[code.fidx] << ":" << code.line << " }";
out << " @ 0x" << std::hex << reinterpret_cast<u64>(&func) << std::dec;
return result + out.str();
}
@ -337,7 +338,8 @@ std::string vm::report_special_call_lack_arguments(
result = result.substr(0, result.length()-2);
result += ") ";
std::stringstream out;
out << "{entry: 0x" << std::hex << func.entry << std::dec << "}";
const auto& code = bytecode[func.entry];
out << "{ entry: " << files[code.fidx] << ":" << code.line << " }";
out << " @ 0x" << std::hex << reinterpret_cast<u64>(&func) << std::dec;
return result + out.str();
}

55
std/argparse.nas Normal file
View File

@ -0,0 +1,55 @@
var _arg = globals.arg;
var new = func(description) {
var parser = {
description: description,
subparser: [],
command_list: [],
add_command: func(long, short, help) {
return _add_command(parser, long, short, help);
},
add_subparser: func(name, help) {
return _add_subparser(parser, name, help);
},
parse: func() {
return _parse(parser);
}
};
return parser;
}
var _help = func(parser) {
println(parser.description);
println("Subcommand:");
foreach(var cmd; parser.subparser) {
println(cmd.name, "\t", cmd.parser.description);
}
println("Options:");
foreach(var cmd; parser.command_list) {
println(cmd.full_name, " ", cmd.short_name, "\t", cmd.help);
}
}
var _parse = func(parser) {
if (size(_arg)==0) {
_help(parser);
}
}
var _add_command = func(parser, long, short, help) {
var new_command = {
full_name: long,
short_name: short,
help: help
};
append(parser.command_list, new_command);
}
var _add_subparser = func(parser, name, help) {
var new_subparser = {
name: name,
parser: new(help)
};
append(parser.subparser, new_subparser);
}

View File

@ -1,6 +1,5 @@
# lib.nas
# 2019 ValKmjolnir
use std.math;
# print is used to print all things in nasal, try and see how it works.
# this function uses std::cout to output logs.
@ -271,7 +270,14 @@ var isint = func(x) {
}
var isnum = func(x) {
return typeof(x)=="num" or !math.isnan(num(x));
if (typeof(x)=="num") {
return true;
}
x = num(x);
if (!__isnan(x) and x!=nil) {
return true;
}
return false;
}
var isscalar = func(s) {
@ -347,8 +353,8 @@ var md5 = func(str) {
}
# important global constants
var D2R = math.pi / 180; # degree to radian
var R2D = 180 / math.pi; # radian to degree
var D2R = 3.14159265358979323846264338327950288 / 180; # degree to radian
var R2D = 180 / 3.14159265358979323846264338327950288; # radian to degree
var FT2M = 0.3048; # feet to meter
var M2FT = 1 / FT2M;

View File

@ -1,3 +1,4 @@
use std.math;
var mat = func(width,height) {
var res=[];

View File

@ -4,7 +4,7 @@
# 2023/11/06 ValKmjolnir
use module.libsock;
use std.json;
use module.libjson;
use std.os;
use std.unix;
@ -87,9 +87,9 @@ var new = func(hostname, port) {
var data = substr(total_source, begin_position, length);
# parse this json and return
var props = json.parse(data);
if (json.get_error()) {
println("encounter error when parsing \"", path, "\"");
var props = libjson.parse(data);
if (size(libjson.get_error())>0) {
println("encounter error when parsing \"", path, "\":\n", libjson.get_error());
logprint(LOG_DEBUG, _raw_str(data));
return {path: path};
}

View File

@ -9,6 +9,7 @@
# local node, there is no equivalent of the "relative path" variants
# available in C++; just use node.getNode(path).whatever() instead.
#
use std.math;
var _new = func {
return {

View File

@ -1,6 +1,8 @@
# utils.nas
# 2023 by ValKmjolnir
use std.math;
# when count can be divided exactly by times, return true
var times_trigger = func(times, count) {
return math.mod(times, count)==0;
}

11
test/argparse_test.nas Normal file
View File

@ -0,0 +1,11 @@
# use module.libjson;
# libjson.stringify(math.tan);
# println(libjson.get_error());
use std.argparse;
var args = argparse.new("test cli");
args.add_command("--what", "-w", "what-what");
args.add_subparser("what", "what-what");
args.parse();

View File

@ -1,5 +1,6 @@
# Road check and auto pilot by ValKmjolnir
use std.fg_env;
use std.math;
var props = fg_env.props;
var geodinfo = fg_env.geodinfo;

View File

@ -1,4 +1,5 @@
use std.mat;
use std.math;
rand(time(0));

View File

@ -1,6 +1,7 @@
use std.process_bar;
use std.os;
use std.io;
use std.math;
var ppm = func(filename, width, height, RGB) {
# P3 use ASCII number

View File

@ -23,6 +23,7 @@
# SOFTWARE.
use module.libmat;
use std.runtime;
use std.math;
func() {
# allocate more spaces

View File

@ -1,4 +1,5 @@
use std.runtime;
use std.math;
var mod = math.mod;

View File

@ -1,6 +1,7 @@
use std.process_bar;
use std.os;
use std.io;
use std.math;
var ppm = func(filename, width, height, RGB) {
# P3 use ASCII number

View File

@ -1,5 +1,6 @@
use std.bits;
use std.os;
use std.math;
var inst={
inst_stop:0,

View File

@ -1,4 +1,5 @@
use std.bits;
use std.math;
var check = func(x) {
if (x<0x100000000)

View File

@ -3,6 +3,7 @@ use std.process_bar;
use std.file;
use std.os;
use std.io;
use std.math;
srand();

View File

@ -5,6 +5,7 @@ use std.runtime;
use std.os;
use std.io;
use std.unix;
use std.math;
var is_windows_platform=os.platform()=="windows";
var is_macos_platform=os.platform()=="macOS";

View File

@ -1,3 +1,5 @@
use std.math;
var is_prime = func(x) {
for(var i=2;i<x;i+=1)
if (x/i==int(x/i))

View File

@ -1,4 +1,5 @@
use std.runtime;
use std.math;
# basic type
nil;

View File

@ -1,3 +1,4 @@
use std.math;
var REPS = 10;
var COUNT = 16384;

View File

@ -1,4 +1,8 @@
use std.phi;
use std.math;
use std.utils;
# if on WSL2, you may need to use `ip route` to see the ip of the host
var tips = func() {
println("usage:");
@ -20,7 +24,7 @@ var connect = phi.new(arg[0], num(arg[1]));
var count = 0;
var recursive_get_prop = func(path = "/") {
count += 1;
if (math.mod(count, 50)==0) {
if (utils.times_trigger(count, 20)) {
println("get ", count," nodes, now: \"", path, "\"");
}
var props = connect.getprop(path);

View File

@ -1,4 +1,5 @@
use std.io;
use std.math;
var ppm = func(filename, buffer) {
# P3 use ASCII number

View File

@ -2,6 +2,7 @@ use std.file;
use std.padding;
use std.process_bar;
use std.io;
use std.math;
var tips = func() {
println("usage:");