First commit
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
wl
|
||||||
|
*.exe
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
all:
|
||||||
|
gcc src/basic.c src/file.c src/parse.c src/main.c -o wl -Wall -Wextra -O0 -g3
|
||||||
@@ -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>
|
||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+78
@@ -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
|
||||||
Reference in New Issue
Block a user