sxpr_parser.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,003 行 · 第 1/2 页
C
1,003 行
static int get_escape(char c, char *d){ int err = 0; switch(c){ case 'a': *d = '\a'; break; case 'b': *d = '\b'; break; case 'f': *d = '\f'; break; case 'n': *d = '\n'; break; case 'r': *d = '\r'; break; case 't': *d = '\t'; break; case 'v': *d = '\v'; break; case c_escape: *d = c_escape; break; case c_single_quote: *d = c_single_quote; break; case c_double_quote: *d = c_double_quote; break; default: err = -EINVAL; } return err;}int Parser_ready(Parser *p){ return CONSP(p->val) || (p->start_state && CONSP(p->start_state->val));}Sxpr Parser_get_val(Parser *p){ Sxpr v = ONONE, w = ONONE; if(CONSP(p->val)){ } else if (p->start_state && CONSP(p->start_state->val)){ p->val = p->start_state->val; p->val = nrev(p->val); p->start_state->val = ONULL; } else { goto exit; } w = p->val; v = CAR(w); p->val = CDR(w); hfree(w); exit: return v;}Sxpr Parser_get_all(Parser *p){ Sxpr v = ONULL; if(CONSP(p->val)){ v = p->val; p->val = ONONE; } else if(p->start_state && CONSP(p->start_state->val)){ v = p->start_state->val; p->start_state->val = ONULL; v = nrev(v); } return v;}static int state_comment(Parser *p, char c){ int err = 0; if(c == '\n' || Parser_at_eof(p)){ Parser_pop(p); } else { err = input_char(p, c); } return err;}static int begin_comment(Parser *p, char c){ int err = 0; err = Parser_push(p, state_comment, "comment"); if(err) goto exit; err = input_char(p, c); exit: return err;}static int end_string(Parser *p){ int err = 0; err = Parser_string(p); if(err) goto exit; err = Parser_return(p); exit: return err;}static int octaldone(Parser *p){ int err = 0; char d = (char)(p->state->ival & 0xff); Parser_pop(p); err = Parser_input_char(p, d); return err;}static int octaldigit(Parser *p, int d){ int err = 0; p->state->ival *= 8; p->state->ival += d; p->state->count++; if(err) goto exit; if(p->state->ival < 0 || p->state->ival > 0xff){ err = Parser_error(p); goto exit; } if(p->state->count == 3){ err = octaldone(p); } exit: return err;}static int state_octal(Parser *p, char c){ int err = 0; if(Parser_at_eof(p)){ err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF); goto exit; } else if('0' <= c && c <= '7'){ err = octaldigit(p, c - '0'); } else { err = octaldone(p); if(err) goto exit; Parser_input_char(p, c); } exit: return err;}static int hexdone(Parser *p){ int err = 0; char d = (char)(p->state->ival & 0xff); Parser_pop(p); err = Parser_input_char(p, d); return err;} static int hexdigit(Parser *p, int d){ int err = 0; p->state->ival *= 16; p->state->ival += d; p->state->count++; if(err) goto exit; if(p->state->ival < 0 || p->state->ival > 0xff){ err = Parser_error(p); goto exit; } if(p->state->count == 2){ err = hexdone(p); } exit: return err;} static int state_hex(Parser *p, char c){ int err = 0; if(Parser_at_eof(p)){ err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF); goto exit; } else if('0' <= c && c <= '9'){ err = hexdigit(p, c - '0'); } else if('A' <= c && c <= 'F'){ err = hexdigit(p, c - 'A' + 10); } else if('a' <= c && c <= 'f'){ err = hexdigit(p, c - 'a' + 10); } else if(p->state->count){ err = hexdone(p); if(err) goto exit; Parser_input_char(p, c); } exit: return err;}static int state_escape(Parser *p, char c){ int err = 0; char d; if(Parser_at_eof(p)){ err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF); goto exit; } if(get_escape(c, &d) == 0){ err = save_char(p, d); if(err) goto exit; Parser_pop(p); } else if(c == 'x'){ p->state->fn = state_hex; p->state->ival = 0; p->state->count = 0; } else { p->state->fn = state_octal; p->state->ival = 0; p->state->count = 0; err = Parser_input_char(p, c); } exit: return err;}static int state_string(Parser *p, char c){ int err = 0; if(Parser_at_eof(p)){ err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF); } else if(c == p->state->delim){ err = end_string(p); } else if(c == '\\'){ err = Parser_push(p, state_escape, "escape"); } else { err = save_char(p, c); } return err;}static int begin_string(Parser *p, char c){ int err = 0; err = Parser_push(p, state_string, "string"); if(err) goto exit; new_token(p); p->state->delim = c; exit: return err;}static int end_atom(Parser *p){ int err = 0; err = Parser_atom(p); if(err) goto exit; err = Parser_return(p); exit: return err;}static int state_atom(Parser *p, char c){ int err = 0; if(Parser_at_eof(p)){ err = end_atom(p); } else if(is_separator(p, c) || in_space_class(c) || in_comment_class(c)){ err = end_atom(p); if(err) goto exit; err = Parser_input_char(p, c); } else { err = save_char(p, c); } exit: return err;}static int begin_atom(Parser *p, char c){ int err = 0; err = Parser_push(p, state_atom, "atom"); if(err) goto exit; new_token(p); err = save_char(p, c); exit: return err;}static int end_data(Parser *p){ int err = 0; err = Parser_data(p); if(err) goto exit; err = Parser_return(p); exit: return err;}static int counted_data(Parser *p, char c){ int err = 0; err = save_char(p, c); if(err) goto exit; if(token_len(p) == p->state->count){ err = end_data(p); } exit: return err;}static int counted_data_count(Parser *p, char c){ int err = 0; if(c == p->state->delim){ new_token(p); p->state->count = p->state->ival; p->state->fn = counted_data; } else if('0' <= c && c <= '9'){ p->state->ival *= 10; p->state->ival += c - '0'; } else { err = -EINVAL; } return err;}static int quoted_data(Parser *p, char c){ int err = 0; int count = p->state->count; err = save_char(p, c); if(err) goto exit; // Check that buf is longer than delim and // ends with delim. If so, trim delim off and return. if((token_len(p) >= count) && !memcmp(p->tok_end - count, p->buf, count)){ p->tok_end -= count; end_data(p); } exit: return err;}static int quoted_data_delim(Parser *p, char c){ // Saves the delim in the token buffer. int err = 0; err = save_char(p, c); if(err) goto exit; if(c == p->state->delim){ p->state->fn = quoted_data; p->state->count = token_len(p); // Advance the token pointer past the delim. p->tok = p->tok_end; } exit: return err;}static int state_data(Parser *p, char c){ // Quoted data: // <<delim< anything not containing delimiter<delim< // Where 'delim' is anything not containing '<'. // Counted data: // <*nnn..* N bytes // Where nnn... is N in decimal ( int err = 0; switch(c){ case c_data_count: p->state->delim = c; p->state->fn = counted_data_count; p->state->ival = 0; new_token(p); break; case c_data_quote: p->state->delim = c; p->state->fn = quoted_data_delim; new_token(p); err = save_char(p, c); break; default: err = Parser_error(p); break; } return err;}static int begin_data(Parser *p, char c){ int err = 0; err = Parser_push(p, state_data, "data"); if(err) goto exit; new_token(p); exit: return err;}static int state_list(Parser *p, char c){ int err = 0; dprintf(">\n"); if(Parser_at_eof(p)){ err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF); } else if(c == c_list_close){ p->state->val = nrev(p->state->val); err = Parser_return(p); } else { err = state_start(p, c); } dprintf("< err=%d\n", err); return err; }static int begin_list(Parser *p, char c){ return Parser_push(p, state_list, "list");}static int state_start(Parser *p, char c){ int err = 0; dprintf(">\n"); if(Parser_at_eof(p)){ err = Parser_return(p); } else if(in_space_class(c)){ //skip } else if(in_comment_class(c)){ begin_comment(p, c); } else if(c == c_list_open){ begin_list(p, c); } else if(c == c_list_close){ err = Parser_error(p); } else if(in_string_quote_class(c)){ begin_string(p, c); } else if(c == c_data_open){ begin_data(p, c); } else if(in_printable_class(c)){ begin_atom(p, c); } else if(c == 0x04){ //ctrl-D, EOT: end-of-text. Parser_input_eof(p); } else { err = Parser_error(p); } dprintf("< err=%d\n", err); return err;}int begin_start(Parser *p, char c){ int err = 0; dprintf(">\n"); err = Parser_push(p, state_start, "start"); if(err) goto exit; p->start_state = p->state; exit: dprintf("< err=%d\n", err); return err;}int Parser_input_char(Parser *p, char c){ int err = 0; if(Parser_at_eof(p)){ //skip; } else { input_char(p, c); } if(!p->state){ err = p->begin(p, c); if(err) goto exit; } err = p->state->fn(p, c); exit: return err;}int Parser_input_eof(Parser *p){ int err = 0; p->eof = 1; err = Parser_input_char(p, IOSTREAM_EOF); return err;}int Parser_input(Parser *p, char *buf, int buf_n){ int err = 0; int i = 0; dprintf("> buf_n=%d\n", buf_n); if(buf_n <= 0){ buf_n = 0; err = Parser_input_eof(p); goto exit; } dprintf("> buf=|%*s|\n", buf_n, buf); for(i = 0; i < buf_n; i++){ err = Parser_input_char(p, buf[i]); if(err) goto exit; } exit: err = (err < 0 ? err : buf_n); dprintf("< err=%d\n", err); return err;}#ifdef SXPR_PARSER_MAIN/* Stuff for standalone testing. */#include "file_stream.h"//#include "string_stream.h"/** Main program for testing. * Parses input and prints it. * * @param argc number of arguments * @param argv arguments * @return error code */int main(int argc, char *argv[]){ Parser *pin; int err = 0; char buf[1024]; int k; Sxpr obj; int i = 0; pin = Parser_new(); Parser_set_error_stream(pin, iostdout); dprintf("> parse...\n"); while(1){ k = fread(buf, 1, 100, stdin); if(k>=0){ buf[k+1] = '\0'; } err = Parser_input(pin, buf, k); while(Parser_ready(pin)){ obj = Parser_get_val(pin); printf("obj %d\n", i++); objprint(iostdout, obj, 0); printf("\n"); } if(k <= 0) break; } dprintf("> err=%d\n", err); return 0;}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?