Score compiles and lists scores.
This commit is contained in:
parent
5f223b1ca2
commit
bdb9e171d1
4
Makefile
4
Makefile
@ -42,7 +42,7 @@ bin/test-source: build/text.o build/pair.o build/journal.o build/source.o build/
|
||||
bin/test-kjv: build/text.o build/pair.o build/kjvcite.o build/test_kjv.o
|
||||
bin/kjv: build/text.o build/pair.o build/journal.o build/kjvcite.o build/kjv.o build/source.o
|
||||
bin/flight: build/text.o build/pair.o build/journal.o build/source.o build/flights.o build/flighthours.o
|
||||
bin/score: build/text.o build/pair.o build/journal.o build/scan_score.o
|
||||
bin/score: build/text.o build/pair.o build/journal.o build/scores.o
|
||||
|
||||
bin/%:
|
||||
@echo "\033[1;36mlinking $@\033[0m"
|
||||
@ -72,7 +72,7 @@ build/%.c: src/%.re.c
|
||||
# # https://github.com/neil-edelman/cdoc documentation
|
||||
# -cdoc -o $@ $<
|
||||
|
||||
.SECONDARY: build/kjv.c build/journal.c build/source.c build/scan_kjv.c build/flights.c build/kjvcite.c
|
||||
.SECONDARY: build/kjv.c build/journal.c build/source.c build/scan_kjv.c build/flights.c build/kjvcite.c build/scores.c
|
||||
.PHONY: clean release test
|
||||
|
||||
test: $(projects)
|
||||
|
@ -244,13 +244,6 @@ struct journal_iterator journal_iterator(struct journal *const j) {
|
||||
return it;
|
||||
}
|
||||
|
||||
/*struct journal_iterator journal_begin_at(struct journal *const j,
|
||||
const union date32 x) {
|
||||
struct journal_iterator it;
|
||||
it._ = day_tree_begin_at(&j->days, x);
|
||||
return it;
|
||||
}*/
|
||||
|
||||
int journal_next(struct journal_iterator *const it,
|
||||
union date32 *const k, const char **v) {
|
||||
assert(it && k && v);
|
||||
|
@ -9,7 +9,6 @@
|
||||
@std C11 */
|
||||
|
||||
#include "../src/kjvcite.h"
|
||||
#include "../src/text.h"
|
||||
#include "../src/pair.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
@ -1,27 +1,3 @@
|
||||
/** Is `y` a leap-year? */
|
||||
static int leap(int y) {
|
||||
assert(y >= 1582);
|
||||
if(!(y % 400)) return 1;
|
||||
if(!(y % 100)) return 0;
|
||||
if(!(y % 4)) return 1;
|
||||
return 0;
|
||||
}
|
||||
/** Convert or narrower type or return zero. */
|
||||
static union date32 date_to_32(const int y, const int m, const int d) {
|
||||
union date32 d32 = { 0 };
|
||||
/* Leap year calculations only work at y>=1 and Gregorian Calendar and max
|
||||
23 bits. */
|
||||
if(y < 1582 || y > 8388607 || m < 1 || m > 12 || d < 1 || d > 31) goto no;
|
||||
switch(m) {
|
||||
case 1: case 3: case 5: case 7: case 8: case 10: case 12: break;
|
||||
case 4: case 6: case 9: case 11: if(d > 30) goto no; break;
|
||||
case 2: if(d > 28 + leap(y)) goto no; break;
|
||||
default: assert(0); break;
|
||||
}
|
||||
d32.year = (unsigned)y, d32.month = (unsigned)m, d32.day = (unsigned)d;
|
||||
no:
|
||||
return d32;
|
||||
}
|
||||
/** Tomohiko Sakamoto comp.lang.c 1993-04-10. */
|
||||
static unsigned weekday(union date32 d) {
|
||||
d.year -= d.month < 3;
|
||||
|
59
src/pair.c
59
src/pair.c
@ -9,7 +9,6 @@
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h> /* sprintf */
|
||||
|
||||
/** @return Constructs `a` and `b` as a pair. */
|
||||
struct pair pair(const char *const a, const char *const b) {
|
||||
@ -19,14 +18,14 @@ struct pair pair(const char *const a, const char *const b) {
|
||||
}
|
||||
|
||||
/** Doesn't check if the number is actually in [0, 9].
|
||||
@return Whether it was able to parse unsigned `p` to `n`. */
|
||||
int pair_to_natural(const char *s, const char *const e, uint32_t *const n) {
|
||||
@return Whether it was able to parse unsigned [`a`, `b`] to `n`. */
|
||||
int pair_to_natural(const char *a, const char *const b, uint32_t *const n) {
|
||||
uint32_t accum = 0;
|
||||
while(s < e) {
|
||||
unsigned next = accum * 10 + (unsigned)(*s - '0');
|
||||
while(a < b) {
|
||||
unsigned next = accum * 10 + (unsigned)(*a - '0');
|
||||
if(accum > next) return errno = ERANGE, 0;
|
||||
accum = next;
|
||||
s++;
|
||||
a++;
|
||||
}
|
||||
return *n = accum, 1;
|
||||
}
|
||||
@ -69,6 +68,53 @@ int pair_is_string(struct pair x, const char *y) {
|
||||
while(x.a < x.b) { if(*x.a != *y || !*y) return 0; x.a++, y++; }
|
||||
return !*y;
|
||||
}
|
||||
/** Is `y` a leap-year? */
|
||||
static int leap(int y) {
|
||||
assert(y >= 1582);
|
||||
if(!(y % 400)) return 1;
|
||||
if(!(y % 100)) return 0;
|
||||
if(!(y % 4)) return 1;
|
||||
return 0;
|
||||
}
|
||||
/** Convert or narrower type or return zero. */
|
||||
static union date32 date_to_32(const uint32_t y, const uint32_t m,
|
||||
const uint32_t d) {
|
||||
union date32 d32 = { 0 };
|
||||
/* Leap year calculations only work at y>=1 and Gregorian Calendar and max
|
||||
23 bits. */
|
||||
if(y < 1582 || y > 8388607 || m < 1 || m > 12 || d < 1 || d > 31) goto no;
|
||||
switch(m) {
|
||||
case 1: case 3: case 5: case 7: case 8: case 10: case 12: break;
|
||||
case 4: case 6: case 9: case 11: if(d > 30) goto no; break;
|
||||
case 2: if(d > (uint32_t)(28 + leap((int)y))) goto no; break;
|
||||
default: assert(0); break;
|
||||
}
|
||||
d32.year = (unsigned)y, d32.month = (unsigned)m, d32.day = (unsigned)d;
|
||||
no:
|
||||
return d32;
|
||||
}
|
||||
/** `a` represents the start of a date in y...-mm-dd, which is stored in `d`.
|
||||
@return Success.
|
||||
@throws[ERANGE] Year is more then 23 bits.
|
||||
@throws[EILSEQ] The is not a date? */
|
||||
int pair_to_date(const char *a, union date32 *const d) {
|
||||
uint32_t year = 0, month, day;
|
||||
union date32 temp;
|
||||
assert(a && d);
|
||||
while(*a >= '0' && *a <= '9') {
|
||||
year = year * 10 + (unsigned)(*a - '0');
|
||||
if(year > 0x7FFFFF) return errno = ERANGE, 0; /* 23 bits */
|
||||
a++;
|
||||
}
|
||||
if(a[0] != '-' || a[1] == '\0' || a[2] == '\0'
|
||||
|| a[3] != '-' || a[4] == '\0' || a[5] == '\0')
|
||||
return errno = EILSEQ, 0;
|
||||
month = (unsigned)(a[1] - '0') * 10 + (unsigned)(a[2] - '0');
|
||||
day = (unsigned)(a[4] - '0') * 10 + (unsigned)(a[5] - '0');
|
||||
temp = date_to_32(year, month, day);
|
||||
if(!temp.u32) return errno = EILSEQ, 0;
|
||||
return *d = temp, 1;
|
||||
}
|
||||
|
||||
/** @return A djb2 <http://www.cse.yorku.ca/~oz/hash.html> hash of `p`. */
|
||||
static uint32_t pair_djb2(struct pair p) {
|
||||
@ -80,6 +126,7 @@ static uint32_t pair_djb2(struct pair p) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
#include <stdio.h> /* sprintf */
|
||||
/* Maps from substring keywords to indices, default zero. */
|
||||
static void pairmap_to_string(const struct pair key, const size_t i,
|
||||
char (*const a)[12]) { (void)key; sprintf(*a, "%zu", i); }
|
||||
|
@ -12,6 +12,8 @@ int pair_hours_to_minutes(const char *h0, const char *const h1,
|
||||
const char *m0, const char *const m1, uint32_t *const n);
|
||||
int pair_is_equal(struct pair, struct pair);
|
||||
int pair_is_string(struct pair, const char *);
|
||||
#include "journal.h" /* date32 */
|
||||
int pair_to_date(const char *a, union date32 *const d);
|
||||
/*fixme
|
||||
uint32_t pair_djb2(const struct pair p);*/
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
#endif
|
||||
|
||||
#include "../src/journal.h"
|
||||
#include "../src/scan_score.h"
|
||||
#include "../src/scores.h"
|
||||
#include <stdio.h>
|
||||
//#include <string.h>
|
||||
//#include <stdlib.h>
|
||||
@ -56,11 +56,12 @@ static int score_compare(const union line64 a, const union line64 b)
|
||||
|
||||
static int scan(union date32 date, const char *const buffer,
|
||||
struct scores *const scores) {
|
||||
const char *YYCURSOR, *YYMARKER, *yyt1, *yyt2, *yyt3, *s0, *s1, *t0, *t1;
|
||||
const char *YYCURSOR, *YYMARKER, *yyt1, *yyt2, *s0, *s1;
|
||||
enum YYCONDTYPE condition = yycline;
|
||||
size_t line = 1;
|
||||
char datestr[12] = {0};
|
||||
const char *why = "unexpected";
|
||||
struct score *score = 0;
|
||||
assert(buffer && scores);
|
||||
YYCURSOR = YYMARKER = yyt1 = buffer;
|
||||
/*!re2c /**/
|
||||
@ -71,11 +72,13 @@ static int scan(union date32 date, const char *const buffer,
|
||||
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);
|
||||
glyph = [^\x00-\x20\x7f]; // [^\x00\n\t ] + all weird
|
||||
semitext = glyph \ ";";
|
||||
natural = [1-9][0-9]*;
|
||||
uint = [0-9]+;
|
||||
keyword = [A-Za-z0-9][A-Za-z0-9_-]*;
|
||||
date = natural "-" [0-1][0-9] "-" [0-3][0-9];
|
||||
*/
|
||||
for( ; ; ) { /*!re2c /**/
|
||||
/* Default ignore. */
|
||||
@ -86,53 +89,74 @@ static int scan(union date32 date, const char *const buffer,
|
||||
<line> * :=> skip
|
||||
<line> "::" / [^:] :=> score
|
||||
|
||||
<score> * { why = "default score unrecognized"; goto catch; }
|
||||
<score> * { why = "score unrecognized"; goto catch; }
|
||||
/* Already there. Use the map to get the index from the keyword and
|
||||
then stick a marker in the tree with that index. */
|
||||
<score> @s0 keyword @s1 / "\n" => skip { also_add_to_tree: {
|
||||
const struct pair keyword = pair(s0, s1);
|
||||
const union line64 key = { { (uint32_t)line, date } };
|
||||
size_t i, *pi;
|
||||
size_t idx, *pidx;
|
||||
if(line > UINT32_MAX)
|
||||
{ errno = ERANGE; why = "too many lines of text"; goto catch; }
|
||||
if(!(i = pair_map_table_get(&scores->map, keyword)))
|
||||
if(!(idx = pair_map_table_get(&scores->map, keyword)))
|
||||
{ why = "keyword not introduced"; goto catch; }
|
||||
switch(score_tree_try(&scores->dates, key, &pi)) {
|
||||
/* fixme: bulk */
|
||||
switch(score_tree_try(&scores->dates, key, &pidx)) {
|
||||
case TREE_PRESENT: why = "duplicate key"; /* _Sic_. */
|
||||
case TREE_ERROR: goto catch;
|
||||
case TREE_ABSENT: *pi = i; break;
|
||||
case TREE_ABSENT: *pidx = idx; break;
|
||||
}
|
||||
/*date32_to_string(date, &datestr);
|
||||
printf("%s: <%.*s>\n", datestr, (int)(s1 - s0), s0);*/
|
||||
date32_to_string(date, &datestr);
|
||||
printf("%s: <%.*s>\n", datestr, (int)(s1 - s0), s0);
|
||||
continue;
|
||||
} }
|
||||
/* This is lazy and will pickup trailing spaces. */
|
||||
<score> @s0 keyword @s1 ":" [^\x00\n]+ / "\n" => skip {
|
||||
struct pair keyword = pair(s0, s1);
|
||||
/* New score. */
|
||||
<score> @s0 keyword @s1 ":" => score_name {
|
||||
size_t *idx;
|
||||
struct score *score;
|
||||
switch(pair_map_table_assign(&scores->map, keyword, &idx)) {
|
||||
switch(pair_map_table_assign(&scores->map, pair(s0, s1), &idx)) {
|
||||
case TABLE_PRESENT: errno = EDOM; why = "new keyword already used";
|
||||
case TABLE_ERROR: goto catch; /* /\ _Sic_. */
|
||||
case TABLE_ABSENT: *idx = 0; break; /* Good. */
|
||||
case TABLE_ERROR: goto catch; /* _Sic_. */
|
||||
case TABLE_ABSENT: *idx = 0; break;
|
||||
}
|
||||
if(!(score = scorelist_array_new(&scores->list))) goto catch;
|
||||
*idx = (size_t)(score - scores->list.data);
|
||||
/*struct pair key, name; union date32 date; unsigned edges;*/
|
||||
score->key.a = s0, score->key.b = s1;
|
||||
score->name.a = 0, score->name.b = 0;
|
||||
score->date.year = 0, score->date.month = 0, score->date.day = 0;
|
||||
score->date.u32 = 0;
|
||||
score->edges = 0;
|
||||
date32_to_string(date, &datestr);
|
||||
fprintf(stderr, "%s: new source <%.*s> stored in list at %zu.\n",
|
||||
fprintf(stderr, "%s: new score <%.*s> stored in list at %zu.\n",
|
||||
datestr, (int)(s1 - s0), s0, *idx);
|
||||
goto also_add_to_tree;
|
||||
}
|
||||
/*ws* @name0 [^\x00\n;]+ @name1 ";"
|
||||
ws* @year0 natural @year1 "-" @month [0-1][0-9] "-" @day [0-1][0-9] ";"
|
||||
ws*
|
||||
/ "\n" => skip*/
|
||||
<score_name> * { why = "name unrecognized"; goto catch; }
|
||||
<score_date> * { why = "date unrecognized"; goto catch; }
|
||||
<score_edges> * { why = "edges unrecognized"; goto catch; }
|
||||
<score_name> ws* @s0 semitext+ (" " semitext+)* @s1 /* ws* */ ";"
|
||||
=> score_date {
|
||||
assert(score);
|
||||
score->name.a = s0, score->name.b = s1;
|
||||
}
|
||||
<score_date> ws* "~"? @s0 date ws* ";" => score_edges {
|
||||
assert(score);
|
||||
if(!pair_to_date(s0, &score->date)) goto catch;
|
||||
}
|
||||
<score_edges> ws* "~"? @s0 uint @s1 ws* / "\n" => skip {
|
||||
assert(score);
|
||||
if(!pair_to_natural(s0, s1, &score->edges)) goto catch;
|
||||
score = 0; /* Done. */
|
||||
}
|
||||
*/ }
|
||||
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);
|
||||
fprintf(stderr, "%s line %zu: %s.\n", datestr, line, why);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -172,3 +196,10 @@ finally:
|
||||
|
||||
int scores_is_empty(const struct scores *const s)
|
||||
{ return !s || !s->dates.root.node; }
|
||||
|
||||
int main(void) {
|
||||
struct journal j = journal();
|
||||
struct scores s = scores(&j);
|
||||
scores_(&s);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue
Block a user