add support to read json files
This commit is contained in:
parent
31d7ac51ed
commit
4bb15c84dd
BIN
build/codegen.o
BIN
build/codegen.o
Binary file not shown.
BIN
build/main.o
BIN
build/main.o
Binary file not shown.
112
src/codegen.cpp
112
src/codegen.cpp
|
|
@ -1,5 +1,6 @@
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
CodeGen::CodeGen() {
|
CodeGen::CodeGen() {
|
||||||
context = std::make_unique<llvm::LLVMContext>();
|
context = std::make_unique<llvm::LLVMContext>();
|
||||||
|
|
@ -50,6 +51,31 @@ CodeGen::CodeGen() {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
llvm::Function::Create(readCsvType, llvm::Function::ExternalLinkage, "sun_read_csv", module.get());
|
llvm::Function::Create(readCsvType, llvm::Function::ExternalLinkage, "sun_read_csv", module.get());
|
||||||
|
|
||||||
|
// void* sun_read_json(char* filename)
|
||||||
|
llvm::FunctionType* readJsonType = llvm::FunctionType::get(
|
||||||
|
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0),
|
||||||
|
{
|
||||||
|
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0) // filename
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
llvm::Function::Create(readJsonType, llvm::Function::ExternalLinkage, "sun_read_json", module.get());
|
||||||
|
|
||||||
|
// void sun_print_json(void* val)
|
||||||
|
llvm::FunctionType* printJsonType = llvm::FunctionType::get(llvm::Type::getVoidTy(*context), {llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0)}, false);
|
||||||
|
llvm::Function::Create(printJsonType, llvm::Function::ExternalLinkage, "sun_print_json", module.get());
|
||||||
|
|
||||||
|
// void* sun_map_get(void* map, char* key)
|
||||||
|
llvm::FunctionType* mapGetType = llvm::FunctionType::get(
|
||||||
|
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0),
|
||||||
|
{
|
||||||
|
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0), // map
|
||||||
|
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0) // key
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
llvm::Function::Create(mapGetType, llvm::Function::ExternalLinkage, "sun_map_get", module.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::AllocaInst* CodeGen::createEntryBlockAlloca(llvm::Function* theFunction, const std::string& varName, llvm::Type* type) {
|
llvm::AllocaInst* CodeGen::createEntryBlockAlloca(llvm::Function* theFunction, const std::string& varName, llvm::Type* type) {
|
||||||
|
|
@ -98,7 +124,7 @@ void CodeGen::visit(NumberExpr& node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGen::visit(StringExpr& node) {
|
void CodeGen::visit(StringExpr& node) {
|
||||||
lastValue = builder->CreateGlobalString(node.value);
|
lastValue = builder->CreateGlobalStringPtr(node.value);
|
||||||
lastClassName = "String"; // Special marker for string
|
lastClassName = "String"; // Special marker for string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,6 +204,36 @@ void CodeGen::visit(CallExpr& node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle "readjson" specially
|
||||||
|
if (node.callee == "readjson") {
|
||||||
|
if (node.args.size() != 1) {
|
||||||
|
std::cerr << "readjson() takes exactly 1 argument." << std::endl;
|
||||||
|
lastValue = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.args[0]->accept(*this);
|
||||||
|
llvm::Value* filenameVal = lastValue;
|
||||||
|
|
||||||
|
if (filenameVal->getType() != llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0)) {
|
||||||
|
filenameVal = builder->CreateBitCast(filenameVal, llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Function* readJsonFn = module->getFunction("sun_read_json");
|
||||||
|
if (!readJsonFn) {
|
||||||
|
std::cerr << "Error: sun_read_json function not found in module!" << std::endl;
|
||||||
|
lastValue = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastValue = builder->CreateCall(readJsonFn, {filenameVal}, "json_data");
|
||||||
|
if (!lastValue) {
|
||||||
|
std::cerr << "Error: CreateCall for sun_read_json returned null!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastClassName = "JSON"; // Special marker
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle "len" specially
|
// Handle "len" specially
|
||||||
if (node.callee == "len") {
|
if (node.callee == "len") {
|
||||||
if (node.args.size() != 1) {
|
if (node.args.size() != 1) {
|
||||||
|
|
@ -211,8 +267,17 @@ void CodeGen::visit(CallExpr& node) {
|
||||||
std::string argType = lastClassName;
|
std::string argType = lastClassName;
|
||||||
|
|
||||||
if (argType == "String") {
|
if (argType == "String") {
|
||||||
|
if (argVal->getType() != llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0)) {
|
||||||
|
argVal = builder->CreateBitCast(argVal, llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0));
|
||||||
|
}
|
||||||
llvm::Function* printStr = module->getFunction("print_string");
|
llvm::Function* printStr = module->getFunction("print_string");
|
||||||
builder->CreateCall(printStr, {argVal});
|
builder->CreateCall(printStr, {argVal});
|
||||||
|
} else if (argType == "JSON") {
|
||||||
|
if (argVal->getType() != llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0)) {
|
||||||
|
argVal = builder->CreateBitCast(argVal, llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0));
|
||||||
|
}
|
||||||
|
llvm::Function* printJson = module->getFunction("sun_print_json");
|
||||||
|
builder->CreateCall(printJson, {argVal});
|
||||||
} else {
|
} else {
|
||||||
// Assume int
|
// Assume int
|
||||||
llvm::Function* printInt = module->getFunction("print_int");
|
llvm::Function* printInt = module->getFunction("print_int");
|
||||||
|
|
@ -309,6 +374,14 @@ void CodeGen::visit(IncrementExpr& node) {
|
||||||
|
|
||||||
indexExpr->index->accept(*this);
|
indexExpr->index->accept(*this);
|
||||||
llvm::Value* indexVal = lastValue;
|
llvm::Value* indexVal = lastValue;
|
||||||
|
std::string indexType = lastClassName;
|
||||||
|
|
||||||
|
if (indexType == "String") {
|
||||||
|
// Map increment? Not supported yet easily without sun_map_set
|
||||||
|
std::cerr << "Increment on map values not fully supported yet." << std::endl;
|
||||||
|
lastValue = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
llvm::Function* getFn = module->getFunction("sun_array_get");
|
llvm::Function* getFn = module->getFunction("sun_array_get");
|
||||||
llvm::Function* setFn = module->getFunction("sun_array_set");
|
llvm::Function* setFn = module->getFunction("sun_array_set");
|
||||||
|
|
@ -867,8 +940,42 @@ void CodeGen::visit(IndexExpr& node) {
|
||||||
llvm::Value* arrPtr = lastValue;
|
llvm::Value* arrPtr = lastValue;
|
||||||
std::string arrayType = lastClassName;
|
std::string arrayType = lastClassName;
|
||||||
|
|
||||||
|
if (!arrPtr) {
|
||||||
|
std::cerr << "Error: Array evaluated to null in IndexExpr" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
node.index->accept(*this);
|
node.index->accept(*this);
|
||||||
llvm::Value* indexVal = lastValue;
|
llvm::Value* indexVal = lastValue;
|
||||||
|
std::string indexType = lastClassName;
|
||||||
|
|
||||||
|
if (!indexVal) {
|
||||||
|
std::cerr << "Error: Index evaluated to null in IndexExpr" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indexType == "String") {
|
||||||
|
// Map lookup
|
||||||
|
llvm::Function* getFn = module->getFunction("sun_map_get");
|
||||||
|
if (!getFn) {
|
||||||
|
std::cerr << "Error: sun_map_get function not found!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
llvm::Value* valPtr = builder->CreateCall(getFn, {arrPtr, indexVal}, "elem");
|
||||||
|
|
||||||
|
// We don't know the return type, assume generic (void*) or int?
|
||||||
|
// If it's JSON, it could be anything.
|
||||||
|
// Let's assume it returns void* and we might need to cast it if we use it as int.
|
||||||
|
// But wait, if we use it in an expression, we expect int or string.
|
||||||
|
// If we assume int, we need PtrToInt.
|
||||||
|
// If we assume String, we keep it as Ptr.
|
||||||
|
|
||||||
|
// For now, let's assume JSON values are either Strings or Ints (casted to Ptr).
|
||||||
|
// If we don't know, we return Ptr.
|
||||||
|
lastValue = valPtr;
|
||||||
|
lastClassName = "JSON"; // Keep it generic
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
llvm::Function* getFn = module->getFunction("sun_array_get");
|
llvm::Function* getFn = module->getFunction("sun_array_get");
|
||||||
llvm::Value* valPtr = builder->CreateCall(getFn, {arrPtr, indexVal}, "elem");
|
llvm::Value* valPtr = builder->CreateCall(getFn, {arrPtr, indexVal}, "elem");
|
||||||
|
|
@ -879,6 +986,9 @@ void CodeGen::visit(IndexExpr& node) {
|
||||||
} else if (arrayType == "CSVArray") {
|
} else if (arrayType == "CSVArray") {
|
||||||
lastValue = valPtr; // It's a void* (pointer to array)
|
lastValue = valPtr; // It's a void* (pointer to array)
|
||||||
lastClassName = "StringArray";
|
lastClassName = "StringArray";
|
||||||
|
} else if (arrayType == "JSON") {
|
||||||
|
lastValue = valPtr;
|
||||||
|
lastClassName = "JSON";
|
||||||
} else {
|
} else {
|
||||||
// Assume IntArray, cast back to i32
|
// Assume IntArray, cast back to i32
|
||||||
lastValue = builder->CreatePtrToInt(valPtr, llvm::Type::getInt32Ty(*context), "elemInt");
|
lastValue = builder->CreatePtrToInt(valPtr, llvm::Type::getInt32Ty(*context), "elemInt");
|
||||||
|
|
|
||||||
258
src/main.cpp
258
src/main.cpp
|
|
@ -40,20 +40,63 @@ char* str_concat(char* a, char* b) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Struct Definitions
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
int type; // 0=int, 1=string, 2=array, 3=map, 4=null
|
||||||
|
union {
|
||||||
|
int i;
|
||||||
|
char* s;
|
||||||
|
void* ptr;
|
||||||
|
} as;
|
||||||
|
} JsonValue;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int magic; // 0x12345678
|
||||||
int size;
|
int size;
|
||||||
void** data;
|
void** data;
|
||||||
} Array;
|
} Array;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* key;
|
||||||
|
void* value;
|
||||||
|
} MapEntry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int size;
|
||||||
|
int capacity;
|
||||||
|
MapEntry* entries;
|
||||||
|
} Map;
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
void* sun_array_create(int size);
|
||||||
|
JsonValue* sun_json_array(void* arr);
|
||||||
|
JsonValue* sun_json_map(void* map);
|
||||||
|
JsonValue* sun_json_string(char* s);
|
||||||
|
JsonValue* sun_json_int(int i);
|
||||||
|
JsonValue* sun_json_null();
|
||||||
|
char* sun_strdup(const char* s);
|
||||||
|
|
||||||
|
// Array Functions
|
||||||
void* sun_array_create(int size) {
|
void* sun_array_create(int size) {
|
||||||
Array* arr = (Array*)malloc(sizeof(Array));
|
Array* arr = (Array*)malloc(sizeof(Array));
|
||||||
|
arr->magic = 0x12345678;
|
||||||
arr->size = size;
|
arr->size = size;
|
||||||
arr->data = (void**)calloc(size, sizeof(void*));
|
arr->data = (void**)calloc(size, sizeof(void*));
|
||||||
return (void*)arr;
|
return (void*)arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sun_array_set(void* arrPtr, int index, void* value) {
|
void sun_array_set(void* arrPtr, int index, void* value) {
|
||||||
|
if (!arrPtr) return;
|
||||||
Array* arr = (Array*)arrPtr;
|
Array* arr = (Array*)arrPtr;
|
||||||
|
if (arr->magic != 0x12345678) {
|
||||||
|
JsonValue* v = (JsonValue*)arrPtr;
|
||||||
|
if (v->type == 2) {
|
||||||
|
arr = (Array*)v->as.ptr;
|
||||||
|
} else {
|
||||||
|
printf("Error: Not an array (set)\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (index >= 0 && index < arr->size) {
|
if (index >= 0 && index < arr->size) {
|
||||||
arr->data[index] = value;
|
arr->data[index] = value;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -63,21 +106,118 @@ void sun_array_set(void* arrPtr, int index, void* value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void* sun_array_get(void* arrPtr, int index) {
|
void* sun_array_get(void* arrPtr, int index) {
|
||||||
|
if (!arrPtr) return NULL;
|
||||||
Array* arr = (Array*)arrPtr;
|
Array* arr = (Array*)arrPtr;
|
||||||
|
if (arr->magic != 0x12345678) {
|
||||||
|
JsonValue* v = (JsonValue*)arrPtr;
|
||||||
|
if (v->type == 2) {
|
||||||
|
arr = (Array*)v->as.ptr;
|
||||||
|
} else {
|
||||||
|
printf("Error: Not an array (get) type=%d magic=%x\n", v->type, arr->magic);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (index >= 0 && index < arr->size) {
|
if (index >= 0 && index < arr->size) {
|
||||||
return arr->data[index];
|
return arr->data[index];
|
||||||
} else {
|
} else {
|
||||||
printf("Error: Array index out of bounds: %d\n", index);
|
printf("Error: Array index out of bounds: %d\n", index);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int sun_array_length(void* arrPtr) {
|
int sun_array_length(void* arrPtr) {
|
||||||
|
if (!arrPtr) return 0;
|
||||||
Array* arr = (Array*)arrPtr;
|
Array* arr = (Array*)arrPtr;
|
||||||
|
if (arr->magic != 0x12345678) {
|
||||||
|
JsonValue* v = (JsonValue*)arrPtr;
|
||||||
|
if (v->type == 2) {
|
||||||
|
arr = (Array*)v->as.ptr;
|
||||||
|
} else {
|
||||||
|
printf("Error: Not an array (len)\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
return arr->size;
|
return arr->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Map Functions
|
||||||
|
void* sun_map_create() {
|
||||||
|
Map* map = (Map*)malloc(sizeof(Map));
|
||||||
|
map->size = 0;
|
||||||
|
map->capacity = 8;
|
||||||
|
map->entries = (MapEntry*)malloc(sizeof(MapEntry) * map->capacity);
|
||||||
|
return (void*)map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_map_set(void* mapPtr, char* key, void* value) {
|
||||||
|
Map* map = (Map*)mapPtr;
|
||||||
|
for (int i = 0; i < map->size; i++) {
|
||||||
|
if (strcmp(map->entries[i].key, key) == 0) {
|
||||||
|
map->entries[i].value = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (map->size >= map->capacity) {
|
||||||
|
map->capacity *= 2;
|
||||||
|
map->entries = (MapEntry*)realloc(map->entries, sizeof(MapEntry) * map->capacity);
|
||||||
|
}
|
||||||
|
map->entries[map->size].key = sun_strdup(key);
|
||||||
|
map->entries[map->size].value = value;
|
||||||
|
map->size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* sun_map_get(void* mapPtr, char* key) {
|
||||||
|
if (!mapPtr) return NULL;
|
||||||
|
JsonValue* v = (JsonValue*)mapPtr;
|
||||||
|
if (v->type == 3) {
|
||||||
|
mapPtr = v->as.ptr;
|
||||||
|
}
|
||||||
|
Map* map = (Map*)mapPtr;
|
||||||
|
for (int i = 0; i < map->size; i++) {
|
||||||
|
if (strcmp(map->entries[i].key, key) == 0) {
|
||||||
|
return map->entries[i].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON Constructors
|
||||||
|
JsonValue* sun_json_int(int i) {
|
||||||
|
JsonValue* v = (JsonValue*)malloc(sizeof(JsonValue));
|
||||||
|
v->type = 0; v->as.i = i; return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue* sun_json_string(char* s) {
|
||||||
|
JsonValue* v = (JsonValue*)malloc(sizeof(JsonValue));
|
||||||
|
v->type = 1; v->as.s = s; return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue* sun_json_array(void* arr) {
|
||||||
|
JsonValue* v = (JsonValue*)malloc(sizeof(JsonValue));
|
||||||
|
v->type = 2; v->as.ptr = arr; return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue* sun_json_map(void* map) {
|
||||||
|
JsonValue* v = (JsonValue*)malloc(sizeof(JsonValue));
|
||||||
|
v->type = 3; v->as.ptr = map; return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue* sun_json_null() {
|
||||||
|
JsonValue* v = (JsonValue*)malloc(sizeof(JsonValue));
|
||||||
|
v->type = 4; return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_print_json(void* ptr) {
|
||||||
|
if (!ptr) { printf("null\n"); return; }
|
||||||
|
JsonValue* v = (JsonValue*)ptr;
|
||||||
|
if (v->type == 0) printf("%d\n", v->as.i);
|
||||||
|
else if (v->type == 1) printf("%s\n", v->as.s);
|
||||||
|
else if (v->type == 2) printf("[Array]\n");
|
||||||
|
else if (v->type == 3) printf("[Object]\n");
|
||||||
|
else if (v->type == 4) printf("null\n");
|
||||||
|
else printf("Unknown JSON type: %d\n", v->type);
|
||||||
|
}
|
||||||
|
|
||||||
char* sun_strdup(const char* s) {
|
char* sun_strdup(const char* s) {
|
||||||
char* d = (char*)malloc(strlen(s) + 1);
|
char* d = (char*)malloc(strlen(s) + 1);
|
||||||
if (d == NULL) return NULL;
|
if (d == NULL) return NULL;
|
||||||
|
|
@ -85,6 +225,122 @@ char* sun_strdup(const char* s) {
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JSON Parser
|
||||||
|
char* json_pos;
|
||||||
|
void skip_whitespace() {
|
||||||
|
while (*json_pos && (*json_pos == ' ' || *json_pos == '\t' || *json_pos == '\n' || *json_pos == '\r')) {
|
||||||
|
json_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void* parse_json_value();
|
||||||
|
|
||||||
|
char* parse_json_string() {
|
||||||
|
skip_whitespace();
|
||||||
|
if (*json_pos != '"') return NULL;
|
||||||
|
json_pos++;
|
||||||
|
char* start = json_pos;
|
||||||
|
while (*json_pos && *json_pos != '"') {
|
||||||
|
json_pos++;
|
||||||
|
}
|
||||||
|
if (*json_pos == '"') {
|
||||||
|
*json_pos = '\0';
|
||||||
|
char* str = sun_strdup(start);
|
||||||
|
*json_pos = '"';
|
||||||
|
json_pos++;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* parse_json_object() {
|
||||||
|
skip_whitespace();
|
||||||
|
if (*json_pos != '{') return NULL;
|
||||||
|
json_pos++;
|
||||||
|
void* map = sun_map_create();
|
||||||
|
skip_whitespace();
|
||||||
|
if (*json_pos == '}') {
|
||||||
|
json_pos++;
|
||||||
|
return sun_json_map(map);
|
||||||
|
}
|
||||||
|
while (1) {
|
||||||
|
skip_whitespace();
|
||||||
|
char* key = parse_json_string();
|
||||||
|
skip_whitespace();
|
||||||
|
if (*json_pos != ':') { printf("Expected : in JSON object\n"); exit(1); }
|
||||||
|
json_pos++;
|
||||||
|
void* value = parse_json_value();
|
||||||
|
sun_map_set(map, key, value);
|
||||||
|
skip_whitespace();
|
||||||
|
if (*json_pos == ',') { json_pos++; continue; }
|
||||||
|
else if (*json_pos == '}') { json_pos++; break; }
|
||||||
|
else { printf("Expected , or } in JSON object\n"); exit(1); }
|
||||||
|
}
|
||||||
|
return sun_json_map(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* parse_json_array() {
|
||||||
|
skip_whitespace();
|
||||||
|
if (*json_pos != '[') return NULL;
|
||||||
|
json_pos++;
|
||||||
|
int capacity = 8;
|
||||||
|
int size = 0;
|
||||||
|
void** temp = (void**)malloc(sizeof(void*) * capacity);
|
||||||
|
skip_whitespace();
|
||||||
|
if (*json_pos == ']') {
|
||||||
|
json_pos++;
|
||||||
|
void* arr = sun_array_create(0);
|
||||||
|
free(temp);
|
||||||
|
return sun_json_array(arr);
|
||||||
|
}
|
||||||
|
while (1) {
|
||||||
|
void* val = parse_json_value();
|
||||||
|
if (size >= capacity) {
|
||||||
|
capacity *= 2;
|
||||||
|
temp = (void**)realloc(temp, sizeof(void*) * capacity);
|
||||||
|
}
|
||||||
|
temp[size++] = val;
|
||||||
|
skip_whitespace();
|
||||||
|
if (*json_pos == ',') { json_pos++; continue; }
|
||||||
|
else if (*json_pos == ']') { json_pos++; break; }
|
||||||
|
else { printf("Expected , or ] in JSON array\n"); exit(1); }
|
||||||
|
}
|
||||||
|
void* arr = sun_array_create(size);
|
||||||
|
Array* a = (Array*)arr;
|
||||||
|
for(int i=0; i<size; i++) a->data[i] = temp[i];
|
||||||
|
free(temp);
|
||||||
|
return sun_json_array(arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* parse_json_value() {
|
||||||
|
skip_whitespace();
|
||||||
|
if (*json_pos == '{') return parse_json_object();
|
||||||
|
if (*json_pos == '[') return parse_json_array();
|
||||||
|
if (*json_pos == '"') return sun_json_string(parse_json_string());
|
||||||
|
if ((*json_pos >= '0' && *json_pos <= '9') || *json_pos == '-') {
|
||||||
|
int val = strtol(json_pos, &json_pos, 10);
|
||||||
|
return sun_json_int(val);
|
||||||
|
}
|
||||||
|
if (strncmp(json_pos, "true", 4) == 0) { json_pos += 4; return sun_json_int(1); }
|
||||||
|
if (strncmp(json_pos, "false", 5) == 0) { json_pos += 5; return sun_json_int(0); }
|
||||||
|
if (strncmp(json_pos, "null", 4) == 0) { json_pos += 4; return sun_json_null(); }
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* sun_read_json(char* filename) {
|
||||||
|
FILE* fp = fopen(filename, "r");
|
||||||
|
if (!fp) { printf("Error: Could not open file %s\n", filename); exit(1); }
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
long length = ftell(fp);
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
char* buffer = (char*)malloc(length + 1);
|
||||||
|
fread(buffer, 1, length, fp);
|
||||||
|
buffer[length] = '\0';
|
||||||
|
fclose(fp);
|
||||||
|
json_pos = buffer;
|
||||||
|
void* result = parse_json_value();
|
||||||
|
free(buffer);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
void* sun_read_csv(char* filename, char* separator, char* quote) {
|
void* sun_read_csv(char* filename, char* separator, char* quote) {
|
||||||
FILE* fp = fopen(filename, "r");
|
FILE* fp = fopen(filename, "r");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#ifndef SUN_VERSION_H
|
#ifndef SUN_VERSION_H
|
||||||
#define SUN_VERSION_H
|
#define SUN_VERSION_H
|
||||||
|
|
||||||
#define SUN_VERSION "0.4.0"
|
#define SUN_VERSION "0.5.0"
|
||||||
|
|
||||||
#endif // SUN_VERSION_H
|
#endif // SUN_VERSION_H
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"name": "SunLang",
|
||||||
|
"version": 1,
|
||||||
|
"features": ["csv", "json"],
|
||||||
|
"nested": {
|
||||||
|
"key": "value"
|
||||||
|
},
|
||||||
|
"list": [10, 20, 30]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
function main() {
|
||||||
|
var data = readjson("./tests/test.json");
|
||||||
|
|
||||||
|
print(data["name"]);
|
||||||
|
print(data["version"]);
|
||||||
|
|
||||||
|
var list = data["list"];
|
||||||
|
print(list[0]);
|
||||||
|
print(list[1]);
|
||||||
|
|
||||||
|
var nested = data["nested"];
|
||||||
|
print(nested["key"]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue