implementing hcl_feed()
This commit is contained in:
parent
982a7c1592
commit
60c9fe8ac9
26
bin/main.c
26
bin/main.c
@ -855,16 +855,6 @@ int main (int argc, char* argv[])
|
|||||||
* -- instead of returning -1 immediately. --*/
|
* -- instead of returning -1 immediately. --*/
|
||||||
set_signal (SIGINT, handle_sigint);
|
set_signal (SIGINT, handle_sigint);
|
||||||
|
|
||||||
#if 0
|
|
||||||
hcl_prbfmt (hcl, "this is good %s %10hs %hs\n", "whole new world. 1234567890 from this point onward, any failure leasd to jumping to oops label", "as이거 좋은거잖아dkfjsdakfjsadklfjasd", "1111");
|
|
||||||
{
|
|
||||||
hcl_uch_t fmt[] = {'G','G','%','l','s', 'a','b','c','-','-','%','0','2','0','x','\0'};
|
|
||||||
hcl_uch_t ustr[] = {'A','B','C', 'X','Y','Z','Q','Q','\0'};
|
|
||||||
hcl_prufmt (hcl, fmt, ustr, 0x6789);
|
|
||||||
hcl_logufmt (hcl, HCL_LOG_WARN, fmt, ustr, 0x6789);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// TODO: change the option name
|
// TODO: change the option name
|
||||||
// in the INTERACTIVE mode, the compiler generates MAKE_FUNCTION for lambda functions.
|
// in the INTERACTIVE mode, the compiler generates MAKE_FUNCTION for lambda functions.
|
||||||
@ -879,6 +869,22 @@ hcl_logufmt (hcl, HCL_LOG_WARN, fmt, ustr, 0x6789);
|
|||||||
cflags = 0;
|
cflags = 0;
|
||||||
if (xtn->reader_istty) cflags = HCL_COMPILE_CLEAR_CODE | HCL_COMPILE_CLEAR_FNBLK;
|
if (xtn->reader_istty) cflags = HCL_COMPILE_CLEAR_CODE | HCL_COMPILE_CLEAR_FNBLK;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
hcl_oow_t slen;
|
||||||
|
hcl_ooch_t* scr = hcl_dupbtooocstr(hcl, "(:::::..##..|,:{{}}..\n....)(#(#[", &slen);
|
||||||
|
if (hcl_feed (hcl, scr, slen) <= -1)
|
||||||
|
{
|
||||||
|
if (hcl->errnum == HCL_ESYNERR) print_synerr (hcl);
|
||||||
|
else hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: cannot feed - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl));
|
||||||
|
}
|
||||||
|
|
||||||
|
hcl_endfeed (hcl);
|
||||||
|
}
|
||||||
|
hcl_close (hcl);
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
hcl_cnode_t* obj;
|
hcl_cnode_t* obj;
|
||||||
|
@ -149,12 +149,14 @@ enum hcl_iotok_type_t
|
|||||||
|
|
||||||
HCL_IOTOK_IDENT,
|
HCL_IOTOK_IDENT,
|
||||||
HCL_IOTOK_IDENT_DOTTED,
|
HCL_IOTOK_IDENT_DOTTED,
|
||||||
HCL_IOTOK_DOT,
|
HCL_IOTOK_DOT, /* . */
|
||||||
HCL_IOTOK_ELLIPSIS,
|
HCL_IOTOK_DBLDOTS, /* .. */
|
||||||
HCL_IOTOK_COLON,
|
HCL_IOTOK_ELLIPSIS, /* ... */
|
||||||
|
HCL_IOTOK_COLON, /* : */
|
||||||
|
HCL_IOTOK_DBLCOLONS, /* :: */
|
||||||
HCL_IOTOK_TRPCOLONS, /* ::: */
|
HCL_IOTOK_TRPCOLONS, /* ::: */
|
||||||
HCL_IOTOK_DCSTAR, /* ::* */
|
HCL_IOTOK_DCSTAR, /* ::* */
|
||||||
HCL_IOTOK_COMMA,
|
HCL_IOTOK_COMMA, /* , */
|
||||||
HCL_IOTOK_LPAREN, /* ( */
|
HCL_IOTOK_LPAREN, /* ( */
|
||||||
HCL_IOTOK_RPAREN, /* ) */
|
HCL_IOTOK_RPAREN, /* ) */
|
||||||
HCL_IOTOK_LPARCOLON, /* (: */
|
HCL_IOTOK_LPARCOLON, /* (: */
|
||||||
@ -496,6 +498,23 @@ struct hcl_rstl_t
|
|||||||
hcl_rstl_t* prev;
|
hcl_rstl_t* prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct hcl_feed_dt_t hcl_feed_dt_t;
|
||||||
|
struct hcl_feed_dt_t
|
||||||
|
{
|
||||||
|
int row_start;
|
||||||
|
int row_end;
|
||||||
|
int col_next;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum hcl_feed_lx_state_t
|
||||||
|
{
|
||||||
|
HCL_FEED_LX_START,
|
||||||
|
HCL_FEED_LX_DELIM_TOKEN,
|
||||||
|
HCL_FEED_LX_COMMENT,
|
||||||
|
HCL_FEED_LX_SHARP_TOKEN
|
||||||
|
};
|
||||||
|
typedef enum hcl_feed_lx_state_t hcl_feed_lx_state_t;
|
||||||
|
|
||||||
struct hcl_compiler_t
|
struct hcl_compiler_t
|
||||||
{
|
{
|
||||||
/* output handler */
|
/* output handler */
|
||||||
@ -541,6 +560,33 @@ struct hcl_compiler_t
|
|||||||
} r; /* reading */
|
} r; /* reading */
|
||||||
/* == END READER == */
|
/* == END READER == */
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
hcl_feed_lx_state_t state;
|
||||||
|
hcl_ioloc_t loc;
|
||||||
|
} lx;
|
||||||
|
hcl_feed_dt_t dt; /* delimiter token */
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int code;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
} xxx;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
} yyy;
|
||||||
|
} u;
|
||||||
|
} st[100];
|
||||||
|
hcl_ooi_t top;
|
||||||
|
} feed;
|
||||||
|
|
||||||
/* == COMPILER STACK == */
|
/* == COMPILER STACK == */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -577,6 +623,8 @@ struct hcl_compiler_t
|
|||||||
hcl_clsblk_info_t* info;
|
hcl_clsblk_info_t* info;
|
||||||
hcl_oow_t info_capa;
|
hcl_oow_t info_capa;
|
||||||
} clsblk; /* class block */
|
} clsblk; /* class block */
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2192,6 +2192,15 @@ HCL_EXPORT hcl_ooi_t hcl_proutufmt (
|
|||||||
);
|
);
|
||||||
|
|
||||||
#if defined(HCL_INCLUDE_COMPILER)
|
#if defined(HCL_INCLUDE_COMPILER)
|
||||||
|
|
||||||
|
HCL_EXPORT int hcl_feed (
|
||||||
|
hcl_t* hcl,
|
||||||
|
const hcl_ooch_t* data,
|
||||||
|
hcl_oow_t len
|
||||||
|
);
|
||||||
|
|
||||||
|
#define hcl_endfeed(hcl) (hcl_feed((hcl), HCL_NULL, 0))
|
||||||
|
|
||||||
HCL_EXPORT int hcl_compile (
|
HCL_EXPORT int hcl_compile (
|
||||||
hcl_t* hcl,
|
hcl_t* hcl,
|
||||||
hcl_cnode_t* obj,
|
hcl_cnode_t* obj,
|
||||||
|
670
lib/read.c
670
lib/read.c
@ -289,6 +289,12 @@ static HCL_INLINE int is_spacechar (hcl_ooci_t c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HCL_INLINE int is_linebreak (hcl_ooci_t c)
|
||||||
|
{
|
||||||
|
/* TODO: different line end conventions? */
|
||||||
|
return c == '\n';
|
||||||
|
}
|
||||||
|
|
||||||
static HCL_INLINE int is_alphachar (hcl_ooci_t c)
|
static HCL_INLINE int is_alphachar (hcl_ooci_t c)
|
||||||
{
|
{
|
||||||
/* TODO: support full unicode */
|
/* TODO: support full unicode */
|
||||||
@ -313,11 +319,12 @@ static HCL_INLINE int is_alnumchar (hcl_ooci_t c)
|
|||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
|
||||||
}
|
}
|
||||||
|
|
||||||
static HCL_INLINE int is_delimiter (hcl_ooci_t c)
|
static HCL_INLINE int is_delimchar (hcl_ooci_t c)
|
||||||
{
|
{
|
||||||
return c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' ||
|
return c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' ||
|
||||||
c == '\"' || c == '\'' || c == '#' || c == ';' || c == '|' || c == '.' ||
|
c == ';' || c == '|' || c == ',' || c == '.' || c == ':' ||
|
||||||
c == ',' || c == ':' || is_spacechar(c) || c == HCL_UCI_EOF;
|
/* the first characters of tokens in delim_token_tab up to this point */
|
||||||
|
c == '#' || c == '\"' || c == '\'' || is_spacechar(c) || c == HCL_UCI_EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int copy_string_to (hcl_t* hcl, const hcl_oocs_t* src, hcl_oocs_t* dst, hcl_oow_t* dst_capa, int append, hcl_ooch_t add_delim)
|
static int copy_string_to (hcl_t* hcl, const hcl_oocs_t* src, hcl_oocs_t* dst, hcl_oow_t* dst_capa, int append, hcl_ooch_t add_delim)
|
||||||
@ -733,14 +740,14 @@ static int get_radix_number (hcl_t* hcl, hcl_ooci_t rc, int radix)
|
|||||||
}
|
}
|
||||||
while (CHAR_TO_NUM(c, radix) < radix);
|
while (CHAR_TO_NUM(c, radix) < radix);
|
||||||
|
|
||||||
if (!is_delimiter(c))
|
if (!is_delimchar(c))
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ADD_TOKEN_CHAR(hcl, c);
|
ADD_TOKEN_CHAR(hcl, c);
|
||||||
GET_CHAR_TO (hcl, c);
|
GET_CHAR_TO (hcl, c);
|
||||||
}
|
}
|
||||||
while (!is_delimiter(c));
|
while (!is_delimchar(c));
|
||||||
|
|
||||||
hcl_setsynerrbfmt (hcl, HCL_SYNERR_NUMLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl),
|
hcl_setsynerrbfmt (hcl, HCL_SYNERR_NUMLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl),
|
||||||
"invalid digit in radixed number in %.*js", hcl->c->tok.name.len, hcl->c->tok.name.ptr);
|
"invalid digit in radixed number in %.*js", hcl->c->tok.name.len, hcl->c->tok.name.ptr);
|
||||||
@ -763,19 +770,26 @@ static int get_sharp_token (hcl_t* hcl)
|
|||||||
GET_CHAR_TO (hcl, c);
|
GET_CHAR_TO (hcl, c);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #bBBBB binary
|
|
||||||
* #oOOOO octal
|
|
||||||
* #xXXXX hexadecimal
|
* #xXXXX hexadecimal
|
||||||
|
* #oOOOO octal
|
||||||
|
* #bBBBB binary
|
||||||
* #eDDD error
|
* #eDDD error
|
||||||
* #pHHH smptr
|
* #pHHH smptr
|
||||||
* #nil
|
|
||||||
* #true
|
|
||||||
* #false
|
|
||||||
* #include
|
|
||||||
* #\C character
|
* #\C character
|
||||||
* #\xHHHH unicode character
|
* #\xHHHH unicode character
|
||||||
* #\UHHHH unicode character
|
* #\UHHHH unicode character
|
||||||
* #\uHHHH unicode character
|
* #\uHHHH unicode character
|
||||||
|
* #\backspace
|
||||||
|
* #\linefeed
|
||||||
|
* #\newline
|
||||||
|
* #\nul
|
||||||
|
* #\page
|
||||||
|
* #\return
|
||||||
|
* #\rubout
|
||||||
|
* #\space
|
||||||
|
* #\tab
|
||||||
|
* #\vtab
|
||||||
|
* #include
|
||||||
* #[ ] byte array
|
* #[ ] byte array
|
||||||
* #( ) qlist
|
* #( ) qlist
|
||||||
*/
|
*/
|
||||||
@ -809,7 +823,7 @@ static int get_sharp_token (hcl_t* hcl)
|
|||||||
ADD_TOKEN_CHAR (hcl, '\\');
|
ADD_TOKEN_CHAR (hcl, '\\');
|
||||||
|
|
||||||
GET_CHAR_TO (hcl, c);
|
GET_CHAR_TO (hcl, c);
|
||||||
if (is_delimiter(c))
|
if (is_delimchar(c))
|
||||||
{
|
{
|
||||||
hcl_setsynerrbfmt (hcl, HCL_SYNERR_CHARLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl),
|
hcl_setsynerrbfmt (hcl, HCL_SYNERR_CHARLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl),
|
||||||
"no valid character after #\\ in %.*js", hcl->c->tok.name.len, hcl->c->tok.name.ptr);
|
"no valid character after #\\ in %.*js", hcl->c->tok.name.len, hcl->c->tok.name.ptr);
|
||||||
@ -822,7 +836,7 @@ static int get_sharp_token (hcl_t* hcl)
|
|||||||
ADD_TOKEN_CHAR (hcl, c);
|
ADD_TOKEN_CHAR (hcl, c);
|
||||||
GET_CHAR_TO (hcl, c);
|
GET_CHAR_TO (hcl, c);
|
||||||
}
|
}
|
||||||
while (!is_delimiter(c));
|
while (!is_delimchar(c));
|
||||||
|
|
||||||
if (TOKEN_NAME_LEN(hcl) >= 4)
|
if (TOKEN_NAME_LEN(hcl) >= 4)
|
||||||
{
|
{
|
||||||
@ -849,10 +863,8 @@ static int get_sharp_token (hcl_t* hcl)
|
|||||||
"invalid hexadecimal character in %.*js", TOKEN_NAME_LEN(hcl), TOKEN_NAME_PTR(hcl));
|
"invalid hexadecimal character in %.*js", TOKEN_NAME_LEN(hcl), TOKEN_NAME_PTR(hcl));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = c * 16 + CHAR_TO_NUM(hcl->c->tok.name.ptr[i], 16); /* don't care if it is for 'p' */
|
c = c * 16 + CHAR_TO_NUM(hcl->c->tok.name.ptr[i], 16); /* don't care if it is for 'p' */
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#if (HCL_SIZEOF_OOCH_T >= 2)
|
#if (HCL_SIZEOF_OOCH_T >= 2)
|
||||||
else if (TOKEN_NAME_CHAR(hcl, 2) == 'u')
|
else if (TOKEN_NAME_CHAR(hcl, 2) == 'u')
|
||||||
@ -868,26 +880,22 @@ static int get_sharp_token (hcl_t* hcl)
|
|||||||
goto hexcharlit;
|
goto hexcharlit;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (does_token_name_match(hcl, VOCA_SPACE))
|
else if (does_token_name_match(hcl, VOCA_BACKSPACE))
|
||||||
{
|
{
|
||||||
c = ' ';
|
c = '\b';
|
||||||
|
}
|
||||||
|
else if (does_token_name_match(hcl, VOCA_LINEFEED))
|
||||||
|
{
|
||||||
|
c = '\n';
|
||||||
}
|
}
|
||||||
else if (does_token_name_match(hcl, VOCA_NEWLINE))
|
else if (does_token_name_match(hcl, VOCA_NEWLINE))
|
||||||
{
|
{
|
||||||
/* TODO: convert it to host newline convention. how to handle if it's composed of 2 letters like \r\n? */
|
/* TODO: convert it to host newline convention. how to handle if it's composed of 2 letters like \r\n? */
|
||||||
c = '\n';
|
c = '\n';
|
||||||
}
|
}
|
||||||
else if (does_token_name_match(hcl, VOCA_BACKSPACE))
|
else if (does_token_name_match(hcl, VOCA_NUL)) /* null character. not #nil */
|
||||||
{
|
{
|
||||||
c = '\b';
|
c = '\0';
|
||||||
}
|
|
||||||
else if (does_token_name_match(hcl, VOCA_TAB))
|
|
||||||
{
|
|
||||||
c = '\t';
|
|
||||||
}
|
|
||||||
else if (does_token_name_match(hcl, VOCA_LINEFEED))
|
|
||||||
{
|
|
||||||
c = '\n';
|
|
||||||
}
|
}
|
||||||
else if (does_token_name_match(hcl, VOCA_PAGE))
|
else if (does_token_name_match(hcl, VOCA_PAGE))
|
||||||
{
|
{
|
||||||
@ -897,18 +905,22 @@ static int get_sharp_token (hcl_t* hcl)
|
|||||||
{
|
{
|
||||||
c = '\r';
|
c = '\r';
|
||||||
}
|
}
|
||||||
else if (does_token_name_match(hcl, VOCA_NUL)) /* null character. not #nil */
|
else if (does_token_name_match(hcl, VOCA_RUBOUT))
|
||||||
{
|
{
|
||||||
c = '\0';
|
c = '\x7F'; /* DEL */
|
||||||
|
}
|
||||||
|
else if (does_token_name_match(hcl, VOCA_SPACE))
|
||||||
|
{
|
||||||
|
c = ' ';
|
||||||
|
}
|
||||||
|
else if (does_token_name_match(hcl, VOCA_TAB))
|
||||||
|
{
|
||||||
|
c = '\t';
|
||||||
}
|
}
|
||||||
else if (does_token_name_match(hcl, VOCA_VTAB))
|
else if (does_token_name_match(hcl, VOCA_VTAB))
|
||||||
{
|
{
|
||||||
c = '\v';
|
c = '\v';
|
||||||
}
|
}
|
||||||
else if (does_token_name_match(hcl, VOCA_RUBOUT))
|
|
||||||
{
|
|
||||||
c = '\x7F'; /* DEL */
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hcl_setsynerrbfmt (hcl, HCL_SYNERR_CHARLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl),
|
hcl_setsynerrbfmt (hcl, HCL_SYNERR_CHARLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl),
|
||||||
@ -945,7 +957,7 @@ static int get_sharp_token (hcl_t* hcl)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (is_delimiter(c))
|
if (is_delimchar(c))
|
||||||
{
|
{
|
||||||
/* EOF, whitespace, etc */
|
/* EOF, whitespace, etc */
|
||||||
hcl_setsynerrbfmt (hcl, HCL_SYNERR_HASHLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl),
|
hcl_setsynerrbfmt (hcl, HCL_SYNERR_HASHLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl),
|
||||||
@ -954,15 +966,14 @@ static int get_sharp_token (hcl_t* hcl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ADD_TOKEN_CHAR (hcl, '#');
|
ADD_TOKEN_CHAR (hcl, '#');
|
||||||
long_name:
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ADD_TOKEN_CHAR (hcl, c);
|
ADD_TOKEN_CHAR (hcl, c);
|
||||||
GET_CHAR_TO (hcl, c);
|
GET_CHAR_TO (hcl, c);
|
||||||
}
|
}
|
||||||
while (!is_delimiter(c));
|
while (!is_delimchar(c));
|
||||||
|
|
||||||
if (does_token_name_match (hcl, VOCA_INCLUDE))
|
if (does_token_name_match(hcl, VOCA_INCLUDE))
|
||||||
{
|
{
|
||||||
SET_TOKEN_TYPE (hcl, HCL_IOTOK_INCLUDE);
|
SET_TOKEN_TYPE (hcl, HCL_IOTOK_INCLUDE);
|
||||||
}
|
}
|
||||||
@ -1275,7 +1286,7 @@ retry:
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
ident:
|
ident:
|
||||||
if (is_delimiter(c))
|
if (is_delimchar(c))
|
||||||
{
|
{
|
||||||
hcl_setsynerrbfmt (hcl, HCL_SYNERR_ILCHR, TOKEN_LOC(hcl), HCL_NULL, "illegal character %jc encountered", c);
|
hcl_setsynerrbfmt (hcl, HCL_SYNERR_ILCHR, TOKEN_LOC(hcl), HCL_NULL, "illegal character %jc encountered", c);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1304,7 +1315,7 @@ retry:
|
|||||||
|
|
||||||
read_more_seg:
|
read_more_seg:
|
||||||
GET_CHAR_TO (hcl, c);
|
GET_CHAR_TO (hcl, c);
|
||||||
if (!is_delimiter(c))
|
if (!is_delimchar(c))
|
||||||
{
|
{
|
||||||
hcl_oow_t start;
|
hcl_oow_t start;
|
||||||
hcl_oocs_t seg;
|
hcl_oocs_t seg;
|
||||||
@ -1318,7 +1329,7 @@ retry:
|
|||||||
ADD_TOKEN_CHAR (hcl, c);
|
ADD_TOKEN_CHAR (hcl, c);
|
||||||
GET_CHAR_TO (hcl, c);
|
GET_CHAR_TO (hcl, c);
|
||||||
}
|
}
|
||||||
while (!is_delimiter(c));
|
while (!is_delimchar(c));
|
||||||
|
|
||||||
seg.ptr = &TOKEN_NAME_CHAR(hcl,start);
|
seg.ptr = &TOKEN_NAME_CHAR(hcl,start);
|
||||||
seg.len = TOKEN_NAME_LEN(hcl) - start;
|
seg.len = TOKEN_NAME_LEN(hcl) - start;
|
||||||
@ -1340,7 +1351,7 @@ retry:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (is_delimiter(c))
|
else if (is_delimchar(c))
|
||||||
{
|
{
|
||||||
unget_char (hcl, &hcl->c->lxc);
|
unget_char (hcl, &hcl->c->lxc);
|
||||||
break;
|
break;
|
||||||
@ -2412,3 +2423,580 @@ void hcl_detachio (hcl_t* hcl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static void init_feed (hcl_t* hcl)
|
||||||
|
{
|
||||||
|
hcl->c->feed.lx.state = HCL_FEED_LX_START;
|
||||||
|
hcl->c->feed.lx.loc.line = 1;
|
||||||
|
hcl->c->feed.lx.loc.colm = 1;
|
||||||
|
hcl->c->feed.lx.loc.file = HCL_NULL;
|
||||||
|
|
||||||
|
hcl->c->feed.top = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push_feed_state (hcl_t* hcl, int code)
|
||||||
|
{
|
||||||
|
if (hcl->c->feed.top >= HCL_COUNTOF(hcl->c->feed.st) - 1) /* TODO: use a dynamically allocated stack? */
|
||||||
|
{
|
||||||
|
hcl_seterrbfmt (hcl, HCL_EBUFFULL, "feed state stack full");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hcl->c->feed.top++;
|
||||||
|
HCL_MEMSET (&hcl->c->feed.st[hcl->c->feed.top], 0, HCL_SIZEOF(hcl->c->feed.st[hcl->c->feed.top]));
|
||||||
|
hcl->c->feed.st[hcl->c->feed.top].code = code;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pop_feed_state (hcl_t* hcl)
|
||||||
|
{
|
||||||
|
HCL_ASSERT (hcl, hcl->c->feed.top >= 0);
|
||||||
|
hcl->c->feed.top--;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct delim_token_t
|
||||||
|
{
|
||||||
|
const char* t_value;
|
||||||
|
hcl_oow_t t_len;
|
||||||
|
hcl_iotok_type_t t_type;
|
||||||
|
};
|
||||||
|
typedef struct delim_token_t delim_token_t;
|
||||||
|
|
||||||
|
static delim_token_t delim_token_tab[] =
|
||||||
|
{
|
||||||
|
/* [NOTE 1]
|
||||||
|
* if you add a new token, ensure the first character is listed in is_delimchar()
|
||||||
|
*
|
||||||
|
* [NOTE 2]
|
||||||
|
* for the implementation limitation in find_delim_token_char(),
|
||||||
|
* the entries in this table must be laid out in a certain way.
|
||||||
|
*
|
||||||
|
* Group the items with the same prefix together.
|
||||||
|
* List the shorter before the longer items in the same group.
|
||||||
|
* The length must not differ by greater than 1 between 2 items in the same group.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{ "(", 1, HCL_IOTOK_LPAREN },
|
||||||
|
{ "(:", 2, HCL_IOTOK_LPARCOLON },
|
||||||
|
{ ")", 1, HCL_IOTOK_RPAREN },
|
||||||
|
|
||||||
|
{ "[", 1, HCL_IOTOK_LBRACK },
|
||||||
|
{ "]", 1, HCL_IOTOK_RBRACK },
|
||||||
|
|
||||||
|
{ "{", 1, HCL_IOTOK_LBRACE },
|
||||||
|
{ "}", 1, HCL_IOTOK_RBRACE },
|
||||||
|
|
||||||
|
{ "|", 1, HCL_IOTOK_VBAR },
|
||||||
|
{ ",", 1, HCL_IOTOK_COMMA },
|
||||||
|
|
||||||
|
{ ".", 1, HCL_IOTOK_DOT },
|
||||||
|
{ "..", 2, HCL_IOTOK_DBLDOTS },
|
||||||
|
{ "...", 3, HCL_IOTOK_ELLIPSIS },
|
||||||
|
|
||||||
|
{ ":", 1, HCL_IOTOK_COLON },
|
||||||
|
{ "::", 2, HCL_IOTOK_DBLCOLONS },
|
||||||
|
{ "::*", 3, HCL_IOTOK_DCSTAR },
|
||||||
|
{ ":::", 3, HCL_IOTOK_TRPCOLONS }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int find_delim_token_char (hcl_t* hcl, const hcl_ooci_t c, int row_start, int row_end, int col, hcl_feed_dt_t* dt)
|
||||||
|
{
|
||||||
|
int found = 0, i;
|
||||||
|
|
||||||
|
for (i = row_start; i <= row_end; i++)
|
||||||
|
{
|
||||||
|
//printf (">>> %d %d %d col=>%d c=>%jc\n", i, row_start, row_end, col, c);
|
||||||
|
if (col < delim_token_tab[i].t_len && c == delim_token_tab[i].t_value[col])
|
||||||
|
{
|
||||||
|
//printf ("MATCH [%jc] [%jc]\n", c, delim_token_tab[i].t_value[col]);
|
||||||
|
if (!found) dt->row_start = i;
|
||||||
|
dt->row_end = i;
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
else if (found) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) dt->col_next = col + 1;
|
||||||
|
//printf ("**** return %d %d\n", dt->row_start, dt->row_end);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HCL_INLINE int feed_wrap_up (hcl_t* hcl, hcl_iotok_type_t type)
|
||||||
|
{
|
||||||
|
SET_TOKEN_TYPE (hcl, type);
|
||||||
|
|
||||||
|
HCL_DEBUG4 (hcl, "TOKEN LEN %zu=>[%.*js] %d\n", TOKEN_NAME_LEN(hcl), TOKEN_NAME_LEN(hcl), TOKEN_NAME_PTR(hcl), TOKEN_TYPE(hcl));
|
||||||
|
/* TOOD: fire token callback or something */
|
||||||
|
|
||||||
|
hcl->c->feed.lx.state = HCL_FEED_LX_START;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int feed_wrap_up_with_char (hcl_t* hcl, hcl_ooci_t c, hcl_iotok_type_t type)
|
||||||
|
{
|
||||||
|
ADD_TOKEN_CHAR (hcl, c);
|
||||||
|
return feed_wrap_up(hcl, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int feed_wrap_up_with_str (hcl_t* hcl, const hcl_ooch_t* str, hcl_oow_t len, hcl_iotok_type_t type)
|
||||||
|
{
|
||||||
|
ADD_TOKEN_STR (hcl, str, len);
|
||||||
|
return feed_wrap_up(hcl, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int feed_continue (hcl_t* hcl, hcl_feed_lx_state_t state)
|
||||||
|
{
|
||||||
|
hcl->c->feed.lx.state = state;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int feed_continue_with_char (hcl_t* hcl, hcl_ooci_t c, hcl_feed_lx_state_t state)
|
||||||
|
{
|
||||||
|
ADD_TOKEN_CHAR (hcl, c);
|
||||||
|
hcl->c->feed.lx.state = state;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define FEED_WRAP_UP(hcl, type) do { if (feed_wrap_up(hcl, type) <= -1) return -1; } while(0)
|
||||||
|
#define FEED_WRAP_UP_WITH_CHAR(hcl, c, type) do { if (feed_wrap_up_with_char(hcl, c, type) <= -1) return -1; } while(0)
|
||||||
|
#define FEED_WRAP_UP_WITH_CHARS(hcl, str, len, type) do { if (feed_wrap_up_with_str(hcl, str, len, type) <= -1) return -1; } while(0)
|
||||||
|
#define FEED_CONTINUE(hcl, state) do { if (feed_continue(hcl, state) <= -1) return -1; } while(0)
|
||||||
|
#define FEED_CONTINUE_WITH_CHAR(hcl, c, state) do { if (feed_continue_with_char(hcl, c, state) <= -1) return -1; } while(0)
|
||||||
|
|
||||||
|
#define FEED_LX_STATE(hcl) ((hcl)->c->feed.lx.state)
|
||||||
|
#define FEED_LX_LOC(hcl) (&((hcl)->c->feed.lx.loc))
|
||||||
|
|
||||||
|
static int feed_lx_start (hcl_t* hcl, hcl_ooci_t c)
|
||||||
|
{
|
||||||
|
HCL_ASSERT (hcl, FEED_LX_STATE(hcl) == HCL_FEED_LX_START);
|
||||||
|
|
||||||
|
/* clear the token name, reset its location */
|
||||||
|
SET_TOKEN_TYPE (hcl, HCL_IOTOK_EOF); /* is it correct? */
|
||||||
|
CLEAR_TOKEN_NAME (hcl);
|
||||||
|
|
||||||
|
//HCL_DEBUG1 (hcl, "XXX[%jc]\n", c);
|
||||||
|
if (find_delim_token_char(hcl, c, 0, HCL_COUNTOF(delim_token_tab) - 1, 0, &hcl->c->feed.dt))
|
||||||
|
{
|
||||||
|
/* the character is one of the first character of a delimiter token */
|
||||||
|
if (hcl->c->feed.dt.row_start == hcl->c->feed.dt.row_end && hcl->c->feed.dt.col_next == delim_token_tab[hcl->c->feed.dt.row_start].t_len)
|
||||||
|
{
|
||||||
|
FEED_WRAP_UP_WITH_CHAR (hcl, c, delim_token_tab[hcl->c->feed.dt.row_start].t_type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FEED_CONTINUE_WITH_CHAR (hcl, c, HCL_FEED_LX_DELIM_TOKEN); /* consume c and move to HCL_FEED_LX_DELIM_TOKEN state */
|
||||||
|
}
|
||||||
|
goto consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case HCL_OOCI_EOF:
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
#if 0
|
||||||
|
n = end_include(hcl);
|
||||||
|
if (n <= -1) return -1;
|
||||||
|
if (n >= 1) goto retry;
|
||||||
|
#endif
|
||||||
|
FEED_WRAP_UP_WITH_CHARS (hcl, vocas[VOCA_EOF].str, vocas[VOCA_EOF].len, HCL_IOTOK_EOF);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ';':
|
||||||
|
FEED_CONTINUE_WITH_CHAR (hcl, c, HCL_FEED_LX_COMMENT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '#':
|
||||||
|
FEED_CONTINUE_WITH_CHAR (hcl, c, HCL_FEED_LX_SHARP_TOKEN);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
case '\"':
|
||||||
|
if (get_string(hcl, '\"', '\\', 0, 0) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\'':
|
||||||
|
if (get_string(hcl, '\'', '\\', 0, 0) <= -1) return -1;
|
||||||
|
if (hcl->c->tok.name.len != 1)
|
||||||
|
{
|
||||||
|
hcl_setsynerr (hcl, HCL_SYNERR_CHARLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SET_TOKEN_TYPE (hcl, HCL_IOTOK_CHARLIT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '#':
|
||||||
|
if (get_sharp_token(hcl) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '+':
|
||||||
|
case '-':
|
||||||
|
oldc = c;
|
||||||
|
GET_CHAR_TO (hcl, c);
|
||||||
|
if(is_digitchar(c))
|
||||||
|
{
|
||||||
|
unget_char (hcl, &hcl->c->lxc);
|
||||||
|
c = oldc;
|
||||||
|
goto numlit;
|
||||||
|
}
|
||||||
|
else if (c == '#')
|
||||||
|
{
|
||||||
|
int radix;
|
||||||
|
hcl_iolxc_t sharp;
|
||||||
|
|
||||||
|
sharp = hcl->c->lxc; /* back up '#' */
|
||||||
|
|
||||||
|
GET_CHAR_TO (hcl, c);
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'b':
|
||||||
|
radix = 2;
|
||||||
|
goto radnumlit;
|
||||||
|
case 'o':
|
||||||
|
radix = 8;
|
||||||
|
goto radnumlit;
|
||||||
|
case 'x':
|
||||||
|
radix = 16;
|
||||||
|
radnumlit:
|
||||||
|
ADD_TOKEN_CHAR (hcl, oldc);
|
||||||
|
if (get_radix_number(hcl, c, radix) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
unget_char (hcl, &hcl->c->lxc);
|
||||||
|
unget_char (hcl, &sharp);
|
||||||
|
c = oldc;
|
||||||
|
goto ident;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unget_char (hcl, &hcl->c->lxc);
|
||||||
|
c = oldc;
|
||||||
|
goto ident;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
|
numlit:
|
||||||
|
SET_TOKEN_TYPE (hcl, HCL_IOTOK_NUMLIT);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
ADD_TOKEN_CHAR (hcl, c);
|
||||||
|
GET_CHAR_TO (hcl, c);
|
||||||
|
if (TOKEN_TYPE(hcl) == HCL_IOTOK_NUMLIT && c == '.')
|
||||||
|
{
|
||||||
|
SET_TOKEN_TYPE (hcl, HCL_IOTOK_FPDECLIT);
|
||||||
|
ADD_TOKEN_CHAR (hcl, c);
|
||||||
|
GET_CHAR_TO (hcl, c);
|
||||||
|
if (!is_digitchar(c))
|
||||||
|
{
|
||||||
|
/* the first character after the decimal point is not a decimal digit */
|
||||||
|
hcl_setsynerrbfmt (hcl, HCL_SYNERR_NUMLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl), "invalid numeric literal with no digit after decimal point");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_digitchar(c))
|
||||||
|
{
|
||||||
|
unget_char (hcl, &hcl->c->lxc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ident:
|
||||||
|
if (is_delimchar(c))
|
||||||
|
{
|
||||||
|
hcl_setsynerrbfmt (hcl, HCL_SYNERR_ILCHR, TOKEN_LOC(hcl), HCL_NULL, "illegal character %jc encountered", c);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SET_TOKEN_TYPE (hcl, HCL_IOTOK_IDENT);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
ADD_TOKEN_CHAR (hcl, c);
|
||||||
|
GET_CHAR_TO (hcl, c);
|
||||||
|
|
||||||
|
if (c == '.')
|
||||||
|
{
|
||||||
|
hcl_iolxc_t period;
|
||||||
|
hcl_iotok_type_t type;
|
||||||
|
|
||||||
|
type = classify_ident_token(hcl, TOKEN_NAME(hcl));
|
||||||
|
if (type != HCL_IOTOK_IDENT)
|
||||||
|
{
|
||||||
|
SET_TOKEN_TYPE (hcl, type);
|
||||||
|
unget_char (hcl, &hcl->c->lxc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
period = hcl->c->lxc;
|
||||||
|
|
||||||
|
read_more_seg:
|
||||||
|
GET_CHAR_TO (hcl, c);
|
||||||
|
if (!is_delimchar(c))
|
||||||
|
{
|
||||||
|
hcl_oow_t start;
|
||||||
|
hcl_oocs_t seg;
|
||||||
|
|
||||||
|
SET_TOKEN_TYPE (hcl, HCL_IOTOK_IDENT_DOTTED);
|
||||||
|
ADD_TOKEN_CHAR (hcl, '.');
|
||||||
|
|
||||||
|
start = TOKEN_NAME_LEN(hcl);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ADD_TOKEN_CHAR (hcl, c);
|
||||||
|
GET_CHAR_TO (hcl, c);
|
||||||
|
}
|
||||||
|
while (!is_delimchar(c));
|
||||||
|
|
||||||
|
seg.ptr = &TOKEN_NAME_CHAR(hcl,start);
|
||||||
|
seg.len = TOKEN_NAME_LEN(hcl) - start;
|
||||||
|
if (classify_ident_token(hcl, &seg) != HCL_IOTOK_IDENT)
|
||||||
|
{
|
||||||
|
hcl_setsynerr (hcl, HCL_SYNERR_MSEGIDENT, TOKEN_LOC(hcl), TOKEN_NAME(hcl));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '.') goto read_more_seg;
|
||||||
|
|
||||||
|
unget_char (hcl, &hcl->c->lxc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unget_char (hcl, &hcl->c->lxc);
|
||||||
|
unget_char (hcl, &period);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (is_delimchar(c))
|
||||||
|
{
|
||||||
|
unget_char (hcl, &hcl->c->lxc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOKEN_TYPE(hcl) == HCL_IOTOK_IDENT)
|
||||||
|
{
|
||||||
|
hcl_iotok_type_t type;
|
||||||
|
type = classify_ident_token(hcl, TOKEN_NAME(hcl));
|
||||||
|
SET_TOKEN_TYPE (hcl, type);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
consumed:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
not_consumed:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int feed_lx_delim_token (hcl_t* hcl, hcl_ooci_t c)
|
||||||
|
{
|
||||||
|
if (find_delim_token_char(hcl, c, hcl->c->feed.dt.row_start, hcl->c->feed.dt.row_end, hcl->c->feed.dt.col_next, &hcl->c->feed.dt))
|
||||||
|
{
|
||||||
|
if (hcl->c->feed.dt.row_start == hcl->c->feed.dt.row_end && hcl->c->feed.dt.col_next == delim_token_tab[hcl->c->feed.dt.row_start].t_len)
|
||||||
|
{
|
||||||
|
/* complete token and switch to the HCL_FEED_LX_START state */
|
||||||
|
FEED_WRAP_UP_WITH_CHAR (hcl, c, delim_token_tab[hcl->c->feed.dt.row_start].t_type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ADD_TOKEN_CHAR(hcl, c);
|
||||||
|
}
|
||||||
|
goto consumed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* the longest match so far */
|
||||||
|
FEED_WRAP_UP(hcl, delim_token_tab[hcl->c->feed.dt.row_start].t_type);
|
||||||
|
goto not_consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
consumed:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
not_consumed:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int feed_lx_comment (hcl_t* hcl, hcl_ooci_t c)
|
||||||
|
{
|
||||||
|
if (is_linebreak(c)) FEED_CONTINUE (hcl, HCL_FEED_LX_START);
|
||||||
|
return 1; /* consumed */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int feed_lx_sharp_token (hcl_t* hcl, hcl_ooci_t c)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* #xXXXX hexadecimal
|
||||||
|
* #oOOOO octal
|
||||||
|
* #bBBBB binary
|
||||||
|
* #eDDD error
|
||||||
|
* #pHHH smptr
|
||||||
|
* #\C character
|
||||||
|
* #\xHHHH unicode character
|
||||||
|
* #\UHHHH unicode character
|
||||||
|
* #\uHHHH unicode character
|
||||||
|
* #\backspace
|
||||||
|
* #\linefeed
|
||||||
|
* #\newline
|
||||||
|
* #\nul
|
||||||
|
* #\page
|
||||||
|
* #\return
|
||||||
|
* #\rubout
|
||||||
|
* #\space
|
||||||
|
* #\tab
|
||||||
|
* #\vtab
|
||||||
|
* #include
|
||||||
|
* #[ ] byte array
|
||||||
|
* #( ) qlist
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '#':
|
||||||
|
case '!':
|
||||||
|
/* ## comment start
|
||||||
|
* #! also comment start.
|
||||||
|
* ; comment start */
|
||||||
|
FEED_CONTINUE_WITH_CHAR (hcl, c, HCL_FEED_LX_COMMENT);
|
||||||
|
goto consumed;
|
||||||
|
|
||||||
|
case '[':
|
||||||
|
FEED_WRAP_UP_WITH_CHAR (hcl, c, HCL_IOTOK_BAPAREN);
|
||||||
|
goto consumed;
|
||||||
|
|
||||||
|
case '(':
|
||||||
|
FEED_WRAP_UP_WITH_CHAR (hcl, c, HCL_IOTOK_QLPAREN);
|
||||||
|
goto consumed;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// TODO: fix this part
|
||||||
|
if (is_spacechar(c) || c == HCL_UCI_EOF)
|
||||||
|
hcl_setsynerrbfmt (hcl, HCL_SYNERR_HASHLIT, FEED_LX_LOC(hcl), HCL_NULL,
|
||||||
|
"no character after the hash sign");
|
||||||
|
else
|
||||||
|
hcl_setsynerrbfmt (hcl, HCL_SYNERR_HASHLIT, FEED_LX_LOC(hcl), HCL_NULL,
|
||||||
|
"invalid character after the hash sign - %jc", c);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
consumed:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
not_consumed:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int feed_char (hcl_t* hcl, hcl_ooci_t c)
|
||||||
|
{
|
||||||
|
/* TODO: track line number and column number? */
|
||||||
|
switch (FEED_LX_STATE(hcl))
|
||||||
|
{
|
||||||
|
case HCL_FEED_LX_START: return feed_lx_start(hcl, c);
|
||||||
|
case HCL_FEED_LX_DELIM_TOKEN: return feed_lx_delim_token(hcl, c);
|
||||||
|
case HCL_FEED_LX_COMMENT: return feed_lx_comment(hcl, c);
|
||||||
|
case HCL_FEED_LX_SHARP_TOKEN: return feed_lx_sharp_token(hcl, c);
|
||||||
|
|
||||||
|
/*
|
||||||
|
case HCL_FEED_LX_DQSTR:
|
||||||
|
return feed_lx_dqstr(hcl, c);
|
||||||
|
|
||||||
|
case HCL_FEED_LX_SQSTR:
|
||||||
|
return feed_lxsqstr(hcl, c);
|
||||||
|
|
||||||
|
case HCL_FEED_LX_COMMENT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HCL_FEED_LX_CSTR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HCL_FEED_LX_DIRECTIVE:
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* INVALID STATE */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hcl_feed (hcl_t* hcl, const hcl_ooch_t* data, hcl_oow_t len)
|
||||||
|
{
|
||||||
|
/* TODO: need to return the number of processed characters?
|
||||||
|
* need to stop after the first complete expression? */
|
||||||
|
|
||||||
|
hcl_oow_t i;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
for (i = 0; i < len; )
|
||||||
|
{
|
||||||
|
x = feed_char(hcl, data[i]);
|
||||||
|
if (x <= -1) return -1;
|
||||||
|
i += x;
|
||||||
|
if (x > 0)
|
||||||
|
{
|
||||||
|
if (is_linebreak(data[i]))
|
||||||
|
{
|
||||||
|
hcl->c->feed.lx.loc.line++;
|
||||||
|
hcl->c->feed.lx.loc.colm = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hcl->c->feed.lx.loc.colm++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < 1;)
|
||||||
|
{
|
||||||
|
x = feed_char(hcl, HCL_OOCI_EOF);
|
||||||
|
if (x <= -1) return -1;
|
||||||
|
i += x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
hcl_setopt (ON_EXPRESSION CALLBACK??? );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
hcl_feed (hcl, "(hello) (10)", 12);
|
||||||
|
> on_token
|
||||||
|
> on_expression
|
||||||
|
> on_eof
|
||||||
|
|
||||||
|
default callback for on_expression?
|
||||||
|
compile
|
||||||
|
execute??/ if in the interactive mode? (say it's used as a network protocol. execute each expression when received....)
|
||||||
|
|
||||||
|
default callback for on_eof?
|
||||||
|
execute or terminate?
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user