WIP on parser
This commit is contained in:
parent
ff268cded0
commit
d61e77f9dc
|
@ -6,8 +6,8 @@
|
|||
*/
|
||||
|
||||
/* parse.c */
|
||||
void iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601_date* latest,
|
||||
struct iso8601_details* details);
|
||||
int iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601_date* latest,
|
||||
struct iso8601_details* details);
|
||||
|
||||
/* c_library.c */
|
||||
void iso8601_now(struct iso8601_date* date, struct iso8601_details* details);
|
||||
|
|
|
@ -7,10 +7,272 @@
|
|||
|
||||
|
||||
|
||||
void iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601_date* latest,
|
||||
int iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601_date* latest,
|
||||
struct iso8601_details* details)
|
||||
{
|
||||
|
||||
enum {
|
||||
state_none,
|
||||
state_year, // e.g. `2006' or `2006123'
|
||||
state_date2, // 2nd component of date, e.g. `2006-' or `2006-1'
|
||||
state_day, // e.g. `2006-01-' or `2006-01-01'
|
||||
state_week_basic, // e.g. `2006W' or `2006W123'
|
||||
state_week_extended, // e.g. `2006-W' or `2006-W31'
|
||||
state_week_day, // e.g. `2006-W31-'
|
||||
state_week_done, // `2006-W31-1'
|
||||
state_time_basic,
|
||||
state_time_hour
|
||||
}state = state_none;
|
||||
|
||||
char ch;
|
||||
int num = 0, neg = 0, dig = 0;
|
||||
int y = 0, m = 0, d = 0, w = 0, wd = 0, hour = 0, min = 0, sec = 0;
|
||||
|
||||
while(1) {
|
||||
ch = *str++;
|
||||
printf("ch = '%c', state = %d, num = %d, dig = %d\n", ch, state, num, dig);
|
||||
|
||||
switch(state) {
|
||||
case state_none:
|
||||
switch(ch) {
|
||||
case '0' ... '9':
|
||||
state = state_year;
|
||||
num = ch - '0';
|
||||
++dig;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
neg = 1;
|
||||
state = state_year;
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case state_year:
|
||||
switch(ch) {
|
||||
case '0' ... '9':
|
||||
++dig;
|
||||
num *= 10;
|
||||
num += ch - '0';
|
||||
if(num > 1000000000) {
|
||||
errno = EDOM;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '-':
|
||||
if(!dig) {
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
y = num;
|
||||
num = 0;
|
||||
dig = 0;
|
||||
state = state_date2;
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
case 0:
|
||||
switch(dig) {
|
||||
case 4:
|
||||
if(ch) {
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
y = num;
|
||||
goto done;
|
||||
|
||||
case 6:
|
||||
if(ch) {
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
y = num / 100;
|
||||
m = num - y * 100;
|
||||
goto done;
|
||||
|
||||
case 7:
|
||||
y = num / 1000;
|
||||
d = num - (y * 1000);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
y = num / 10000;
|
||||
num -= y * 10000;
|
||||
m = num / 100;
|
||||
d = num - m * 100;
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
if(!ch) goto done;
|
||||
state = state_time_basic;
|
||||
num = 0;
|
||||
dig = 0;
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
y = num;
|
||||
num = 0;
|
||||
dig = 0;
|
||||
state = state_week_basic;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case state_date2:
|
||||
switch(ch) {
|
||||
case '0' ... '9':
|
||||
num *= 10;
|
||||
num += ch - '0';
|
||||
++dig;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
if(num < 1 || num > 12 || dig != 2) {
|
||||
errno = EDOM;
|
||||
return -1;
|
||||
}
|
||||
m = num;
|
||||
num = 0;
|
||||
dig = 0;
|
||||
state = state_day;
|
||||
|
||||
case 'W':
|
||||
if(dig) {
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
state = state_week_extended;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case 'T':
|
||||
if(dig != 3) {
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
d = num;
|
||||
if(!ch) goto done;
|
||||
state = state_time_hour;
|
||||
num = 0;
|
||||
dig = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case state_day:
|
||||
switch(ch) {
|
||||
case '0' ... '9':
|
||||
num *= 10;
|
||||
num += ch;
|
||||
++dig;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case 'T':
|
||||
if(dig != 2) {
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
d = num;
|
||||
if(!ch) goto done;
|
||||
state = state_time_hour;
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case state_week_basic:
|
||||
switch(ch) {
|
||||
case '0' ... '9':
|
||||
num *= 10;
|
||||
num += ch - '0';
|
||||
++dig;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case 'T':
|
||||
switch(dig) {
|
||||
case 3:
|
||||
w = num / 10;
|
||||
wd = num % 10;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
w = num;
|
||||
if(!ch) break;
|
||||
|
||||
default:
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
if(!ch) goto done;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case state_week_extended:
|
||||
switch(ch) {
|
||||
case '0' ... '9':
|
||||
num *= 10;
|
||||
num += ch - '0';
|
||||
++dig;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case '-':
|
||||
if(dig != 2) {
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
w = num;
|
||||
num = 0;
|
||||
dig = 0;
|
||||
if(!ch) goto done;
|
||||
state = state_week_day;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case state_week_day:
|
||||
if(ch < '1' || ch > '7') {
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
wd = ch - '0';
|
||||
state = state_week_done;
|
||||
break;
|
||||
|
||||
case state_week_done:
|
||||
if(!ch) goto done;
|
||||
if(ch != 'T') {
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
state = state_time_hour;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
printf("y=%d, m=%d, d=%d, w=%d, wd=%d\n", y, m, d, w, wd);
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/* libiso8601/src/tests/parser.c
|
||||
*
|
||||
* (c)2006, Laurence Withers, <l@lwithers.me.uk>.
|
||||
* Released under the GNU GPLv2. See file COPYING or
|
||||
* http://www.gnu.org/copyleft/gpl.html for details.
|
||||
*/
|
||||
|
||||
#include "iso8601.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
int do_date(const char* str)
|
||||
{
|
||||
struct iso8601_date earliest, latest;
|
||||
struct iso8601_details details;
|
||||
char buf[100], buf2[100];
|
||||
|
||||
if(iso8601_parse(str, &earliest, &latest, &details)) {
|
||||
perror("iso8601_parse");
|
||||
return 1;
|
||||
}
|
||||
|
||||
iso8601_print(buf, sizeof(buf), &earliest, &details);
|
||||
iso8601_print(buf2, sizeof(buf2), &latest, &details);
|
||||
|
||||
printf("Results for ``%s'':\n"
|
||||
" Earliest: day=%d, sec=%05d, nsec=%09d; %s\n"
|
||||
" Latest : day=%d, sec=%05d, nsec=%09d; %s\n"
|
||||
" Details : date_prec=%d, time_prec=%d, extended=%d, tz_sec=%d\n"
|
||||
"\n",
|
||||
str,
|
||||
earliest.day, earliest.sec, earliest.nsec, buf,
|
||||
latest.day, latest.sec, latest.nsec, buf2,
|
||||
details.date_prec, details.time_prec, details.extended, details.tz_sec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int ret = 0, i;
|
||||
char buf[100];
|
||||
|
||||
if(argc == 2 && !strcmp(argv[1], "--print-summary")) {
|
||||
printf("One line summary.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(argc == 1) {
|
||||
while(!feof(stdin)) {
|
||||
printf("date >> ");
|
||||
scanf("%s", buf);
|
||||
do_date(buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(i = 1; i < argc; ++i) {
|
||||
ret |= do_date(argv[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* options for text editors
|
||||
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||
vim: expandtab:ts=4:sw=4
|
||||
*/
|
Loading…
Reference in New Issue