M README.md +5 -4
@@ 14,12 14,10 @@ LAAL is a simple syntax for expressing p
- [ ] Stage 1: bootstrap
- [x] A. LibLAAL parser in C99
- - [ ] B. LibLAAG code generator in C99
- - [ ] C. Systems LAAL in C99
+ - [ ] B. Systems LAAL in C99 emitting C
- [ ] Stage 2: self-hosted
- [ ] A. LibLAAL parser in Systems LAAL
- - [ ] B. LibLAAG code generator in Systems LAAL
- - [ ] C. Systems LAAL in itself
+ - [ ] B. Systems LAAL in itself
- [ ] Stage 3: scripting implementation
- [ ] A. LibLAARS scripting runtime/VM in Systems LAAL
- [ ] B. Scripting LAAL in Systems LAAL
@@ 27,6 25,9 @@ LAAL is a simple syntax for expressing p
- [ ] A. LAAB build system (supersceding Muon for building LAAL)
- [ ] B. LAAD markup (supersceding POD for docs)
- [ ] C. LibTAAL editor tooling (supersceding handwritten tooling for LAAL)
+- [ ] Unknown
+ - [ ] LibLAAG code generator (possible backends: QBE, C, WASM)
+ - Postponed until further understanding is gained and Systems LAAL is self-hosted
## Requirements
M include/laal.h +5 -2
@@ 35,6 35,7 @@ extern "C"
} laal_position_t;
extern const laal_position_t LAAL_DEFAULT_POSITION;
+ extern const laal_position_t LAAL_INVALID_POSITION;
__LAAL_PURE
bool laal_position_equal (laal_position_t x, laal_position_t y);
@@ 81,12 82,14 @@ extern "C"
/// Parse a LAAL source file into a laal_value (always of type LAAL_MAP)
__LAAL_MUST_USE
- laal_error_t laal_parse_file (FILE *stream, laal_value_t *result);
+ laal_error_t laal_parse_file (FILE *stream, laal_value_t *result,
+ laal_position_t *error_pos);
/// Parse LAAL source from a given string, make sure there is a null
/// terminator!
__LAAL_MUST_USE
- laal_error_t laal_parse_string (const char *string, laal_value_t *result);
+ laal_error_t laal_parse_string (const char *string, laal_value_t *result,
+ laal_position_t *error_pos);
/// Output the LAAL source representation of a given value to a file
/// This consumes the value, so it should be copied beforehand if needed
M include/meson.build +1 -1
@@ 21,4 21,4 @@ configure_file(input : 'laal_config.h.in
configuration : config)
include = include_directories('.')
-install_headers(headers, subdir : 'laal')
+install_headers(headers)
M meson.build +2 -2
@@ 5,9 5,9 @@
#
# Project info
project(
- 'laal',
+ 'liblaal',
['c'],
- version : '0.0.2',
+ version : '0.0.3',
license : 'MPL-2.0',
default_options : [
'c_std=c99',
M src/laal.c +43 -6
@@ 40,6 40,11 @@ const laal_position_t LAAL_DEFAULT_POSIT
.col = 0,
};
+const laal_position_t LAAL_INVALID_POSITION = {
+ .row = UINTPTR_MAX,
+ .col = UINTPTR_MAX,
+};
+
bool
laal_position_equal (laal_position_t x, laal_position_t y)
{
@@ 269,30 274,62 @@ laal_value_compare (const laal_value_t x
}
laal_error_t
-laal_parse_file (FILE *stream, laal_value_t *output)
+laal_parse_file (FILE *stream, laal_value_t *output,
+ laal_position_t *error_pos)
{
laal_tokens_t tokens = laal_tokens_create ();
laal_position_t pos = LAAL_DEFAULT_POSITION;
+ memcpy (error_pos, &LAAL_INVALID_POSITION, sizeof (laal_position_t));
char buffer[LAAL_IO_BUFFER_SIZE];
while (!feof (stream))
{
fgets (buffer, LAAL_IO_BUFFER_SIZE, stream);
- laal_try (laal_lexer_lex, tokens, buffer, &pos);
+
+ laal_error_t res = laal_lexer_lex (tokens, buffer, &pos);
+ if (res != LAAL_SUCCESS)
+ {
+ memcpy (error_pos, &pos, sizeof (laal_position_t));
+ return res;
+ }
}
- laal_try (laal_parse_tokens, output, tokens);
+
+ laal_error_t res = laal_parse_tokens (output, tokens);
+ if (res != LAAL_SUCCESS)
+ {
+ if (laal_tokens_get (tokens) != NULL)
+ memcpy (error_pos, &laal_tokens_get (tokens)->position,
+ sizeof (laal_position_t));
+ return res;
+ }
laal_tokens_destroy (tokens);
return LAAL_SUCCESS;
}
laal_error_t
-laal_parse_string (const char *source, laal_value_t *output)
+laal_parse_string (const char *source, laal_value_t *output,
+ laal_position_t *error_pos)
{
laal_tokens_t tokens = laal_tokens_create ();
laal_position_t pos = LAAL_DEFAULT_POSITION;
- laal_try (laal_lexer_lex, tokens, source, &pos);
- laal_try (laal_parse_tokens, output, tokens);
+ memcpy (error_pos, &LAAL_INVALID_POSITION, sizeof (laal_position_t));
+
+ laal_error_t lex_res = laal_lexer_lex (tokens, source, &pos);
+ if (lex_res != LAAL_SUCCESS)
+ {
+ memcpy (error_pos, &pos, sizeof (laal_position_t));
+ return lex_res;
+ }
+
+ laal_error_t parse_res = laal_parse_tokens (output, tokens);
+ if (parse_res != LAAL_SUCCESS)
+ {
+ if (laal_tokens_get (tokens) != NULL)
+ memcpy (error_pos, &laal_tokens_get (tokens)->position,
+ sizeof (laal_position_t));
+ return parse_res;
+ }
laal_tokens_destroy (tokens);
return LAAL_SUCCESS;
M src/laal_parser.c +1 -1
@@ 109,7 109,7 @@ parse_character (laal_tokens_t tokens, l
// String to print output to
char *out_text = malloc (res_len + 1);
laal_check_alloc (out_text);
- sprintf (out_text, "%d", data);
+ snprintf (out_text, res_len, "%d", data);
*output = laal_value_from (out_text, LAAL_NUMBER, token->position);
laal_check_alloc (*output);
M test/interface.c +23 -4
@@ 7,6 7,7 @@
#include <laal.h>
#include <laal_lexer.h>
#include <laal_parser.h>
+#include <string.h>
static void
ensure_correct (const char *programme, const laal_value_t output)
@@ 44,10 45,13 @@ TEST ("Parse String")
{
const char *programme = "greeting := string \"Hello, world!\";";
laal_value_t res = NULL;
- laal_error_t err = laal_parse_string (programme, &res);
+ laal_position_t err_pos = LAAL_INVALID_POSITION;
+ laal_error_t err = laal_parse_string (programme, &res, &err_pos);
if (err != LAAL_SUCCESS)
{
fprintf (stderr, "\nError code: %d", err);
+ if (memcmp (&err_pos, &LAAL_INVALID_POSITION, sizeof (laal_position_t)))
+ fprintf (stderr, "\nAt position: (%lu,%lu)", err_pos.row, err_pos.col);
TEST_FAIL ("Parsing error while parsing string")
}
@@ 66,12 70,15 @@ TEST ("Parse File")
rewind (src);
laal_value_t res = NULL;
- laal_error_t err = laal_parse_file (src, &res);
+ laal_position_t err_pos = LAAL_DEFAULT_POSITION;
+ laal_error_t err = laal_parse_file (src, &res, &err_pos);
fclose (src);
if (err != LAAL_SUCCESS)
{
fprintf (stderr, "\nError code: %d", err);
+ if (memcmp (&err_pos, &LAAL_INVALID_POSITION, sizeof (laal_position_t)))
+ fprintf (stderr, "\nAt position: (%lu,%lu)", err_pos.row, err_pos.col);
TEST_FAIL ("Parsing error while parsing from file")
}
@@ 85,10 92,16 @@ TEST ("Write File")
= "@<A simple greeting@>\n"
"greeting := format \"Hello, ${who}!\" {who := \"world\"};";
laal_value_t res_initial = NULL;
- laal_error_t parse_initial_err = laal_parse_string (programme, &res_initial);
+ laal_position_t parse_initial_err_pos = LAAL_INVALID_POSITION;
+ laal_error_t parse_initial_err
+ = laal_parse_string (programme, &res_initial, &parse_initial_err_pos);
if (parse_initial_err != LAAL_SUCCESS)
{
fprintf (stderr, "\nError code: %d", parse_initial_err);
+ if (memcmp (&parse_initial_err_pos, &LAAL_INVALID_POSITION,
+ sizeof (laal_position_t)))
+ fprintf (stderr, "\nAt position: (%lu,%lu)", parse_initial_err_pos.row,
+ parse_initial_err_pos.col);
TEST_FAIL ("Parsing error while parsing initial data")
}
@@ 104,12 117,18 @@ TEST ("Write File")
rewind (out);
laal_value_t res_final = NULL;
- laal_error_t parse_final_err = laal_parse_file (out, &res_final);
+ laal_position_t parse_final_err_pos = LAAL_INVALID_POSITION;
+ laal_error_t parse_final_err
+ = laal_parse_file (out, &res_final, &parse_final_err_pos);
fclose (out);
if (parse_final_err != LAAL_SUCCESS)
{
fprintf (stderr, "\nError code: %d", parse_final_err);
+ if (memcmp (&parse_final_err_pos, &LAAL_INVALID_POSITION,
+ sizeof (laal_position_t)))
+ fprintf (stderr, "\nAt position: (%lu,%lu)", parse_final_err_pos.row,
+ parse_final_err_pos.col);
TEST_FAIL ("Parsing error while parsing generated data")
}