interpret/src/scan_flight.re.c

172 lines
5.2 KiB
C

/** @license 2022 Neil Edelman, distributed under the terms of the
[MIT License](https://opensource.org/licenses/MIT).
Scan journal entries for kjv references. */
#include "../src/journal.h"
#include "../src/helper.h"
#include <inttypes.h> /* C99 */
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <limits.h>
struct substring { const char *str; int len; };
/** type, reg, launch, how, height, landing, pilot_min, dual_min, instr_min,
remarks */
struct glider {
struct substring type, reg, launch;
enum launch how;
unsigned height_ft, pilot_min, dual_min, instr_min;
struct substring remarks;
};
/** type, reg, launch -- landing, pilot, copilot, dual_min, pilot_min,
ifrsim_min, ifr_min, remarks */
struct power {
struct substring type, reg, launch, landing, pilot, copilot;
unsigned dual_min, pilot_min, ifrsim_min, ifr_min;
struct substring remarks;
};
/** Could be a glider or power. */
struct flight {
enum { GLIDER, POWER } type;
union { struct glider glider; struct power power; };
};
struct flights {
};
/*!conditions:re2c*/
static int scan(union date32 date, const char *const buffer,
struct flights *const f) {
const char *YYCURSOR, *YYMARKER, *yyt1, *yyt2, *yyt3, *s0, *s1, *t0, *t1;
enum flight_type type = Glider;
uint32_t chapter = 0, verse = 0, verse_end = 0;
enum YYCONDTYPE condition = yycline;
size_t line = 1;
char datestr[12] = {0};
const char *why = "unexpected";
assert(buffer && kj);
YYCURSOR = YYMARKER = yyt1 = buffer;
/*!re2c /**/
re2c:define:YYCTYPE = char;
re2c:yyfill:enable = 0;
re2c:define:YYGETCONDITION = "condition";
re2c:define:YYSETCONDITION = "condition = @@;";
re2c:define:YYGETCONDITION:naked = 1;
re2c:define:YYSETCONDITION:naked = 1;
unix_control = [\x01-\x08\x0b-\x1f\x7f];
ws = [ \t];
glyph = [^] \ ("\x00" | "\n" | unix_control | ws);
natural = [1-9][0-9]*;
lookat = ws* natural ":" natural [ab]? ("-" natural [ab]?)? engage;
*/
for( ; ; ) { /*!re2c /**/
<skip> [^\n\x00] { continue; }
<skip> "\x00" { why = "no newline at end of file"; goto catch; }
<skip> "\n" => line { line++; continue; }
<line> "\x00" { return 1; }
<line> "\n" { line++; continue; }
<line> * :=> skip /* Guess it can't be simplified? */
<line> "[glider]" :=> glider
<line> "[flight]" :=> flight
/* "M" - Motor Car Tow
"W" - Winch
"A" - Aero Tow */
/* type; registration; launch -- landing; pic; sic;
single engine day dual; pilot; instrument simulated; actual; remarks */
<book> * { why = "default unrecognized"; goto catch; }
/* 19:15a, just ignore the a. */
<book> ws+ @s0 natural @s1 ":" @t0 natural @t1 [ab]? {
if(chapter || verse || verse_end)
{ why = "reference unrecognized"; goto catch; }
if(!helper_natural(s0, s1, &chapter)
|| !helper_natural(t0, t1, &verse))
{ why = "reference numerical error"; goto catch; }
continue;
}
<book> "-" @s0 natural @s1 [ab]? { /* Verse range. */
if(!chapter || !verse || verse_end)
{ why = "range unrecognized"; goto catch; }
if(!helper_natural(s0, s1, &verse_end))
{ why = "range numerical error"; goto catch; }
continue;
}
<book> engage => skip {
char citestr[12];
if(!chapter || !verse) { why = "missing information"; goto catch; }
if(verse_end && verse_end <= verse)
{ why = "interval error"; goto catch; }
union kjvcite cite
= { .book = book, .chapter = chapter, .verse = verse };
if(!datestr[0]) date32_to_string(date, &datestr); /* Only once. */
kjvcite_to_string(cite, &citestr);
for( ; ; verse++, cite.verse++) {
if(!kjv_add(kj, cite)) { why = "add to set"; goto catch; }
if(!verse_end || verse_end <= verse) break;
}
printf("%s\t%zu\t%zu\t%zu\t# ",
datestr, kj->words.verse, kj->words.set, kj->words.cumulative);
if(verse_end) {
printf("%s-%" PRIu32 "\n", citestr, verse_end);
} else {
printf("%s\n", citestr);
}
book = Revelation, chapter = 0, verse = 0, verse_end = 0;
continue;
}
*/ }
assert(0); /* Never gets here. */
catch:
if(!errno) errno = EILSEQ;
date32_to_string(date, &datestr);
fprintf(stderr, "%s\n"
"%s line %zu: %s.\n", buffer, datestr, line, why);
return 0;
}
int main(void) {
int success = EXIT_SUCCESS;
struct journal j;
struct journal_iterator it;
struct kjv kj = kjv();
union date32 k;
union load *v;
size_t i;
j = journal();
if(!journal_is_valid(&j)) goto catch;
fprintf(stderr, "Journal: %s.\n", journal_to_string(&j));
printf("set term postscript eps enhanced\n"
"set output \"kjv.eps\"\n"
"$Data <<EOD\n"
"# date\tverse\tset\tcumulative / %zu\n", kj.words.total);
it = journal_begin(&j), i = 0; while(journal_next(&it, &k, &v))
if(!scan(k, v->text, &kj)) goto catch;
printf("EOD\n"
"set monochrome\n"
"set xdata time\n"
"set timefmt \"%%Y-%%m-%%d\"\n"
"set xtics format \"%%Y-%%m-%%d\" rotate by -30\n"
"set ylabel \"words in KJV\"\n"
"set format y \"%%g%%%%\"\n"
"set key top left\n"
"set grid\n"
"unset border\n"
"#set style fill solid 0.1 #pattern 5 (better, but restarts)\n"
"plot $Data using 1:($3)*100/%zu with fillsteps lw 2 title \"set\", \\\n"
"$Data using 1:($4)*100/%zu with steps lw 1 title \"cumulative\"\n",
kj.words.total, kj.words.total);
goto finally;
catch:
success = EXIT_FAILURE;
perror("journal");
finally:
journal_(&j);
return success;
}