A whole host of stuff
We now have a primitive and not fully tested parser for strings and symbol sequences. We record the lines and columns of each object on the object for better compile time error handling. I've also structured the code base in a slightly weirder fashion, which makes my includes look nicer. I've split up stuff quite a bit to ensure code units are bit more focused.
This commit is contained in:
56
src/arl/lib/base.h
Normal file
56
src/arl/lib/base.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* base.h: Basic definitions
|
||||
* Created: 2026-01-22
|
||||
* Author: Aryadev Chavali
|
||||
* License: See end of file
|
||||
* Commentary:
|
||||
|
||||
Taken from prick_aliases.h: see https://github.com/oreodave/prick.
|
||||
*/
|
||||
|
||||
#ifndef BASE_H
|
||||
#define BASE_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
typedef int8_t i8;
|
||||
typedef int16_t i16;
|
||||
typedef int32_t i32;
|
||||
typedef int64_t i64;
|
||||
|
||||
static_assert(sizeof(float) == 4, "f32 requires 4 byte floats");
|
||||
static_assert(sizeof(double) == 8, "f64 requires 8 byte doubles");
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||
#define MIN(A, B) ((A) > (B) ? (B) : (A))
|
||||
#define ARRSIZE(A) ((sizeof(A)) / sizeof((A)[0]))
|
||||
|
||||
#define FAIL(...) \
|
||||
do \
|
||||
{ \
|
||||
fprintf(stderr, "FAIL: "); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
assert(0); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
/* Copyright (C) 2026 Aryadev Chavali
|
||||
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the MIT License for details.
|
||||
|
||||
* You may distribute and modify this code under the terms of the MIT License,
|
||||
* which you should have received a copy of along with this program. If not,
|
||||
* please go to <https://opensource.org/license/MIT>.
|
||||
|
||||
*/
|
||||
63
src/arl/lib/sv.c
Normal file
63
src/arl/lib/sv.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/* sv.c: String View implementations
|
||||
* Created: 2026-01-22
|
||||
* Author: Aryadev Chavali
|
||||
* License: See end of file
|
||||
* Commentary: See /include/sv.h
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <arl/lib/sv.h>
|
||||
|
||||
sv_t sv_chop_left(sv_t sv, u64 len)
|
||||
{
|
||||
if (sv.size < len)
|
||||
{
|
||||
return SV(NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return SV(sv.data + len, sv.size - len);
|
||||
}
|
||||
}
|
||||
|
||||
sv_t sv_chop_right(sv_t sv, u64 len)
|
||||
{
|
||||
if (sv.size < len)
|
||||
{
|
||||
return SV(NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return SV(sv.data, sv.size - len);
|
||||
}
|
||||
}
|
||||
|
||||
u64 sv_while(const sv_t sv, const char *expected)
|
||||
{
|
||||
u64 i;
|
||||
for (i = 0; i < sv.size && strchr(expected, sv.data[i]) != NULL; ++i)
|
||||
continue;
|
||||
return i;
|
||||
}
|
||||
|
||||
u64 sv_till(const sv_t sv, const char *expected)
|
||||
{
|
||||
u64 i;
|
||||
for (i = 0; i < sv.size && strchr(expected, sv.data[i]) == NULL; ++i)
|
||||
continue;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Copyright (C) 2026 Aryadev Chavali
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MIT License
|
||||
* for details.
|
||||
|
||||
* You may distribute and modify this code under the terms of the
|
||||
* MIT License, which you should have received a copy of along with this
|
||||
* program. If not, please go to <https://opensource.org/license/MIT>.
|
||||
|
||||
*/
|
||||
39
src/arl/lib/sv.h
Normal file
39
src/arl/lib/sv.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* sv.h: String Views
|
||||
* Created: 2026-01-22
|
||||
* Author: Aryadev Chavali
|
||||
* License: See end of file
|
||||
* Commentary: Absolute bajoding
|
||||
*/
|
||||
|
||||
#ifndef SV_H
|
||||
#define SV_H
|
||||
|
||||
#include <arl/lib/base.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *data;
|
||||
u64 size;
|
||||
} sv_t;
|
||||
|
||||
#define SV(PTR, SIZE) ((sv_t){.data = (PTR), .size = (SIZE)})
|
||||
#define PR_SV "%.*s"
|
||||
#define SV_FMT(SV) (int)((SV).size), (SV).data
|
||||
sv_t sv_chop_left(sv_t sv, u64 len);
|
||||
sv_t sv_chop_right(sv_t sv, u64 len);
|
||||
u64 sv_while(const sv_t sv, const char *expected);
|
||||
u64 sv_till(const sv_t sv, const char *expected);
|
||||
|
||||
#endif
|
||||
|
||||
/* Copyright (C) 2026 Aryadev Chavali
|
||||
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the MIT License for details.
|
||||
|
||||
* You may distribute and modify this code under the terms of the MIT License,
|
||||
* which you should have received a copy of along with this program. If not,
|
||||
* please go to <https://opensource.org/license/MIT>.
|
||||
|
||||
*/
|
||||
111
src/arl/lib/vec.c
Normal file
111
src/arl/lib/vec.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/* vec.c: Vector implementation
|
||||
* Created: 2026-01-22
|
||||
* Author: Aryadev Chavali
|
||||
* License: See end of file
|
||||
* Commentary:
|
||||
|
||||
Taken from prick_vec.h: see https://github.com/oreodave/prick.
|
||||
*/
|
||||
|
||||
#include <arl/lib/base.h>
|
||||
#include <arl/lib/vec.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void vec_append(vec_t *vec, const void *const ptr, u64 size)
|
||||
{
|
||||
if (!vec || !ptr || !size)
|
||||
return;
|
||||
vec_ensure_free(vec, size);
|
||||
memcpy(&VEC_GET(vec, vec->size, u8), ptr, size);
|
||||
vec->size += size;
|
||||
}
|
||||
|
||||
void vec_append_byte(vec_t *vec, u8 byte)
|
||||
{
|
||||
if (!vec)
|
||||
return;
|
||||
vec_ensure_free(vec, 1);
|
||||
VEC_GET(vec, vec->size, u8) = byte;
|
||||
++vec->size;
|
||||
}
|
||||
|
||||
void *vec_data(vec_t *vec)
|
||||
{
|
||||
if (!vec)
|
||||
return NULL;
|
||||
|
||||
if (vec->not_inlined)
|
||||
{
|
||||
return vec->ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return vec->inlined;
|
||||
}
|
||||
}
|
||||
|
||||
void vec_ensure_capacity(vec_t *vec, u64 capacity)
|
||||
{
|
||||
if (!vec)
|
||||
return;
|
||||
if (vec->capacity == 0)
|
||||
vec->capacity = VEC_INLINE_CAPACITY;
|
||||
if (vec->capacity < capacity)
|
||||
{
|
||||
vec->capacity = MAX(vec->capacity * VEC_MULT, capacity);
|
||||
if (!vec->not_inlined)
|
||||
{
|
||||
// We were a small buffer, and now we cannot be i.e. we need to allocate
|
||||
// on the heap.
|
||||
vec->not_inlined = 1;
|
||||
void *buffer = calloc(1, vec->capacity);
|
||||
memcpy(buffer, vec->inlined, vec->size);
|
||||
memset(vec->inlined, 0, sizeof(vec->inlined));
|
||||
vec->ptr = buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're already on the heap, just reallocate.
|
||||
vec->ptr = realloc(vec->ptr, vec->capacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vec_ensure_free(vec_t *vec, u64 size)
|
||||
{
|
||||
if (!vec)
|
||||
return;
|
||||
vec_ensure_capacity(vec, vec->size + size);
|
||||
}
|
||||
|
||||
void vec_free(vec_t *vec)
|
||||
{
|
||||
if (!vec)
|
||||
return;
|
||||
if (vec->not_inlined)
|
||||
free(vec->ptr);
|
||||
memset(vec, 1, sizeof(*vec));
|
||||
}
|
||||
|
||||
void vec_clone(vec_t *v2, vec_t *v1)
|
||||
{
|
||||
if (!v1 || !v2)
|
||||
return;
|
||||
vec_append(v2, vec_data(v1), v1->size);
|
||||
}
|
||||
|
||||
#undef MAX
|
||||
|
||||
/* Copyright (C) 2026 Aryadev Chavali
|
||||
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the MIT License for details.
|
||||
|
||||
* You may distribute and modify this code under the terms of the MIT License,
|
||||
* which you should have received a copy of along with this program. If not,
|
||||
* please go to <https://opensource.org/license/MIT>.
|
||||
|
||||
*/
|
||||
55
src/arl/lib/vec.h
Normal file
55
src/arl/lib/vec.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* vec.h: A dynamically sized array with SBO.
|
||||
* Created: 2026-01-22
|
||||
* Author: Aryadev Chavali
|
||||
* License: See end of file
|
||||
* Commentary:
|
||||
|
||||
Taken from prick_vec.h: see https://github.com/oreodave/prick.
|
||||
*/
|
||||
|
||||
#ifndef VEC_H
|
||||
#define VEC_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <arl/lib/base.h>
|
||||
|
||||
#define VEC_INLINE_CAPACITY 32
|
||||
#define VEC_MULT 2
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u64 size, capacity;
|
||||
u8 not_inlined;
|
||||
union
|
||||
{
|
||||
void *ptr;
|
||||
alignas(max_align_t) u8 inlined[VEC_INLINE_CAPACITY];
|
||||
};
|
||||
} vec_t;
|
||||
static_assert(sizeof(vec_t) == 64, "Expected sizeof(vec_t) to be 64");
|
||||
|
||||
void vec_append(vec_t *vec, const void *const ptr, u64 size);
|
||||
void vec_append_byte(vec_t *vec, u8 byte);
|
||||
void *vec_data(vec_t *vec);
|
||||
void vec_ensure_capacity(vec_t *vec, u64 capacity);
|
||||
void vec_ensure_free(vec_t *vec, u64 size);
|
||||
void vec_free(vec_t *vec);
|
||||
void vec_clone(vec_t *v2, vec_t *v1);
|
||||
|
||||
#define VEC_GET(VEC, INDEX, TYPE) (((TYPE *)vec_data(VEC))[INDEX])
|
||||
|
||||
#endif
|
||||
|
||||
/* Copyright (C) 2026 Aryadev Chavali
|
||||
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the Unlicense for details.
|
||||
|
||||
* You may distribute and modify this code under the terms of the Unlicense,
|
||||
* which you should have received a copy of along with this program. If not,
|
||||
* please go to <https://unlicense.org/>.
|
||||
|
||||
*/
|
||||
75
src/arl/main.c
Normal file
75
src/arl/main.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/* main.cpp:
|
||||
* Created: 2026-01-22
|
||||
* Author: Aryadev Chavali
|
||||
* License: See end of file
|
||||
* Commentary:
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arl/lib/base.h>
|
||||
#include <arl/lib/sv.h>
|
||||
#include <arl/lib/vec.h>
|
||||
#include <arl/parser/parser.h>
|
||||
|
||||
/// Parser
|
||||
sv_t read_file(const char *filename)
|
||||
{
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
if (!fp)
|
||||
FAIL("File `%s` does not exist\n", filename);
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
long size = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
char *buffer = calloc(1, size + 1);
|
||||
fread(buffer, size, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
buffer[size] = '\0';
|
||||
return SV(buffer, size);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const char *filename = "./examples/hello-world.arl";
|
||||
sv_t contents = read_file(filename);
|
||||
printf("%s => " PR_SV "\n", filename, SV_FMT(contents));
|
||||
|
||||
parse_stream_t stream = {.line = 1, .column = 0, .contents = contents};
|
||||
ast_t ast = {0};
|
||||
parse_err_t perr = parse(&ast, &stream);
|
||||
if (perr)
|
||||
{
|
||||
fprintf(stderr, "%s:%lu:%lu: %s\n", filename, stream.line, stream.column,
|
||||
parse_err_to_string(perr));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
free(contents.data);
|
||||
ast_free(&ast);
|
||||
return 0;
|
||||
fail:
|
||||
if (contents.data)
|
||||
free(contents.data);
|
||||
if (ast.objects.capacity > 0)
|
||||
ast_free(&ast);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copyright (C) 2026 Aryadev Chavali
|
||||
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the MIT License for details.
|
||||
|
||||
* You may distribute and modify this code under the terms of the MIT License,
|
||||
* which you should have received a copy of along with this program. If not,
|
||||
* please go to <https://opensource.org/license/MIT>.
|
||||
|
||||
*/
|
||||
46
src/arl/parser/ast.c
Normal file
46
src/arl/parser/ast.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/* ast.c: Implementation of AST constructor/destructor functions
|
||||
* Created: 2026-01-22
|
||||
* Author: Aryadev Chavali
|
||||
* License: See end of file
|
||||
* Commentary: See ast.h.
|
||||
*/
|
||||
|
||||
#include <arl/parser/ast.h>
|
||||
|
||||
obj_t obj_string(u64 line, u64 col, sv_t string)
|
||||
{
|
||||
return (obj_t){
|
||||
.line = line,
|
||||
.column = col,
|
||||
.type = TYPE_STRING,
|
||||
.value = {string},
|
||||
};
|
||||
}
|
||||
|
||||
obj_t obj_symbol(u64 line, u64 col, sv_t symbol)
|
||||
{
|
||||
return (obj_t){
|
||||
.line = line,
|
||||
.column = col,
|
||||
.type = TYPE_SYMBOL,
|
||||
.value = {symbol},
|
||||
};
|
||||
}
|
||||
|
||||
void ast_free(ast_t *ast)
|
||||
{
|
||||
// we can free the vector itself and we're done
|
||||
vec_free(&ast->objects);
|
||||
}
|
||||
|
||||
/* Copyright (C) 2026 Aryadev Chavali
|
||||
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the MIT License for details.
|
||||
|
||||
* You may distribute and modify this code under the terms of the MIT License,
|
||||
* which you should have received a copy of along with this program. If not,
|
||||
* please go to <https://opensource.org/license/MIT>.
|
||||
|
||||
*/
|
||||
57
src/arl/parser/ast.h
Normal file
57
src/arl/parser/ast.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* ast.h: General definition of the AST and objects within it.
|
||||
* Created: 2026-01-22
|
||||
* Author: Aryadev Chavali
|
||||
* License: See end of file
|
||||
* Commentary:
|
||||
*/
|
||||
|
||||
#ifndef AST_H
|
||||
#define AST_H
|
||||
|
||||
#include <arl/lib/base.h>
|
||||
#include <arl/lib/sv.h>
|
||||
#include <arl/lib/vec.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TYPE_SYMBOL,
|
||||
TYPE_STRING,
|
||||
} type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u64 line, column;
|
||||
|
||||
type_t type;
|
||||
union
|
||||
{
|
||||
sv_t as_string;
|
||||
sv_t as_symbol;
|
||||
} value;
|
||||
} obj_t;
|
||||
|
||||
obj_t obj_string(u64 line, u64 col, sv_t string);
|
||||
obj_t obj_symbol(u64 line, u64 col, sv_t symbol);
|
||||
|
||||
// Our AST is simply a vector of objects. Nesting and tree like structure is
|
||||
// imposed by individual objects.
|
||||
typedef struct
|
||||
{
|
||||
vec_t objects;
|
||||
} ast_t;
|
||||
|
||||
void ast_free(ast_t *ast);
|
||||
|
||||
#endif
|
||||
|
||||
/* Copyright (C) 2026 Aryadev Chavali
|
||||
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the MIT License for details.
|
||||
|
||||
* You may distribute and modify this code under the terms of the MIT License,
|
||||
* which you should have received a copy of along with this program. If not,
|
||||
* please go to <https://opensource.org/license/MIT>.
|
||||
|
||||
*/
|
||||
153
src/arl/parser/parser.c
Normal file
153
src/arl/parser/parser.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/* parser.c: Implementation of parser.
|
||||
* Created: 2026-01-22
|
||||
* Author: Aryadev Chavali
|
||||
* License: See end of file
|
||||
* Commentary: See parser.h
|
||||
*/
|
||||
|
||||
#include "arl/lib/sv.h"
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arl/parser/parser.h>
|
||||
|
||||
/// Expected characters in a symbol
|
||||
static const char *SYMBOL_CHARS =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&'()*+,-./"
|
||||
":;<=>?@\\^_`{|}~0123456789";
|
||||
|
||||
const char *parse_err_to_string(parse_err_t err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case PARSE_ERR_OK:
|
||||
return "OK";
|
||||
case PARSE_ERR_UNEXPECTED_EOF:
|
||||
return "UNEXPECTED_EOF";
|
||||
case PARSE_ERR_EXPECTED_SPEECH_MARKS:
|
||||
return "EXPECTED_SPEECH_MARKS";
|
||||
case PARSE_ERR_UNKNOWN_CHAR:
|
||||
return "UNKNOWN_CHAR";
|
||||
default:
|
||||
FAIL("Unexpected value for parse_err_t: %d\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
bool stream_eos(parse_stream_t *stream)
|
||||
{
|
||||
return stream->cursor >= stream->contents.size;
|
||||
}
|
||||
|
||||
char stream_peek(parse_stream_t *stream)
|
||||
{
|
||||
if (stream_eos(stream))
|
||||
return '\0';
|
||||
else
|
||||
return stream->contents.data[stream->cursor];
|
||||
}
|
||||
|
||||
void stream_advance(parse_stream_t *stream, u64 size)
|
||||
{
|
||||
if (stream->cursor + size >= stream->contents.size)
|
||||
stream->cursor = stream->contents.size;
|
||||
else
|
||||
{
|
||||
for (u64 i = 0; i < size; ++i)
|
||||
{
|
||||
++stream->cursor;
|
||||
if (stream_peek(stream) == '\n')
|
||||
{
|
||||
stream->line++;
|
||||
stream->column = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream->column++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u64 stream_size(parse_stream_t *stream)
|
||||
{
|
||||
return stream->contents.size;
|
||||
}
|
||||
|
||||
parse_err_t parse_string(parse_stream_t *stream, obj_t *ret)
|
||||
{
|
||||
// Increment the cursor just past the first speechmark
|
||||
stream_advance(stream, 1);
|
||||
sv_t current_contents = sv_chop_left(stream->contents, stream->cursor);
|
||||
u64 string_size = sv_till(current_contents, "\"");
|
||||
if (string_size + stream->cursor == stream_size(stream))
|
||||
return PARSE_ERR_EXPECTED_SPEECH_MARKS;
|
||||
// Bounds of string are well defined, generate an object and advance the
|
||||
// stream
|
||||
*ret = obj_string(stream->line, stream->column - 1,
|
||||
SV(current_contents.data, string_size));
|
||||
stream_advance(stream, string_size + 1);
|
||||
return PARSE_ERR_OK;
|
||||
}
|
||||
|
||||
parse_err_t parse_symbol(parse_stream_t *stream, obj_t *ret)
|
||||
{
|
||||
sv_t current_contents = sv_chop_left(stream->contents, stream->cursor);
|
||||
u64 symbol_size = sv_while(current_contents, SYMBOL_CHARS);
|
||||
// Generate symbol
|
||||
*ret = obj_symbol(stream->line, stream->column,
|
||||
SV(current_contents.data, symbol_size));
|
||||
stream_advance(stream, symbol_size);
|
||||
return PARSE_ERR_OK;
|
||||
}
|
||||
|
||||
parse_err_t parse(ast_t *out, parse_stream_t *stream)
|
||||
{
|
||||
while (!stream_eos(stream))
|
||||
{
|
||||
char cur = stream_peek(stream);
|
||||
if (isspace(cur))
|
||||
{
|
||||
while (isspace(cur) && !stream_eos(stream))
|
||||
{
|
||||
stream_advance(stream, 1);
|
||||
cur = stream_peek(stream);
|
||||
}
|
||||
}
|
||||
else if (cur == '"')
|
||||
{
|
||||
// we make a copy for parse_string to mess with
|
||||
obj_t ret = {0};
|
||||
parse_err_t perr = parse_string(stream, &ret);
|
||||
if (perr)
|
||||
return perr;
|
||||
vec_append(&out->objects, &ret, sizeof(ret));
|
||||
}
|
||||
else if (strchr(SYMBOL_CHARS, cur) && !isdigit(cur))
|
||||
{
|
||||
// we make a copy for parse_symbol to mess with
|
||||
obj_t ret = {0};
|
||||
parse_err_t perr = parse_symbol(stream, &ret);
|
||||
if (perr)
|
||||
return perr;
|
||||
|
||||
vec_append(&out->objects, &ret, sizeof(ret));
|
||||
}
|
||||
else
|
||||
{
|
||||
return PARSE_ERR_UNKNOWN_CHAR;
|
||||
}
|
||||
}
|
||||
return PARSE_ERR_OK;
|
||||
}
|
||||
|
||||
/* Copyright (C) 2026 Aryadev Chavali
|
||||
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the MIT License for details.
|
||||
|
||||
* You may distribute and modify this code under the terms of the MIT License,
|
||||
* which you should have received a copy of along with this program. If not,
|
||||
* please go to <https://opensource.org/license/MIT>.
|
||||
|
||||
*/
|
||||
42
src/arl/parser/parser.h
Normal file
42
src/arl/parser/parser.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* parser.h: Parser which takes character buffers and yields an AST
|
||||
* Created: 2026-01-22
|
||||
* Author: Aryadev Chavali
|
||||
* License: See end of file
|
||||
* Commentary:
|
||||
*/
|
||||
|
||||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
|
||||
#include <arl/parser/ast.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PARSE_ERR_OK = 0,
|
||||
PARSE_ERR_UNEXPECTED_EOF,
|
||||
PARSE_ERR_EXPECTED_SPEECH_MARKS,
|
||||
PARSE_ERR_UNKNOWN_CHAR,
|
||||
} parse_err_t;
|
||||
const char *parse_err_to_string(parse_err_t err);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u64 line, column, cursor;
|
||||
sv_t contents;
|
||||
} parse_stream_t;
|
||||
|
||||
parse_err_t parse(ast_t *out, parse_stream_t *stream);
|
||||
|
||||
#endif
|
||||
|
||||
/* Copyright (C) 2026 Aryadev Chavali
|
||||
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the MIT License for details.
|
||||
|
||||
* You may distribute and modify this code under the terms of the MIT License,
|
||||
* which you should have received a copy of along with this program. If not,
|
||||
* please go to <https://opensource.org/license/MIT>.
|
||||
|
||||
*/
|
||||
Reference in New Issue
Block a user