interpret/src/interpret.re_c.c

186 lines
5.7 KiB
C
Raw Normal View History

2022-02-10 23:30:11 -05:00
/** @license 2022 Neil Edelman, distributed under the terms of the
[MIT License](https://opensource.org/licenses/MIT).
Lexer for journal entries.
@std C89/90 */
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <errno.h>
/* This defines `enum condition`. */
/*!types:re2c*/
enum symbol { END, TEXT, BANG, WHITE, MAP };
/** scanner reads a file and extracts semantic information. Valid to access
only while underlying pointers do not change. */
struct scanner {
/* `re2c` variables; these point directly into `buffer`. */
const char *marker, *ctx_marker, *from, *cursor;
/* Weird `c2re` stuff: these fields have to come after when >5? */
const char *label, *buffer, *s0, *s1;
enum condition condition;
enum symbol symbol;
size_t line;
int ws_before;
};
/*!re2c
re2c:yyfill:enable = 0;
re2c:flags:tags = 1;
re2c:define:YYCTYPE = char;
re2c:define:YYCURSOR = s->cursor;
re2c:define:YYMARKER = s->marker;
re2c:define:YYCTXMARKER = s->ctx_marker;
re2c:define:YYCONDTYPE = 'condition';
re2c:define:YYGETCONDITION = 's->condition';
re2c:define:YYGETCONDITION:naked = 1;
re2c:define:YYSETCONDITION = 's->condition = @@;';
re2c:define:YYSETCONDITION:naked = 1;
// Eof is marked by null when preparing files for lexing.
// Mutually exclusive; only !, [, are not covered.
end = "\x00";
newline = "\n" | "\r" "\n"?;
ws = [ \t\v\f];
glyph = [^ \t\n\r\v\f![\x00];
glyphs = glyph+;
// inside the block
decimal = [1-9][0-9]*;
number = ([1-9][0-9]* | [0])? "." [0-9]+ | [1-9][0-9]* | [0];
id = [a-zA-Z_][a-zA-Z_\-0-9]{0,63};
*/
static int lex(struct scanner *const s) {
const char *s0, *s1;
/*!stags:re2c format = 'const char *@@;\n'; */
s->ws_before = 0;
scan:
/*!re2c
<text> end { return s->symbol = END, 1; }
// fixme: paragraphs.
<text> newline { s->line++; s->ws_before = 1; goto scan; }
<text> ws+ { s->ws_before = 1; goto scan; }
<text> @s0 glyph+ @s1 { s->s0 = s0, s->s1 = s1;
return s->symbol = TEXT, 1; }
<text> @s0 "!" @s1 { s->s0 = s0, s->s1 = s1;
return s->symbol = BANG, 1; }
<text> "![" :=> image
<text> "[" :=> command
<image> * { return 0; }
<image> ws* "osm" ws* "](geo:" @s0 number "," @s1 number ")" {
s->condition = yyctext;
s->s0 = s0, s->s1 = s1;
printf("Got a map.\n");
return 1;
}
<command> * { return 0; }
*/
}
2022-02-11 03:28:28 -05:00
/*#define POOL_NAME char
#define POOL_TYPE char
#include "../src/pool.h"*/
2022-02-10 23:30:11 -05:00
2022-02-11 03:28:28 -05:00
struct year_listlink;
static int year_link_compare(const struct year_listlink *,
const struct year_listlink *);
static void yearlist_to_string(const struct year_listlink *, char (*)[12]);
#define LIST_NAME year
#define LIST_EXPECT_TRAIT
#include "../src/list.h"
#define LIST_COMPARE &year_link_compare
#define LIST_EXPECT_TRAIT
#include "../src/list.h"
#define LIST_TO_STRING &yearlist_to_string
#include "../src/list.h"
struct year {
struct year_listlink link;
int year;
char as_string[8];
};
static const size_t year_string_size = sizeof ((struct year *)0)->as_string;
static int year_link_compare(const struct year_listlink *const al,
const struct year_listlink *const bl) {
const struct year *const a = (const struct year *)al,
*const b = (const struct year *)bl;
return (b->year < a->year) - (a->year < b->year);
2022-02-10 23:30:11 -05:00
}
2022-02-11 03:28:28 -05:00
#define POOL_NAME year
#define POOL_TYPE struct year
#include "../src/pool.h"
static unsigned hash_year(const struct year *const year)
{ return (unsigned)(year->year - INT_MIN); }
static int year_is_equal(const struct year *const a, const struct year *const b)
{ return a->year == b->year; }
static void year_to_string(const struct year *const y, char (*const a)[12])
{ strncpy(*a, y->as_string, sizeof(*a) - 1), (*a)[sizeof(*a) - 1] = '\0'; }
static void yearlist_to_string(const struct year_listlink *const y,
char (*const a)[12]) { year_to_string((const struct year *)y, a); }
#define TABLE_NAME year
#define TABLE_KEY struct year *
#define TABLE_UINT unsigned
#define TABLE_HASH &hash_year
#define TABLE_IS_EQUAL &year_is_equal
#define TABLE_EXPECT_TRAIT
#include "../src/table.h"
#define TABLE_DEFAULT 0
#define TABLE_EXPECT_TRAIT
#include "../src/table.h"
#define TABLE_TO_STRING &year_to_string
#include "../src/table.h"
2022-02-10 23:30:11 -05:00
2022-02-11 03:28:28 -05:00
#include <unistd.h> /* chdir (POSIX) */
#include <sys/types.h> /* mode_t (POSIX) */
#include <sys/stat.h> /* umask (POSIX) */
#include <dirent.h> /* opendir readdir closedir */
#include <limits.h>
2022-02-10 23:30:11 -05:00
int main(int argc, char **argv) {
int success = EXIT_FAILURE;
2022-02-11 03:28:28 -05:00
DIR *year_dir;
struct dirent *year_de;
struct year_pool year_pool = POOL_IDLE;
struct year_list order;
struct year_table years = TABLE_IDLE;
/* Get the years list. fixme: this is way overkill; `int_array`. */
errno = 0;
year_list_clear(&order);
2022-02-10 23:30:11 -05:00
if(argc != 2) { fprintf(stderr, "Needs journal location.\n"
"(should contain <year>/<month>/<day>.txt)\n"); goto finally; }
2022-02-11 03:28:28 -05:00
if(chdir(argv[1]) == -1 || !(year_dir = opendir("."))) goto catch;
while((year_de = readdir(year_dir))) {
struct stat st;
char *const start = year_de->d_name, *end;
long year = strtol(start, &end, 0); /* Need better. */
struct year *y;
if(errno || *end != '\0' || (size_t)(end - start) >= year_string_size
|| year < INT_MIN || year > INT_MAX)
{ /*fprintf(stderr, "%s: doesn't look like a year.\n",
year_de->d_name);*/ errno = 0; continue; }
if(stat(year_de->d_name, &st)) goto catch;
if(!S_ISDIR(st.st_mode)) { /*fprintf(stderr,
"%s: isn't a directory.\n", year_de->d_name);*/ continue; }
if(!(y = year_pool_new(&year_pool))) goto catch;
y->year = (int)year;
strcpy(y->as_string, year_de->d_name);
year_list_push(&order, &y->link);
}
year_list_sort(&order);
fprintf(stderr, "Years: %s\n", year_list_to_string(&order));
2022-02-10 23:30:11 -05:00
2022-02-11 03:28:28 -05:00
/* Go though each of the years, in order, and extract meta-information. */
2022-02-10 23:30:11 -05:00
{ success = EXIT_SUCCESS; goto finally; }
catch:
perror("interpret");
finally:
2022-02-11 03:28:28 -05:00
year_table_(&years);
year_pool_(&year_pool);
2022-02-10 23:30:11 -05:00
return EXIT_FAILURE;
}