picrin/src/parse.y

452 lines
7.4 KiB
Plaintext
Raw Normal View History

2014-01-17 06:58:31 -05:00
/**
* See Copyright Notice in picrin.h
*/
2013-10-11 02:18:37 -04:00
%{
#include <stdlib.h>
2013-11-15 05:40:31 -05:00
#include <string.h>
2013-10-11 02:18:37 -04:00
#include "picrin.h"
2013-10-19 23:34:57 -04:00
#include "picrin/pair.h"
#include "picrin/string.h"
#include "picrin/vector.h"
2013-11-04 22:38:23 -05:00
#include "picrin/blob.h"
#include "picrin/parse.h"
2013-10-11 02:18:37 -04:00
2013-10-17 04:57:12 -04:00
#define YYERROR_VERBOSE 1
2013-11-15 05:40:31 -05:00
/* just for supressing warnings. a little bit evil */
int yylex();
int yylex_();
2014-02-01 05:33:23 -05:00
void yylex_init_extra();
2013-11-15 05:40:31 -05:00
void yyset_in();
void yy_scan_string();
void yylex_destroy();
#define YY_ARENA_SIZE 50
2013-10-22 14:45:57 -04:00
2013-11-15 05:40:31 -05:00
struct parser_control *
parser_control_new(pic_state *pic)
{
struct parser_control *p;
p = (struct parser_control *)pic_alloc(pic, sizeof(struct parser_control));
p->pic = pic;
p->incomp = false;
p->yynerrs = 0;
2013-11-17 03:33:28 -05:00
p->value = pic_undef_value();
2013-11-15 05:40:31 -05:00
p->yy_arena = pic_vec_new(pic, YY_ARENA_SIZE);
p->yy_arena_idx = 0;
2014-02-01 05:33:23 -05:00
yylex_init_extra(p, &p->yyscanner);
2013-11-15 05:40:31 -05:00
return p;
}
void
parser_control_destroy(struct parser_control *p)
{
pic_state *pic = p->pic;
yylex_destroy(p->yyscanner);
pic_free(pic, p);
}
void
yy_obj_protect(struct parser_control *p, struct pic_object *obj)
{
if (p->yy_arena_idx >= p->yy_arena->len) {
pic_vec_extend_ip(p->pic, p->yy_arena, p->yy_arena->len * 2);
}
p->yy_arena->data[p->yy_arena_idx++] = pic_obj_value(obj);
}
struct pic_object *
yy_obj_alloc(struct parser_control *p, size_t size, enum pic_tt tt)
{
struct pic_object *obj;
obj = pic_obj_alloc_unsafe(p->pic, size, tt);
yy_obj_protect(p, obj);
return obj;
}
pic_value
yy_cons(struct parser_control *p, pic_value car, pic_value cdr)
{
struct pic_pair *pair;
pair = (struct pic_pair *)yy_obj_alloc(p, sizeof(struct pic_pair), PIC_TT_PAIR);
pair->car = car;
pair->cdr = cdr;
return pic_obj_value(pair);
}
pic_value
yy_abbrev(struct parser_control *p, pic_sym sym, pic_value datum)
{
return yy_cons(p, pic_symbol_value(sym), yy_cons(p, datum, pic_nil_value()));
}
pic_value
yy_str_new_cstr(struct parser_control *p, const char *cstr)
{
struct pic_string *str;
str = (struct pic_string *)yy_obj_alloc(p, sizeof(struct pic_string), PIC_TT_STRING);
str->len = strlen(cstr);
2014-02-01 05:33:23 -05:00
str->str = pic_strdup(p->pic, cstr);
2013-11-15 05:40:31 -05:00
return pic_obj_value(str);
}
pic_value
yy_vec_new_from_list(struct parser_control *p, pic_value data)
{
struct pic_vector *vec;
int i, len;
len = pic_length(p->pic, data);
vec = (struct pic_vector *)yy_obj_alloc(p, sizeof(struct pic_vector), PIC_TT_VECTOR);
vec->len = len;
vec->data = (pic_value *)pic_alloc(p->pic, sizeof(pic_value) * len);
for (i = 0; i < len; ++i) {
vec->data[i] = pic_car(p->pic, data);
data = pic_cdr(p->pic, data);
}
return pic_obj_value(vec);
}
pic_value
yy_blob_new(struct parser_control *p, char *dat, int len)
{
struct pic_blob *bv;
bv = (struct pic_blob *)yy_obj_alloc(p, sizeof(struct pic_blob), PIC_TT_BLOB);
2014-02-01 05:33:23 -05:00
bv->data = pic_strndup(p->pic, dat, len);
2013-11-15 05:40:31 -05:00
bv->len = len;
return pic_obj_value(bv);
}
void yyerror(struct parser_control *, const char *);
2013-10-11 02:18:37 -04:00
%}
2013-11-18 06:24:09 -05:00
%pure-parser
2013-10-11 02:18:37 -04:00
%parse-param {struct parser_control *p}
%lex-param {struct parser_control *p}
%union {
int i;
double f;
char *cstr;
2013-11-04 21:37:18 -05:00
char c;
2013-11-04 22:38:23 -05:00
struct {
char *dat;
int len, capa;
} blob;
2013-10-11 02:18:37 -04:00
pic_value datum;
}
2013-11-14 03:31:40 -05:00
%token tDATUM_COMMENT
2013-11-10 21:57:01 -05:00
%token tLPAREN tRPAREN tLBRACKET tRBRACKET tDOT tVPAREN
2013-10-22 23:39:48 -04:00
%token tQUOTE tQUASIQUOTE tUNQUOTE tUNQUOTE_SPLICING
%token <i> tINT tBOOLEAN
%token <f> tFLOAT
%token <cstr> tSYMBOL tSTRING
2013-11-04 21:37:18 -05:00
%token <c> tCHAR
2013-11-04 22:38:23 -05:00
%token <blob> tBYTEVECTOR
2013-10-11 02:18:37 -04:00
%type <datum> program_data
2013-10-20 21:48:03 -04:00
%type <datum> datum simple_datum compound_datum abbrev
2013-10-29 02:51:37 -04:00
%type <datum> list list_data vector vector_data
2013-10-11 02:18:37 -04:00
%%
program
: program_data
2013-10-11 02:18:37 -04:00
{
p->value = $1;
2013-10-11 02:18:37 -04:00
}
| incomplete_program_data
2013-10-17 07:48:50 -04:00
{
p->incomp = true;
p->value = pic_undef_value();
}
2013-11-14 03:31:40 -05:00
| /* empty line */
2013-11-13 03:37:05 -05:00
{
p->value = pic_nil_value();
}
2013-10-11 02:18:37 -04:00
;
program_data
: datum
{
2013-11-15 05:40:31 -05:00
$$ = yy_cons(p, $1, pic_nil_value());
}
| datum program_data
{
2013-11-15 05:40:31 -05:00
$$ = yy_cons(p, $1, $2);
}
2013-11-14 03:31:40 -05:00
| tDATUM_COMMENT datum
{
$$ = pic_nil_value();
}
;
incomplete_program_data
: incomplete_datum
| datum incomplete_program_data
;
2013-10-11 02:18:37 -04:00
datum
: simple_datum
| compound_datum
2013-11-14 03:31:40 -05:00
| tDATUM_COMMENT datum datum
{
$$ = $3;
}
2013-10-11 02:18:37 -04:00
;
simple_datum
: tSYMBOL
{
2013-10-28 13:11:31 -04:00
$$ = pic_symbol_value(pic_intern_cstr(p->pic, $1));
free($1);
}
2013-10-20 21:48:03 -04:00
| tSTRING
{
2013-11-15 05:40:31 -05:00
$$ = yy_str_new_cstr(p, $1);
free($1);
}
| tINT
{
$$ = pic_int_value($1);
}
| tFLOAT
{
$$ = pic_float_value($1);
}
| tBOOLEAN
{
$$ = pic_bool_value($1);
}
2013-11-04 21:37:18 -05:00
| tCHAR
{
$$ = pic_char_value($1);
}
2013-11-04 22:38:23 -05:00
| tBYTEVECTOR
{
2013-11-15 05:40:31 -05:00
$$ = yy_blob_new(p, $1.dat, $1.len);
2013-11-04 22:38:23 -05:00
free($1.dat);
}
2013-10-16 00:17:01 -04:00
;
2013-10-11 02:18:37 -04:00
compound_datum
: list
2013-10-29 02:51:37 -04:00
| vector
2013-10-20 20:29:56 -04:00
| abbrev
2013-10-11 02:18:37 -04:00
;
list
2013-10-17 05:14:18 -04:00
: tLPAREN list_data tRPAREN
2013-10-11 02:18:37 -04:00
{
$$ = $2;
}
2013-11-10 21:57:01 -05:00
| tLBRACKET list_data tRBRACKET
{
$$ = $2;
}
2013-10-11 02:18:37 -04:00
;
2013-10-17 05:14:18 -04:00
list_data
: /* none */
2013-10-11 02:18:37 -04:00
{
$$ = pic_nil_value();
}
2013-11-14 03:31:40 -05:00
| tDATUM_COMMENT datum
{
$$ = pic_nil_value();
}
2013-10-17 05:14:18 -04:00
| datum tDOT datum
2013-10-11 02:18:37 -04:00
{
2013-11-15 05:40:31 -05:00
$$ = yy_cons(p, $1, $3);
2013-10-11 02:18:37 -04:00
}
2013-10-17 05:14:18 -04:00
| datum list_data
2013-10-11 02:18:37 -04:00
{
2013-11-15 05:40:31 -05:00
$$ = yy_cons(p, $1, $2);
2013-10-11 02:18:37 -04:00
}
;
2013-10-29 02:51:37 -04:00
vector
: tVPAREN vector_data tRPAREN
{
2013-11-15 05:40:31 -05:00
$$ = yy_vec_new_from_list(p, $2);
2013-10-29 02:51:37 -04:00
}
;
vector_data
: /* none */
{
$$ = pic_nil_value();
}
2013-11-14 03:31:40 -05:00
| tDATUM_COMMENT datum
{
$$ = pic_nil_value();
}
2013-10-29 02:51:37 -04:00
| datum vector_data
{
2013-11-15 05:40:31 -05:00
$$ = yy_cons(p, $1, $2);
2013-10-29 02:51:37 -04:00
}
;
2013-10-20 20:29:56 -04:00
abbrev
: tQUOTE datum
{
2013-11-15 05:40:31 -05:00
$$ = yy_abbrev(p, p->pic->sQUOTE, $2);
2013-10-22 23:39:48 -04:00
}
| tQUASIQUOTE datum
{
2013-11-15 05:40:31 -05:00
$$ = yy_abbrev(p, p->pic->sQUASIQUOTE, $2);
2013-10-22 23:39:48 -04:00
}
| tUNQUOTE datum
{
2013-11-15 05:40:31 -05:00
$$ = yy_abbrev(p, p->pic->sUNQUOTE, $2);
2013-10-22 23:39:48 -04:00
}
| tUNQUOTE_SPLICING datum
{
2013-11-15 05:40:31 -05:00
$$ = yy_abbrev(p, p->pic->sUNQUOTE_SPLICING, $2);
2013-10-20 20:29:56 -04:00
}
;
2013-10-17 07:48:50 -04:00
incomplete_datum
2013-10-26 13:06:59 -04:00
: tLPAREN incomplete_data
2013-11-10 21:57:01 -05:00
| tLBRACKET incomplete_data
2013-10-29 02:51:37 -04:00
| tVPAREN incomplete_data
2013-10-22 23:39:48 -04:00
| incomplete_abbrev
2013-11-14 03:31:40 -05:00
| tDATUM_COMMENT
2013-10-17 07:48:50 -04:00
;
2013-10-26 13:06:59 -04:00
incomplete_tail
: /* none */
| incomplete_datum
;
2013-10-17 07:48:50 -04:00
incomplete_data
2013-10-26 13:06:59 -04:00
: incomplete_tail
| datum tDOT incomplete_tail
2013-10-17 07:48:50 -04:00
| datum incomplete_data
;
2013-10-22 23:39:48 -04:00
incomplete_abbrev
2013-10-26 13:06:59 -04:00
: tQUOTE incomplete_tail
| tQUASIQUOTE incomplete_tail
| tUNQUOTE incomplete_tail
| tUNQUOTE_SPLICING incomplete_tail
2013-10-22 23:39:48 -04:00
;
2013-10-11 02:18:37 -04:00
%%
2013-10-19 14:05:42 -04:00
void
2013-10-11 02:18:37 -04:00
yyerror(struct parser_control *p, const char *msg)
{
puts(msg);
2013-10-22 14:13:10 -04:00
p->yynerrs++;
2013-10-11 02:18:37 -04:00
}
2013-10-22 14:45:57 -04:00
int
yylex(YYSTYPE *yylvalp, struct parser_control *p)
{
return yylex_(yylvalp, p->yyscanner);
2013-10-22 14:45:57 -04:00
}
int
2013-10-27 05:38:41 -04:00
pic_parse_file(pic_state *pic, FILE *file, pic_value *v)
{
2013-11-15 05:40:31 -05:00
struct parser_control *p;
int r, ai = pic_gc_arena_preserve(pic);
2013-10-27 05:38:41 -04:00
2013-11-15 05:40:31 -05:00
p = parser_control_new(pic);
2013-10-27 05:38:41 -04:00
2013-11-15 05:40:31 -05:00
yyset_in(file, p->yyscanner);
yyparse(p);
2013-10-27 05:38:41 -04:00
2013-11-15 05:40:31 -05:00
if (p->yynerrs > 0) {
r = PIC_PARSER_ERROR;
2013-10-27 05:38:41 -04:00
}
2013-11-15 05:40:31 -05:00
else if (p->incomp) {
r = PIC_PARSER_INCOMPLETE;
}
else {
r = pic_length(pic, p->value);
}
2013-11-17 03:33:28 -05:00
*v = p->value;
2013-11-15 05:40:31 -05:00
parser_control_destroy(p);
#if DEBUG
if (pic_gc_arena_preserve(pic) != ai + 1) {
puts("**logic flaw! yy obj protection failure!**");
2013-10-27 05:38:41 -04:00
}
2013-11-15 05:40:31 -05:00
#endif
2013-11-15 05:40:31 -05:00
pic_gc_arena_restore(pic, ai);
2013-11-17 03:33:28 -05:00
pic_gc_protect(pic, *v);
2013-11-15 05:40:31 -05:00
return r;
2013-10-27 05:38:41 -04:00
}
2013-11-13 03:37:05 -05:00
enum pic_parser_res
2013-10-27 05:38:41 -04:00
pic_parse_cstr(pic_state *pic, const char *str, pic_value *v)
2013-10-11 02:18:37 -04:00
{
2013-11-15 05:40:31 -05:00
struct parser_control *p;
int r, ai = pic_gc_arena_preserve(pic);
2013-10-11 02:18:37 -04:00
2013-11-15 05:40:31 -05:00
p = parser_control_new(pic);
2013-10-11 02:18:37 -04:00
2013-11-15 05:40:31 -05:00
yy_scan_string(str, p->yyscanner);
yyparse(p);
2013-10-11 02:18:37 -04:00
2013-11-15 05:40:31 -05:00
if (p->yynerrs > 0) {
r = PIC_PARSER_ERROR;
}
else if (p->incomp) {
r = PIC_PARSER_INCOMPLETE;
}
else {
r = pic_length(pic, p->value);
2013-10-17 04:57:12 -04:00
}
2013-11-15 05:40:31 -05:00
2013-11-17 03:33:28 -05:00
*v = p->value;
2013-11-15 05:40:31 -05:00
parser_control_destroy(p);
#if DEBUG
if (pic_gc_arena_preserve(pic) != ai + 1) {
puts("**logic flaw! yy obj protection failure!**");
printf("%d\n", pic_gc_arena_preserve(pic));
2013-10-17 07:48:50 -04:00
}
2013-11-15 05:40:31 -05:00
#endif
pic_gc_arena_restore(pic, ai);
2013-11-17 03:33:28 -05:00
pic_gc_protect(pic, *v);
2013-11-15 05:40:31 -05:00
return r;
2013-10-11 02:18:37 -04:00
}
2013-12-07 21:38:47 -05:00
pic_value
pic_parse(pic_state *pic, const char *src)
{
pic_value vs;
int r;
r = pic_parse_cstr(pic, src, &vs);
if (r != 1) {
return pic_undef_value();
}
return pic_car(pic, vs);
}