First commit

This commit is contained in:
2025-08-02 19:53:48 +02:00
commit 4d746942f0
12 changed files with 2186 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
wl
*.exe
+2
View File
@@ -0,0 +1,2 @@
all:
gcc src/basic.c src/file.c src/parse.c src/main.c -o wl -Wall -Wextra -O0 -g3
+22
View File
@@ -0,0 +1,22 @@
func(1, 3, 5);
title = "My Website";
posts = [
{ name: "Post Title 1", data: "1 Jan 2025" },
{ name: "Post Title 2", data: "1 May 2024" },
];
<html>
<head>
<title>$(title);</title>
</head>
<body>
<ul>
$ for post in posts:
<li>$(post.name); - $(post.date);</li>
</ul>
$ comment(1, 3, 4);
</body>
</html>
+28
View File
@@ -0,0 +1,28 @@
---3;
hello;
world;
if 1 + 2: {
a;
b + 3 * 4;
c;
}
while 1 + 2:
"This is a string";
<html>
<head name=hello xxx>
aaa
<title>Some Title</title>
bbb
</head>
<body>
<ul>
$ while 1:
<li>$post.name; $post.date;</li>;
</ul>
</body>
</html>;
+119
View File
@@ -0,0 +1,119 @@
#include "parse.h"
typedef enum {
SCOPE_FUNC,
SCOPE_FOR,
SCOPE_WHILE,
SCOPE_IF,
SCOPE_ELSE,
} ScopeType;
typedef struct {
Node *funcs;
int num_funcs;
int cap_funcs;
} Scope;
void assemble_node(Node *node)
{
switch (node->type) {
case NODE_FUNC_DECL:
break;
case NODE_FUNC_ARG:
break;
case NODE_FUNC_CALL:
{
Node *func = node->left;
Node *args = node->right;
if (func->type == NODE_VALUE_VAR) {
// TODO
}
}
break;
case NODE_BLOCK:
break;
case NODE_IFELSE:
break;
case NODE_FOR:
break;
case NODE_WHILE:
break;
case NODE_SELECT:
break;
case NODE_OPER_POS:
break;
case NODE_OPER_NEG:
break;
case NODE_OPER_ASS:
break;
case NODE_OPER_EQL:
break;
case NODE_OPER_NQL:
break;
case NODE_OPER_LSS:
break;
case NODE_OPER_GRT:
break;
case NODE_OPER_ADD:
break;
case NODE_OPER_SUB:
break;
case NODE_OPER_MUL:
break;
case NODE_OPER_DIV:
break;
case NODE_OPER_MOD:
break;
case NODE_VALUE_INT:
break;
case NODE_VALUE_FLOAT:
break;
case NODE_VALUE_STR:
break;
case NODE_VALUE_VAR:
break;
case NODE_VALUE_HTML:
break;
case NODE_VALUE_ARRAY:
break;
case NODE_VALUE_MAP:
break;
case NODE_HTML_PARAM:
break;
}
}
void assemble(Node *root)
{
}
+87
View File
@@ -0,0 +1,87 @@
#include <stddef.h>
#include <stdint.h>
#include "basic.h"
b32 is_space(char c)
{
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
}
b32 is_digit(char c)
{
return c >= '0' && c <= '9';
}
b32 is_alpha(char c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
b32 is_printable(char c)
{
return c >= ' ' && c <= '~';
}
b32 is_hex_digit(char c)
{
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}
char to_lower(char c)
{
if (c >= 'A' && c <= 'Z')
return c - 'A' + 10;
return c;
}
int hex_digit_to_int(char c)
{
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return c - '0';
}
b32 streq(String a, String b)
{
if (a.len != b.len)
return false;
for (int i = 0; i < a.len; i++)
if (a.ptr[i] != b.ptr[i])
return false;
return true;
}
b32 streqcase(String a, String b)
{
if (a.len != b.len)
return false;
for (int i = 0; i < a.len; i++)
if (to_lower(a.ptr[i]) != to_lower(b.ptr[i]))
return false;
return true;
}
void *alloc(Arena *a, int len, int align)
{
int pad = -(intptr_t) (a->ptr + a->cur) & (align-1);
if (a->len - a->cur < len + pad)
return NULL;
void *ret = a->ptr + a->cur + pad;
a->cur += pad + len;
return ret;
}
b32 grow_alloc(Arena *a, char *p, int new_len)
{
int new_cur = (p - a->ptr) + new_len;
if (new_cur > a->len)
return false;
a->cur = new_cur;
return true;
}
+43
View File
@@ -0,0 +1,43 @@
#ifndef WL_BASIC_INCLUDED
#define WL_BASIC_INCLUDED
typedef unsigned int b32;
#define true 1
#define false 0
typedef struct {
char *ptr;
int len;
} String;
typedef struct {
char *ptr;
int len;
int cur;
} Arena;
#ifdef _WIN32
#define LLU "llu"
#else
#define LLU "lu"
#endif
#define S(X) (String) { (X), (int) sizeof(X)-1 }
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
b32 is_space(char c);
b32 is_digit(char c);
b32 is_alpha(char c);
b32 is_printable(char c);
char to_lower(char c);
b32 is_hex_digit(char c);
int hex_digit_to_int(char c);
b32 streq(String a, String b);
b32 streqcase(String a, String b);
void *alloc(Arena *a, int len, int align);
b32 grow_alloc(Arena *a, char *p, int new_len);
#endif // WL_BASIC_INCLUDED
+122
View File
@@ -0,0 +1,122 @@
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <limits.h>
#include <sys/stat.h>
#endif
#include "file.h"
int file_open(String path, File *handle, int *size)
{
char zt[1<<10];
if (path.len >= (int) sizeof(zt))
return -1;
memcpy(zt, path.ptr, path.len);
zt[path.len] = '\0';
#ifdef _WIN32
*handle = CreateFileA(
zt,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (*handle == INVALID_HANDLE_VALUE) {
DWORD error = GetLastError();
if (error == ERROR_FILE_NOT_FOUND ||
error == ERROR_ACCESS_DENIED)
return 1;
return -1;
}
LARGE_INTEGER fileSize;
if (!GetFileSizeEx(*handle, &fileSize)) {
CloseHandle(*handle);
return -1;
}
if (fileSize.QuadPart > INT_MAX) {
CloseHandle(*handle);
return -1;
}
*size = (int) fileSize.QuadPart;
#else
*handle = open(zt, O_RDONLY);
if (*handle < 0) {
if (errno == ENOENT)
return 1;
return -1;
}
struct stat info;
if (fstat(*handle, &info) < 0) {
close(*handle);
return -1;
}
if (S_ISDIR(info.st_mode)) {
close(*handle);
return 1;
}
if (info.st_size > INT_MAX) {
close(*handle);
return -1;
}
*size = (int) info.st_size;
#endif
return 0;
}
void file_close(File file)
{
#ifdef _WIN32
CloseHandle(file);
#else
close(file);
#endif
}
int file_read(File file, char *dst, int max)
{
#ifdef _WIN32
DWORD num;
BOOL ok = ReadFile(file, dst, max, &num, NULL);
if (!ok)
return -1;
return (int) num;
#else
return read(file, dst, max);
#endif
}
int file_read_all(String path, String *dst)
{
int len;
File handle;
if (file_open(path, &handle, &len) < 0)
return -1;
char *ptr = malloc(len+1);
if (ptr == NULL) {
file_close(handle);
return -1;
}
for (int copied = 0; copied < len; ) {
int ret = file_read(handle, ptr + copied, len - copied);
if (ret <= 0) {
free(ptr);
file_close(handle);
return -1;
}
copied += ret;
}
*dst = (String) { ptr, len };
file_close(handle);
return 0;
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef WL_FILE_INCLUDED
#define WL_FILE_INCLUDED
#include "basic.h"
#if _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
typedef HANDLE File;
#else
typedef int File;
#endif
int file_open(String path, File *handle, int *size);
void file_close(File file);
int file_read(File file, char *dst, int max);
int file_read_all(String path, String *dst);
#endif // WL_FILE_INCLUDED
+31
View File
@@ -0,0 +1,31 @@
#include <stdio.h>
#include <stdlib.h>
#include "file.h"
#include "parse.h"
int main(void)
{
String src;
int ret = file_read_all(S("main.wl"), &src);
if (ret < 0) {
printf("Error!\n");
return -1;
}
char err[1<<9];
char mem[1<<14];
Arena a = { mem, (int) sizeof(mem), 0 };
ParseResult result = parse(src, &a, err, (int) sizeof(err));
if (result.node == NULL) {
printf("%.*s\n", result.errlen, err);
return -1;
}
print_node(result.node);
fflush(stdout);
free(src.ptr);
return 0;
}
+1633
View File
File diff suppressed because it is too large Load Diff
+78
View File
@@ -0,0 +1,78 @@
#ifndef WL_PARSE_INCLUDED
#define WL_PARSE_INCLUDED
#include <stdint.h>
#include "basic.h"
typedef enum {
NODE_FUNC_DECL,
NODE_FUNC_ARG,
NODE_FUNC_CALL,
NODE_BLOCK,
NODE_IFELSE,
NODE_FOR,
NODE_WHILE,
NODE_SELECT,
NODE_OPER_POS,
NODE_OPER_NEG,
NODE_OPER_ASS,
NODE_OPER_EQL,
NODE_OPER_NQL,
NODE_OPER_LSS,
NODE_OPER_GRT,
NODE_OPER_ADD,
NODE_OPER_SUB,
NODE_OPER_MUL,
NODE_OPER_DIV,
NODE_OPER_MOD,
NODE_VALUE_INT,
NODE_VALUE_FLOAT,
NODE_VALUE_STR,
NODE_VALUE_VAR,
NODE_VALUE_HTML,
NODE_VALUE_ARRAY,
NODE_VALUE_MAP,
NODE_HTML_PARAM,
} NodeType;
typedef struct Node Node;
struct Node {
NodeType type;
Node *next;
Node *key;
Node *left;
Node *right;
uint64_t ival;
double dval;
String sval;
Node *params;
Node *child;
Node *cond;
String tagname;
String attr_name;
Node *attr_value;
String for_var1;
String for_var2;
Node *for_set;
String func_name;
Node *func_args;
Node *func_body;
};
typedef struct {
Node *node;
int errlen;
} ParseResult;
void print_node(Node *node);
ParseResult parse(String src, Arena *a, char *errbuf, int errmax);
#endif // WL_PARSE_INCLUDED