enhanced the xli reader to recognize some other line termination conventions than a single LF.

added more code to the upcoming ini-style format reader
This commit is contained in:
hyung-hwan 2015-08-30 03:11:54 +00:00
parent e8fb5c1948
commit 63ecef90a0
4 changed files with 256 additions and 77 deletions

View File

@ -334,6 +334,7 @@ struct qse_xli_io_arg_t
qse_char_t buf[1024]; qse_char_t buf[1024];
qse_size_t pos; qse_size_t pos;
qse_size_t len; qse_size_t len;
int state;
} b; } b;
qse_size_t line; qse_size_t line;

View File

@ -35,15 +35,20 @@
* key1 = value1 * key1 = value1
* -------------------------------- * --------------------------------
* *
* SECTION1 = { * SECTION1 {
* key1 = value1; * key1 = value1;
* key2 = value2; * key2 = value2;
* } * }
* SECTION2 = { * SECTION2 {
* key1 = value1; * key1 = value1;
* } * }
*/ */
enum
{
TOK_STATUS_UPTO_EOL = (1 << 0)
};
#define GET_CHAR(xli) \ #define GET_CHAR(xli) \
do { if (qse_xli_getchar(xli) <= -1) return -1; } while(0) do { if (qse_xli_getchar(xli) <= -1) return -1; } while(0)
@ -71,6 +76,10 @@
} \ } \
} while (0) } while (0)
#define SET_TOKEN_TYPE(xli,tok,code) \
do { (tok)->type = (code); } while (0)
#define MATCH(xli,tok_type) ((xli)->tok.type == (tok_type))
static int skip_spaces (qse_xli_t* xli) static int skip_spaces (qse_xli_t* xli)
{ {
@ -102,7 +111,7 @@ static int skip_comment (qse_xli_t* xli, qse_xli_tok_t* tok)
qse_xli_inserttext (xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(tok->name)) == QSE_NULL) return -1; qse_xli_inserttext (xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(tok->name)) == QSE_NULL) return -1;
GET_CHAR (xli); /* eat the new line letter */ GET_CHAR (xli); /* eat the new line letter */
return 1; /* comment by # */ return 1; /* comment by ; */
} }
return 0; return 0;
@ -130,21 +139,132 @@ static int get_token_into (qse_xli_t* xli, qse_xli_tok_t* tok)
if (c == QSE_CHAR_EOF) if (c == QSE_CHAR_EOF)
{ {
#if 0 ADD_TOKEN_STR (xli, tok, QSE_T("<EOF>"), 5);
n = end_include (xli, 0); SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_EOF);
if (n <= -1) return -1; }
if (n >= 1) else if (xli->tok_status & TOK_STATUS_UPTO_EOL)
{
qse_size_t xlen = 0;
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_SQSTR);
while (1)
{ {
/*xli->rio.last = xli->rio.inp->last;*/ GET_CHAR_TO (xli, c);
/* mark that i'm retrying after end of an included file */ if (c == QSE_CHAR_EOF || c == QSE_T(';')) break;
skip_semicolon_after_include = 1;
goto retry; ADD_TOKEN_CHAR (xli, tok, c);
if (!QSE_ISSPACE(c)) xlen = QSE_STR_LEN(tok->name);
} }
ADD_TOKEN_STR (xli, tok, QSE_T("<EOF>"), 5); /* trim away trailing spaces */
SET_TOKEN_TYPE (xli, tok, TOK_EOF); qse_str_setlen (tok->name, xlen);
#endif
} }
else if (c == QSE_T('['))
{
/* in the ini-styled format, a tag is used as a section name.
* but the kinds of allowed charaters are more limited than
* a normal tag in the xli format. */
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_TAG);
while (1)
{
GET_CHAR_TO (xli, c);
if (c == QSE_CHAR_EOF)
{
/* the string tag is not closed */
qse_xli_seterror (xli, QSE_XLI_ETAGNC, QSE_NULL, &xli->tok.loc);
return -1;
}
if (c == QSE_T(']'))
{
/* terminating quote */
GET_CHAR (xli);
break;
}
if (!QSE_ISALNUM(c) && c != QSE_T('-') && c != QSE_T('_') && c != QSE_T(':'))
{
qse_char_t cc = (qse_char_t)c;
qse_cstr_t ea;
ea.ptr = &cc;
ea.len = 1;
qse_xli_seterror (xli, QSE_XLI_ETAGCHR, &ea, &tok->loc);
return -1;
}
ADD_TOKEN_CHAR (xli, tok, c);
}
}
else if (c == QSE_T('_') || QSE_ISALPHA (c) ||
((xli->opt.trait & QSE_XLI_LEADDIGIT) && QSE_ISDIGIT(c)))
{
int lead_digit = QSE_ISDIGIT(c);
int all_digits = 1;
/* a normal identifier can be composed of wider varieties of
* characters than a keyword/directive */
while (1)
{
ADD_TOKEN_CHAR (xli, tok, c);
GET_CHAR_TO (xli, c);
if (c == QSE_T('_') || c == QSE_T('-') ||
c == QSE_T(':') || c == QSE_T('*') ||
c == QSE_T('/') || QSE_ISALPHA (c))
{
all_digits = 0;
}
else if (QSE_ISDIGIT(c))
{
/* nothing to do */
}
else break;
}
if (lead_digit && all_digits)
{
/* if an identifier begins with a digit, it must contain a non-digits character */
qse_xli_seterror (xli, QSE_XLI_EIDENT, QSE_STR_XSTR(tok->name), &tok->loc);
return -1;
}
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_IDENT);
}
else if (c == QSE_T('='))
{
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_EQ);
ADD_TOKEN_CHAR (xli, tok, c);
}
else
{
/* not handled yet */
if (c == QSE_T('\0'))
{
qse_cstr_t ea;
ea.ptr = QSE_T("<NUL>");
ea.len = 5;
qse_xli_seterror (xli, QSE_XLI_ELXCHR, &ea, &tok->loc);
}
else
{
qse_char_t cc = (qse_char_t)c;
qse_cstr_t ea;
ea.ptr = &cc;
ea.len = 1;
qse_xli_seterror (xli, QSE_XLI_ELXCHR, &ea, &tok->loc);
}
return -1;
}
return 0;
}
static int get_token (qse_xli_t* xli)
{
return get_token_into (xli, &xli->tok);
} }
static int __read_list (qse_xli_t* xli, const qse_xli_scm_t* override) static int __read_list (qse_xli_t* xli, const qse_xli_scm_t* override)
@ -185,6 +305,8 @@ int qse_xli_readini (qse_xli_t* xli, qse_xli_io_impl_t io)
xli->rio.top.colm = 1; xli->rio.top.colm = 1;
xli->rio.inp = &xli->rio.top; xli->rio.inp = &xli->rio.top;
xli->tok_status = 0;
qse_xli_seterrnum (xli, QSE_XLI_ENOERR, QSE_NULL); qse_xli_seterrnum (xli, QSE_XLI_ENOERR, QSE_NULL);
qse_xli_clearrionames (xli); qse_xli_clearrionames (xli);
@ -197,13 +319,11 @@ int qse_xli_readini (qse_xli_t* xli, qse_xli_io_impl_t io)
QSE_ASSERT (xli->parlink == QSE_NULL); QSE_ASSERT (xli->parlink == QSE_NULL);
/* if (!MATCH (xli, QSE_XLI_TOK_EOF))
if (!MATCH (xli, TOK_EOF))
{ {
qse_xli_seterror (xli, QSE_XLI_ESYNTAX, QSE_NULL, &xli->tok.loc); qse_xli_seterror (xli, QSE_XLI_ESYNTAX, QSE_NULL, &xli->tok.loc);
goto oops; goto oops;
} }
*/
QSE_ASSERT (xli->rio.inp == &xli->rio.top); QSE_ASSERT (xli->rio.inp == &xli->rio.top);
qse_xli_closecurrentstream (xli); qse_xli_closecurrentstream (xli);

View File

@ -67,24 +67,7 @@ int qse_xli_closecurrentstream (qse_xli_t* xli)
return 0; return 0;
} }
enum tok_t
{
TOK_EOF,
TOK_XINCLUDE,
TOK_SEMICOLON,
TOK_LBRACE,
TOK_RBRACE,
TOK_EQ,
TOK_COMMA,
TOK_DQSTR,
TOK_SQSTR,
TOK_NSTR,
TOK_IDENT,
TOK_TEXT,
TOK_TAG,
__TOKEN_COUNT__
};
#define GET_CHAR(xli) \ #define GET_CHAR(xli) \
do { if (qse_xli_getchar(xli) <= -1) return -1; } while(0) do { if (qse_xli_getchar(xli) <= -1) return -1; } while(0)
@ -130,12 +113,24 @@ struct kwent_t
static kwent_t kwtab[] = static kwent_t kwtab[] =
{ {
/* keep it sorted by the first field for binary search */ /* keep it sorted by the first field for binary search */
{ { QSE_T("@include"), 8 }, TOK_XINCLUDE } { { QSE_T("@include"), 8 }, QSE_XLI_TOK_XINCLUDE }
}; };
int qse_xli_getchar (qse_xli_t* xli) int qse_xli_getchar (qse_xli_t* xli)
{ {
qse_ssize_t n; qse_ssize_t n;
qse_char_t lc, ec;
if (xli->rio.inp->b.state == -1)
{
xli->rio.inp->b.state = 0;
return -1;
}
else if (xli->rio.inp->b.state == 1)
{
xli->rio.inp->b.state = 0;
goto return_eof;
}
if (xli->rio.inp->b.pos >= xli->rio.inp->b.len) if (xli->rio.inp->b.pos >= xli->rio.inp->b.len)
{ {
@ -152,6 +147,7 @@ int qse_xli_getchar (qse_xli_t* xli)
if (n == 0) if (n == 0)
{ {
return_eof:
xli->rio.inp->last.c = QSE_CHAR_EOF; xli->rio.inp->last.c = QSE_CHAR_EOF;
xli->rio.inp->last.line = xli->rio.inp->line; xli->rio.inp->last.line = xli->rio.inp->line;
xli->rio.inp->last.colm = xli->rio.inp->colm; xli->rio.inp->last.colm = xli->rio.inp->colm;
@ -170,16 +166,57 @@ int qse_xli_getchar (qse_xli_t* xli)
* increment the line counter and reset column to 1. * increment the line counter and reset column to 1.
* incrementing it line number here instead of * incrementing it line number here instead of
* updating inp->last causes the line number for * updating inp->last causes the line number for
* TOK_EOF to be the same line as the last newline. */ * QSE_XLI_TOK_EOF to be the same line as the last newline. */
xli->rio.inp->line++; xli->rio.inp->line++;
xli->rio.inp->colm = 1; xli->rio.inp->colm = 1;
} }
xli->rio.inp->last.c = xli->rio.inp->b.buf[xli->rio.inp->b.pos++]; lc = xli->rio.inp->b.buf[xli->rio.inp->b.pos++];
if (lc == QSE_T('\n') || lc == QSE_T('\r'))
{
/* handle common newline conventions.
* LF+CR
* CR+LF
* LF
* CR
* convert all above to a single LF.
*/
if (xli->rio.inp->b.pos >= xli->rio.inp->b.len)
{
n = xli->rio.impl (
xli, QSE_XLI_IO_READ, xli->rio.inp,
xli->rio.inp->b.buf, QSE_COUNTOF(xli->rio.inp->b.buf)
);
if (n <= -1)
{
xli->rio.inp->b.state = -1;
goto done;
}
else if (n == 0)
{
xli->rio.inp->b.state = 1;
goto done;
}
else
{
xli->rio.inp->b.pos = 0;
xli->rio.inp->b.len = n;
}
}
ec = (lc == '\n')? '\r': '\n';
if (xli->rio.inp->b.buf[xli->rio.inp->b.pos] == ec) xli->rio.inp->b.pos++;
done:
lc = QSE_T('\n');
}
xli->rio.inp->last.c = lc;
xli->rio.inp->last.line = xli->rio.inp->line; xli->rio.inp->last.line = xli->rio.inp->line;
xli->rio.inp->last.colm = xli->rio.inp->colm++; xli->rio.inp->last.colm = xli->rio.inp->colm++;
xli->rio.inp->last.file = xli->rio.inp->name; xli->rio.inp->last.file = xli->rio.inp->name;
xli->rio.last = xli->rio.inp->last; xli->rio.last = xli->rio.inp->last;
return 0; return 0;
} }
@ -248,7 +285,7 @@ static int classify_ident (qse_xli_t* xli, const qse_cstr_t* name)
else return kwp->type; else return kwp->type;
} }
return TOK_IDENT; return QSE_XLI_TOK_IDENT;
} }
static int get_symbols (qse_xli_t* xli, qse_cint_t c, qse_xli_tok_t* tok) static int get_symbols (qse_xli_t* xli, qse_cint_t c, qse_xli_tok_t* tok)
@ -262,11 +299,11 @@ static int get_symbols (qse_xli_t* xli, qse_cint_t c, qse_xli_tok_t* tok)
static struct ops_t ops[] = static struct ops_t ops[] =
{ {
{ QSE_T("="), 1, TOK_EQ }, { QSE_T("="), 1, QSE_XLI_TOK_EQ },
{ QSE_T(","), 1, TOK_COMMA }, { QSE_T(","), 1, QSE_XLI_TOK_COMMA },
{ QSE_T(";"), 1, TOK_SEMICOLON }, { QSE_T(";"), 1, QSE_XLI_TOK_SEMICOLON },
{ QSE_T("{"), 1, TOK_LBRACE }, { QSE_T("{"), 1, QSE_XLI_TOK_LBRACE },
{ QSE_T("}"), 1, TOK_RBRACE }, { QSE_T("}"), 1, QSE_XLI_TOK_RBRACE },
{ QSE_NULL, 0, 0, } { QSE_NULL, 0, 0, }
}; };
@ -434,7 +471,7 @@ retry:
} }
ADD_TOKEN_STR (xli, tok, QSE_T("<EOF>"), 5); ADD_TOKEN_STR (xli, tok, QSE_T("<EOF>"), 5);
SET_TOKEN_TYPE (xli, tok, TOK_EOF); SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_EOF);
} }
else if (c == QSE_T('@')) else if (c == QSE_T('@'))
{ {
@ -462,7 +499,7 @@ retry:
while (QSE_ISALPHA (c)); while (QSE_ISALPHA (c));
type = classify_ident (xli, QSE_STR_XSTR(tok->name)); type = classify_ident (xli, QSE_STR_XSTR(tok->name));
if (type == TOK_IDENT) if (type == QSE_XLI_TOK_IDENT)
{ {
/* this keyword/directive is not recognized */ /* this keyword/directive is not recognized */
qse_xli_seterror (xli, QSE_XLI_EXKWNR, QSE_STR_XSTR(tok->name), &tok->loc); qse_xli_seterror (xli, QSE_XLI_EXKWNR, QSE_STR_XSTR(tok->name), &tok->loc);
@ -505,11 +542,11 @@ retry:
return -1; return -1;
} }
SET_TOKEN_TYPE (xli, tok, TOK_IDENT); SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_IDENT);
} }
else if ((xli->tok_status & TOK_STATUS_ENABLE_NSTR) && QSE_ISDIGIT(c)) else if ((xli->tok_status & TOK_STATUS_ENABLE_NSTR) && QSE_ISDIGIT(c))
{ {
SET_TOKEN_TYPE (xli, tok, TOK_NSTR); SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_NSTR);
do do
{ {
ADD_TOKEN_CHAR (xli, tok, c); ADD_TOKEN_CHAR (xli, tok, c);
@ -520,7 +557,7 @@ retry:
else if (c == QSE_T('\'')) else if (c == QSE_T('\''))
{ {
/* single-quoted string - no escaping */ /* single-quoted string - no escaping */
SET_TOKEN_TYPE (xli, tok, TOK_SQSTR); SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_SQSTR);
while (1) while (1)
{ {
@ -548,7 +585,7 @@ retry:
/* double-quoted string - support escaping */ /* double-quoted string - support escaping */
int escaped = 0; int escaped = 0;
SET_TOKEN_TYPE (xli, tok, TOK_DQSTR); SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_DQSTR);
while (1) while (1)
{ {
@ -592,7 +629,7 @@ retry:
* "tg" is stored into the tag field of qse_xli_str_t. * "tg" is stored into the tag field of qse_xli_str_t.
*/ */
SET_TOKEN_TYPE (xli, tok, TOK_TAG); SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_TAG);
while (1) while (1)
{ {
@ -630,7 +667,7 @@ retry:
else else
{ {
n = get_symbols (xli, c, tok); n = get_symbols (xli, c, tok);
if (n <= -1) return -1; if (n <= -1) return -1; // hard failure
if (n == 0) if (n == 0)
{ {
/* not handled yet */ /* not handled yet */
@ -652,7 +689,7 @@ retry:
return -1; return -1;
} }
if (skip_semicolon_after_include && tok->type == TOK_SEMICOLON) if (skip_semicolon_after_include && tok->type == QSE_XLI_TOK_SEMICOLON)
{ {
/* this handles the optional semicolon after the /* this handles the optional semicolon after the
* included file named as in @include "file-name"; */ * included file named as in @include "file-name"; */
@ -766,7 +803,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
if (key_alias) if (key_alias)
{ {
/* the alias part must be unique for the same key(s) */ /* the alias part must be unique for the same key(s) */
if (MATCH (xli, TOK_IDENT) || MATCH (xli, TOK_DQSTR) || MATCH (xli, TOK_SQSTR) || MATCH(xli, TOK_NSTR)) if (MATCH (xli, QSE_XLI_TOK_IDENT) || MATCH (xli, QSE_XLI_TOK_DQSTR) || MATCH (xli, QSE_XLI_TOK_SQSTR) || MATCH(xli, QSE_XLI_TOK_NSTR))
{ {
qse_xli_atom_t* atom; qse_xli_atom_t* atom;
@ -802,11 +839,11 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
} }
} }
if (MATCH (xli, TOK_EQ)) if (MATCH (xli, QSE_XLI_TOK_EQ))
{ {
if (get_token (xli) <= -1) goto oops; if (get_token (xli) <= -1) goto oops;
if ((xli->opt.trait & QSE_XLI_STRTAG) && MATCH (xli, TOK_TAG)) if ((xli->opt.trait & QSE_XLI_STRTAG) && MATCH (xli, QSE_XLI_TOK_TAG))
{ {
strtag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr); strtag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr);
if (strtag == QSE_NULL) if (strtag == QSE_NULL)
@ -818,7 +855,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
if (get_token (xli) <= -1) goto oops; if (get_token (xli) <= -1) goto oops;
} }
if (MATCH (xli, TOK_SQSTR) || MATCH (xli, TOK_DQSTR) || MATCH(xli, TOK_NSTR) || MATCH (xli, TOK_IDENT)) if (MATCH (xli, QSE_XLI_TOK_SQSTR) || MATCH (xli, QSE_XLI_TOK_DQSTR) || MATCH(xli, QSE_XLI_TOK_NSTR) || MATCH (xli, QSE_XLI_TOK_IDENT))
{ {
qse_xli_str_t* curstrseg; qse_xli_str_t* curstrseg;
qse_size_t segcount = 0; qse_size_t segcount = 0;
@ -838,7 +875,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
curstrseg = (qse_xli_str_t*)pair->val; curstrseg = (qse_xli_str_t*)pair->val;
if (get_token (xli) <= -1) goto oops; if (get_token (xli) <= -1) goto oops;
if ((xli->opt.trait & QSE_XLI_MULSEGSTR) && MATCH(xli, TOK_COMMA)) if ((xli->opt.trait & QSE_XLI_MULSEGSTR) && MATCH(xli, QSE_XLI_TOK_COMMA))
{ {
/* multi-segmented string */ /* multi-segmented string */
do do
@ -851,7 +888,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
strtag = QSE_NULL; strtag = QSE_NULL;
} }
if ((xli->opt.trait & QSE_XLI_STRTAG) && MATCH (xli, TOK_TAG)) if ((xli->opt.trait & QSE_XLI_STRTAG) && MATCH (xli, QSE_XLI_TOK_TAG))
{ {
strtag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr); strtag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr);
if (strtag == QSE_NULL) if (strtag == QSE_NULL)
@ -863,7 +900,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
if (get_token (xli) <= -1) goto oops; if (get_token (xli) <= -1) goto oops;
} }
if (!MATCH (xli, TOK_SQSTR) && !MATCH (xli, TOK_DQSTR) && !MATCH (xli, TOK_NSTR) && !MATCH (xli, TOK_IDENT)) if (!MATCH (xli, QSE_XLI_TOK_SQSTR) && !MATCH (xli, QSE_XLI_TOK_DQSTR) && !MATCH (xli, QSE_XLI_TOK_NSTR) && !MATCH (xli, QSE_XLI_TOK_IDENT))
{ {
qse_xli_seterror (xli, QSE_XLI_ESYNTAX, QSE_NULL, &xli->tok.loc); qse_xli_seterror (xli, QSE_XLI_ESYNTAX, QSE_NULL, &xli->tok.loc);
goto oops; goto oops;
@ -876,11 +913,11 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
segcount++; segcount++;
if (get_token (xli) <= -1) goto oops; /* skip the value */ if (get_token (xli) <= -1) goto oops; /* skip the value */
} }
while (MATCH (xli, TOK_COMMA)); while (MATCH (xli, QSE_XLI_TOK_COMMA));
} }
/* semicolon is mandatory for a string */ /* semicolon is mandatory for a string */
if (!MATCH (xli, TOK_SEMICOLON)) if (!MATCH (xli, QSE_XLI_TOK_SEMICOLON))
{ {
qse_xli_seterror (xli, QSE_XLI_ESCOLON, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc); qse_xli_seterror (xli, QSE_XLI_ESCOLON, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
goto oops; goto oops;
@ -907,7 +944,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
/* TODO: check against schema */ /* TODO: check against schema */
} }
else if (!(xli->opt.trait & QSE_XLI_NOLIST) && MATCH (xli, TOK_LBRACE)) else if (!(xli->opt.trait & QSE_XLI_NOLIST) && MATCH (xli, QSE_XLI_TOK_LBRACE))
{ {
if (scm && !(scm->flags & QSE_XLI_SCM_VALLIST)) if (scm && !(scm->flags & QSE_XLI_SCM_VALLIST))
{ {
@ -928,7 +965,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
* take effect. */ * take effect. */
if (read_list (xli, (qse_xli_list_t*)pair->val, (val_iffy? &scm_val_iffy: QSE_NULL)) <= -1) goto oops; if (read_list (xli, (qse_xli_list_t*)pair->val, (val_iffy? &scm_val_iffy: QSE_NULL)) <= -1) goto oops;
if (!MATCH (xli, TOK_RBRACE)) if (!MATCH (xli, QSE_XLI_TOK_RBRACE))
{ {
qse_xli_seterror (xli, QSE_XLI_ERBRCE, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc); qse_xli_seterror (xli, QSE_XLI_ERBRCE, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
goto oops; goto oops;
@ -937,7 +974,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
if (get_token (xli) <= -1) goto oops; if (get_token (xli) <= -1) goto oops;
/* semicolon is optional for a list */ /* semicolon is optional for a list */
if (MATCH (xli, TOK_SEMICOLON)) if (MATCH (xli, QSE_XLI_TOK_SEMICOLON))
{ {
/* skip the semicolon */ /* skip the semicolon */
if (get_token (xli) <= -1) goto oops; if (get_token (xli) <= -1) goto oops;
@ -945,7 +982,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
/* TODO: check against schema */ /* TODO: check against schema */
} }
else if (MATCH (xli, TOK_SEMICOLON)) else if (MATCH (xli, QSE_XLI_TOK_SEMICOLON))
{ {
if (xli->opt.trait & QSE_XLI_NONIL) if (xli->opt.trait & QSE_XLI_NONIL)
{ {
@ -1018,11 +1055,11 @@ static int __read_list (qse_xli_t* xli, const qse_xli_scm_t* override)
{ {
while (1) while (1)
{ {
if (MATCH (xli, TOK_XINCLUDE)) if (MATCH (xli, QSE_XLI_TOK_XINCLUDE))
{ {
if (get_token(xli) <= -1) return -1; if (get_token(xli) <= -1) return -1;
if (!MATCH(xli,TOK_SQSTR) && !MATCH(xli,TOK_DQSTR)) if (!MATCH(xli,QSE_XLI_TOK_SQSTR) && !MATCH(xli,QSE_XLI_TOK_DQSTR))
{ {
qse_xli_seterror (xli, QSE_XLI_EINCLSTR, QSE_NULL, &xli->tok.loc); qse_xli_seterror (xli, QSE_XLI_EINCLSTR, QSE_NULL, &xli->tok.loc);
return -1; return -1;
@ -1030,7 +1067,7 @@ static int __read_list (qse_xli_t* xli, const qse_xli_scm_t* override)
if (begin_include (xli) <= -1) return -1; if (begin_include (xli) <= -1) return -1;
} }
else if ((xli->opt.trait & QSE_XLI_KEYTAG) && MATCH (xli, TOK_TAG)) else if ((xli->opt.trait & QSE_XLI_KEYTAG) && MATCH (xli, QSE_XLI_TOK_TAG))
{ {
qse_char_t* keytag; qse_char_t* keytag;
int x; int x;
@ -1048,7 +1085,7 @@ static int __read_list (qse_xli_t* xli, const qse_xli_scm_t* override)
return -1; return -1;
} }
if (!MATCH(xli,TOK_IDENT)) if (!MATCH(xli,QSE_XLI_TOK_IDENT))
{ {
QSE_MMGR_FREE (xli->mmgr, keytag); QSE_MMGR_FREE (xli->mmgr, keytag);
qse_xli_seterror (xli, QSE_XLI_ENOKEY, QSE_NULL, &xli->tok.loc); qse_xli_seterror (xli, QSE_XLI_ENOKEY, QSE_NULL, &xli->tok.loc);
@ -1059,11 +1096,11 @@ static int __read_list (qse_xli_t* xli, const qse_xli_scm_t* override)
QSE_MMGR_FREE (xli->mmgr, keytag); QSE_MMGR_FREE (xli->mmgr, keytag);
if (x <= -1) return -1; if (x <= -1) return -1;
} }
else if (MATCH (xli, TOK_IDENT)) else if (MATCH (xli, QSE_XLI_TOK_IDENT))
{ {
if (read_pair (xli, QSE_NULL, override) <= -1) return -1; if (read_pair (xli, QSE_NULL, override) <= -1) return -1;
} }
else if (MATCH (xli, TOK_TEXT)) else if (MATCH (xli, QSE_XLI_TOK_TEXT))
{ {
if (get_token(xli) <= -1) return -1; if (get_token(xli) <= -1) return -1;
} }
@ -1142,6 +1179,8 @@ int qse_xli_read (qse_xli_t* xli, qse_xli_io_impl_t io)
xli->rio.top.colm = 1; xli->rio.top.colm = 1;
xli->rio.inp = &xli->rio.top; xli->rio.inp = &xli->rio.top;
xli->tok_status = 0;
qse_xli_seterrnum (xli, QSE_XLI_ENOERR, QSE_NULL); qse_xli_seterrnum (xli, QSE_XLI_ENOERR, QSE_NULL);
qse_xli_clearrionames (xli); qse_xli_clearrionames (xli);
@ -1154,7 +1193,7 @@ int qse_xli_read (qse_xli_t* xli, qse_xli_io_impl_t io)
QSE_ASSERT (xli->parlink == QSE_NULL); QSE_ASSERT (xli->parlink == QSE_NULL);
if (!MATCH (xli, TOK_EOF)) if (!MATCH (xli, QSE_XLI_TOK_EOF))
{ {
qse_xli_seterror (xli, QSE_XLI_ESYNTAX, QSE_NULL, &xli->tok.loc); qse_xli_seterror (xli, QSE_XLI_ESYNTAX, QSE_NULL, &xli->tok.loc);
goto oops; goto oops;

View File

@ -32,13 +32,32 @@
#include <qse/cmn/rbt.h> #include <qse/cmn/rbt.h>
#include "../cmn/mem.h" #include "../cmn/mem.h"
enum qse_xli_tok_type_t
{
QSE_XLI_TOK_EOF,
QSE_XLI_TOK_XINCLUDE,
QSE_XLI_TOK_SEMICOLON,
QSE_XLI_TOK_LBRACE,
QSE_XLI_TOK_RBRACE,
QSE_XLI_TOK_EQ,
QSE_XLI_TOK_COMMA,
QSE_XLI_TOK_DQSTR,
QSE_XLI_TOK_SQSTR,
QSE_XLI_TOK_NSTR,
QSE_XLI_TOK_IDENT,
QSE_XLI_TOK_TEXT,
QSE_XLI_TOK_TAG
};
typedef enum qse_xli_tok_type_t qse_xli_tok_type_t;
typedef struct qse_xli_tok_t qse_xli_tok_t; typedef struct qse_xli_tok_t qse_xli_tok_t;
struct qse_xli_tok_t struct qse_xli_tok_t
{ {
int type; qse_xli_tok_type_t type;
qse_str_t* name; qse_str_t* name;
qse_xli_loc_t loc; qse_xli_loc_t loc;
}; };
typedef struct qse_xli_list_link_t qse_xli_list_link_t; typedef struct qse_xli_list_link_t qse_xli_list_link_t;
@ -88,7 +107,7 @@ struct qse_xli_t
struct struct
{ {
qse_xli_io_impl_t impl; /* input handler */ qse_xli_io_impl_t impl; /* input handler */
qse_xli_io_lxc_t last; qse_xli_io_lxc_t last;
qse_xli_io_arg_t top; /* for top level */ qse_xli_io_arg_t top; /* for top level */
qse_xli_io_arg_t* inp; /* current */ qse_xli_io_arg_t* inp; /* current */
} rio; } rio;