Works with text.

This commit is contained in:
Neil 2023-05-06 18:11:23 -07:00
parent 9c2edcb9eb
commit c096fbf605
2 changed files with 100 additions and 42 deletions

View File

@ -85,7 +85,7 @@ struct scan {
struct source_array array;
struct pairmap_table map;
struct linemap_tree dates;
} sources;
} sources, documents;
struct {
struct place_array array;
struct pairmap_table map;
@ -96,7 +96,6 @@ struct scan {
struct pairmap_table map;
struct linemap_tree dates;
} scores;
struct source_array documents;
struct glider_tree gliders;
struct flight_tree flights;
struct kjv_tree kjvs;

View File

@ -109,6 +109,7 @@ static int scan_day(struct scan *const scan, union date32 date,
size_t line = 1;
char datestr[12] = {0};
const char *fail = "perhaps a bat?";
struct pair *future = 0;
struct score *new_score = 0;
struct glider *new_glider = 0;
struct flight *new_flight = 0;
@ -129,12 +130,18 @@ static int scan_day(struct scan *const scan, union date32 date,
ws = [ \t];
glyph = [^\x00-\x20\x7f] | [\x80-\xff]; // [^\x00\n\t ] + all weird
semitext = glyph \ ";";
labelchar = glyph \ [;]; // perhaps?
label_mbra = labelchar \ [[\]];
label_mpar = labelchar \ [()];
label_in = label_mbra+ (" " label_mbra+)*; // "[label in; ...]"
label_out = (label_mpar labelchar*) (" " labelchar+)*; // "() label out"
semichar = glyph \ ";";
brachar = semichar \ [[\]];
parchar = glyph \ [()];
// label: possibly separated by spaces; used in freestanding last
anylabel = glyph+ (ws+ glyph+)*;
// label except ";"; used in freestanding
semilabel = semichar+ (ws+ semichar+)*;
// label except ";[]"; used in []
bralabel = brachar+ (ws+ brachar+)*;
// label except start "()"; used in location
parlabel = (parchar glyph*) (ws+ glyph+)*;
keyword = [A-Za-z0-9][A-Za-z0-9_-]*;
@ -165,24 +172,33 @@ static int scan_day(struct scan *const scan, union date32 date,
<line> "[flight]" :=> flight_type
<line> "[" :=> bracket
/* ^"[" ... */
<bracket> * { fail = "bracket unrecognized"; goto catch; }
<bracket> "document: " :=> document_title
// "<<\ntext\n>>" or "text\n" used by several.
<text> * { fail = "text"; goto catch; }
<text> ws+ :=> text
<text> glyph+ {
}
<document_title> * { fail = "document title"; goto catch; }
<document_title> @s0 label_in @s1 "]" => text {
const struct pair label = pair(s0, s1);
fprintf(stderr, "document: <<%.*s>>?\n", (int)(s1 - s0), s0);
<document_title> @s0 bralabel @s1 "]" => text_input {
const union line64 key = { { (uint32_t)line, date } };
size_t *pi;
struct source *doc;
fprintf(stderr, "document: <<%.*s>>\n", (int)(s1 - s0), s0);
if(!(doc = source_array_new(&scan->documents.array))) goto catch;
doc->name.a = s0, doc->name.b = s1;
doc->desc.a = 0, doc->desc.b = 0;
assert(!future), future = &doc->desc;
switch(linemap_tree_bulk_assign(&scan->documents.dates, key, &pi)) {
case TREE_PRESENT: fail = "duplicate"; case TREE_ERROR: goto catch;
case TREE_ABSENT:
*pi = (size_t)(doc - scan->documents.array.data); break;
}
fprintf(stderr, "%s[%zu]: new document <<%.*s>> stored at %zu.\n",
datestr, line, (int)(s1 - s0), s0, *pi);
assert(future);
continue;
}
<place> * { fail = "place unrecognized"; goto catch; }
<place> @s0 label_out @s1 / "\n" => skip { also_place: {
<place> @s0 parlabel @s1 / "\n" => skip { also_place: {
const struct pair keyword = pair(s0, s1);
const union line64 key = { { (uint32_t)line, date } };
size_t i, *pi;
@ -200,7 +216,7 @@ static int scan_day(struct scan *const scan, union date32 date,
datestr, line, (int)(s1 - s0), s0);
} continue; }
<place> "(" @t0 decimal "," @t1 decimal ")"
ws+ @s0 label_out @s1 / "\n" => skip {
ws+ @s0 parlabel @s1 / "\n" => skip {
const struct pair keyword = pair(s0, s1);
const double x = strtod(t0, 0), y = strtod(t1, 0); /* Safe? */
size_t *idx;
@ -242,6 +258,7 @@ static int scan_day(struct scan *const scan, union date32 date,
const struct pair keyword = pair(s0, s1);
const union line64 key = { { (uint32_t)line, date } };
size_t i, *pi;
//fixme: verify way before
if(line > UINT32_MAX)
{ errno = ERANGE; fail = "too many lines of text"; goto catch; }
if(!(i = pair_map_table_get(&scan->sources.map, keyword)))
@ -254,6 +271,7 @@ static int scan_day(struct scan *const scan, union date32 date,
datestr, line, (int)(s1 - s0), s0);
} continue; }
/* New source. fixme: desc not set. */
////////
<source> @s0 keyword @s1 ":" [^\x00\n]+ / "\n" => skip {
struct pair keyword = pair(s0, s1);
size_t *idx;
@ -319,20 +337,19 @@ static int scan_day(struct scan *const scan, union date32 date,
goto new_score;
}
<score_name> * { fail = "name unrecognized"; goto catch; }
<score_name> ws* @s0 semitext+ (" " semitext+)* @s1 /* ws* */ ";"
=> score_date {
<score_name> ws* @s0 semilabel @s1 ";" => score_date {
assert(new_score);
new_score->name.a = s0, new_score->name.b = s1;
continue;
}
<score_date> * { fail = "date unrecognized"; goto catch; }
<score_date> ws* "~"? @s0 date ws* ";" => score_edges {
<score_date> ws* "~"? @s0 date ";" => score_edges {
assert(new_score);
if(!pair_to_date(s0, &new_score->date)) goto catch;
continue;
}
<score_edges> * { fail = "edges unrecognized"; goto catch; }
<score_edges> ws* "~"? @s0 uint @s1 ws* / "\n" => skip {
<score_edges> ws* "~"? @s0 uint @s1 / "\n" => skip {
assert(new_score);
if(!pair_to_natural(s0, s1, &new_score->edges)) goto catch;
new_score = 0; /* Done. */
@ -343,7 +360,7 @@ static int scan_day(struct scan *const scan, union date32 date,
/* type, reg, launch, how, height, landing, pilot, dual, instr, remarks
eg, [glider] 2-33A; C-GCLK; CYQQ; A; 2000'; CYQQ; ;:13;; Peters D1 */
<glider_type> * { fail = "glider type"; goto catch; }
<glider_type> ws* @s0 semitext+ @s1 ws* ";" => glider_reg {
<glider_type> ws* @s0 semilabel @s1 ";" => glider_reg {
const union line64 key = {{ (uint32_t)line, date }};
assert(!new_glider);
if(line > UINT32_MAX) { fail = "line overflow"; goto catch; }
@ -355,10 +372,10 @@ static int scan_day(struct scan *const scan, union date32 date,
continue;
}
<glider_reg> * { fail = "glider reg"; goto catch; }
<glider_reg> ws* @s0 semitext+ @s1 ws* ";" => glider_launch
<glider_reg> ws* @s0 semilabel @s1 ";" => glider_launch
{ new_glider->reg.a = s0, new_glider->reg.b = s1; continue; }
<glider_launch> * { fail = "glider launch"; goto catch; }
<glider_launch> ws* @s0 airport @s1 ws* ";" => glider_how {
<glider_launch> ws* @s0 airport @s1 ";" => glider_how {
new_glider->launch.a = s0, new_glider->launch.b = s1;
fprintf(stderr, "%s[%zu]: glider <<%.*s>> at <<%.*s>>\n",
datestr, line, (int)(new_glider->reg.b - new_glider->reg.a),
@ -366,7 +383,7 @@ static int scan_day(struct scan *const scan, union date32 date,
continue;
}
<glider_how> * { fail = "glider how"; goto catch; }
<glider_how> ws* @s0 [MWA] ws* ";" => glider_height {
<glider_how> ws* @s0 [MWA] ";" => glider_height {
switch(*s0) {
case 'M': new_glider->how = MotorCarTow; break;
case 'W': new_glider->how = Winch; break;
@ -375,10 +392,10 @@ static int scan_day(struct scan *const scan, union date32 date,
continue;
}
<glider_height> * { fail = "glider height"; goto catch; }
<glider_height> ws* @s0 natural @s1 "'" ws* ";" => glider_landing
<glider_height> ws* @s0 natural @s1 "';" => glider_landing
{ if(!pair_to_natural(s0, s1, &new_glider->height_ft)); continue; }
<glider_landing> * { fail = "glider landing"; goto catch; }
<glider_landing> ws* @s0 airport @s1 ws* ";" => glider_pilot
<glider_landing> ws* @s0 airport @s1 ";" => glider_pilot
{ new_glider->landing.a = s0, new_glider->landing.b = s1; continue;}
<glider_pilot> * { fail = "glider pilot time"; goto catch; }
<glider_pilot> ws* ";" => glider_dual /* not PIC */
@ -402,10 +419,10 @@ static int scan_day(struct scan *const scan, union date32 date,
&new_glider->instr_min)) { fail = "glider instr time"; goto catch; }
continue; }
<glider_remarks> * { fail = "glider remarks"; goto catch; }
<glider_remarks> ws* "\n" => line
<glider_remarks> "\n" => line
{ new_glider->remarks.a = new_glider->remarks.b = 0;
new_glider = 0; line++; continue; }
<glider_remarks> ws* @s0 glyph+ (" " glyph+)* @s1 "\n" => line
<glider_remarks> ws* @s0 anylabel @s1 "\n" => line
{ new_glider->remarks.a = s0, new_glider->remarks.b = s1;
new_glider = 0; line++; continue; }
@ -413,7 +430,7 @@ static int scan_day(struct scan *const scan, union date32 date,
/* type; registration; launch -- landing; pic; sic;
single engine day dual; pilot; instrument simulated; actual; remarks */
<flight_type> * { fail = "flight type"; goto catch; }
<flight_type> ws* @s0 semitext+ @s1 ws* ";" => flight_reg {
<flight_type> ws* @s0 semilabel @s1 ";" => flight_reg {
const union line64 key
= {{ (uint32_t)line, {{ date.day, date.month, date.year }} }};
assert(!new_flight);
@ -427,7 +444,7 @@ static int scan_day(struct scan *const scan, union date32 date,
continue;
}
<flight_reg> * { fail = "flight reg"; goto catch; }
<flight_reg> ws* @s0 semitext+ @s1 ws* ";" => flight_airports
<flight_reg> ws* @s0 semilabel @s1 ";" => flight_airports
{ new_flight->reg.a = s0, new_flight->reg.b = s1; continue; }
<flight_airports> * { fail = "flight airports"; goto catch; }
<flight_airports> ws* @s0 airport @s1 ws* "--"
@ -440,14 +457,12 @@ static int scan_day(struct scan *const scan, union date32 date,
continue;
}
<flight_pic> * { fail = "flight pic"; goto catch; }
<flight_pic> ws* @s0 semitext+ (ws+ semitext+)* @s1 /* ws*? */";"
=> flight_sic
<flight_pic> ws* @s0 semilabel @s1 ";" => flight_sic
{ new_flight->pilot.a = s0, new_flight->pilot.b = s1; continue; }
<flight_sic> * { fail = "flight sic"; goto catch; }
<flight_sic> ws* ";" => flight_dual
{ new_flight->copilot.a = new_flight->copilot.b = 0; continue; }
<flight_sic> ws* @s0 semitext+ (ws+ semitext+)* @s1 ";"
=> flight_dual
<flight_sic> ws* @s0 semilabel @s1 ";" => flight_dual
{ new_flight->copilot.a = s0, new_flight->copilot.b = s1; continue; }
<flight_dual> * { fail = "flight dual time"; goto catch; }
<flight_dual> ws* ";" => flight_pilot
@ -478,10 +493,10 @@ static int scan_day(struct scan *const scan, union date32 date,
&new_flight->ifr_min)) { fail = "flight ifr time"; goto catch; }
continue; }
<flight_remarks> * { fail = "flight remarks"; goto catch; }
<flight_remarks> ws* "\n" => line
<flight_remarks> "\n" => line
{ new_flight->remarks.a = new_flight->remarks.b = 0;
new_flight = 0; line++; continue; }
<flight_remarks> ws* @s0 glyph+ (ws+ glyph+)* @s1 "\n" => line
<flight_remarks> ws* @s0 anylabel @s1 "\n" => line
{ new_flight->remarks.a = s0, new_flight->remarks.b = s1;
new_flight = 0; line++; continue; }
@ -497,7 +512,8 @@ static int scan_day(struct scan *const scan, union date32 date,
<line> "Judges" / kjvlookat => book { book = Judges; continue; }
<line> "Ruth" / kjvlookat => book { book = Ruth; continue; }
<line> first "Samuel" / kjvlookat => book { book = ISamuel; continue; }
<line> second "Samuel" / kjvlookat => book { book = IISamuel; continue; }
<line> second "Samuel" / kjvlookat => book
{ book = IISamuel; continue; }
<line> first "Kings" / kjvlookat => book { book = IKings; continue; }
<line> second "Kings" / kjvlookat => book { book = IIKings; continue; }
<line> first "Chronicles" / kjvlookat
@ -568,7 +584,7 @@ static int scan_day(struct scan *const scan, union date32 date,
<line> "Revelation" / kjvlookat => book { book = Revelation; continue; }
<book> * { fail = "kjv unrecognized"; goto catch; }
/* 19:15a, just ignore the a. */
<book> ws+ @s0 natural @s1 ":" @t0 natural @t1 [ab]? {
<book> " " @s0 natural @s1 ":" @t0 natural @t1 [ab]? {
if(chapter || verse || verse_end)
{ fail = "kjv reference"; goto catch; }
if(!pair_to_natural(s0, s1, &chapter)
@ -583,7 +599,7 @@ static int scan_day(struct scan *const scan, union date32 date,
{ fail = "kjv range numerical error"; goto catch; }
continue;
}
<book> ws+ "--" ws+ => skip {
<book> " -- " => skip {
if(!chapter || !verse)
{ fail = "kjv missing information"; goto catch; }
if(verse_end && verse_end <= verse)
@ -608,6 +624,43 @@ static int scan_day(struct scan *const scan, union date32 date,
continue;
}
/* "<<\ntext\n>>" or "text\n" used by several.
Must have future and */
<text_input, text_multi> * { fail = "text input"; goto catch; }
<text_input> ws+ { continue; }
<text_input> "\n" => line { // empty is okay
line++;
assert(future);
future->a = future->b = 0, future = 0;
continue;
}
<text_input> "<<\n" @s0 => text_multi { // multi-line
line++;
fprintf(stderr, "$$$ multi-line!\n");
assert(future);
future->a = s0;
continue;
}
<text_input> @s0 anylabel @s1 "\n" => line { // one line
//<text_input> @s0 semilabel @s1 "\n" => line { // one line
line++;
fprintf(stderr, "text: [[%.*s]]\n", (int)(s1 - s0), s0);
assert(future);
future->a = s0, future->b = s1, future = 0;
continue;
}
<text_multi> [^\x00\n] { continue; }
<text_multi> [\x00] { fail = "missing closing \">>\""; goto catch; }
<text_multi> "\n" { line++; continue; }
<text_multi> @s1 ">>\n" => line {
line++;
assert(future && future->a);
future->b = s1;
future = 0;
continue;
}
*/ }
assert(0); /* Never gets here. */
catch:
@ -632,6 +685,10 @@ void scan_(struct scan *const scan) {
pair_map_table_(&scan->places.map);
place_array_(&scan->places.array);
linemap_tree_(&scan->documents.dates);
pair_map_table_(&scan->documents.map);
source_array_(&scan->documents.array);
linemap_tree_(&scan->sources.dates);
pair_map_table_(&scan->sources.map);
source_array_(&scan->sources.array);
@ -650,6 +707,8 @@ struct scan scan(struct journal *const jrnl) {
struct source *nul;
if(!(nul = source_array_new(&scan.sources.array))) goto catch;
*nul = (struct source){0};
if(!(nul = source_array_new(&scan.documents.array))) goto catch;
*nul = (struct source){0};
}
{
struct place *nul;