diff --git a/src/runtime/c/pgf/data.cxx b/src/runtime/c/pgf/data.cxx index 00db1a0a9..6c58fa1d2 100644 --- a/src/runtime/c/pgf/data.cxx +++ b/src/runtime/c/pgf/data.cxx @@ -42,4 +42,24 @@ void PgfPGF::release(ref pgf) void PgfConcr::release(ref concr) { namespace_release(concr->cflags); + namespace_release(concr->lins); + namespace_release(concr->lincats); + namespace_release(concr->printnames); +} + +void PgfConcrLin::release(ref lin) +{ + PgfDB::free(lin->args); + PgfDB::free(lin->res); + PgfDB::free(lin->seqs); +} + +void PgfConcrLincat::release(ref lincat) +{ + PgfDB::free(lincat->fields); +} + +void PgfConcrPrintname::release(ref printname) +{ + PgfDB::free(printname->printname); } diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index d19a1e4e3..bdae8a366 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -876,6 +876,9 @@ PgfConcrRevision pgf_create_concrete(PgfDB *db, PgfRevision revision, concr->ref_count = 1; concr->ref_count_ex = 1; concr->cflags = 0; + concr->lins = 0; + concr->lincats = 0; + concr->printnames = 0; concr->prev = 0; concr->next = 0; memcpy(&concr->name, name, sizeof(PgfText)+name->size+1); @@ -912,6 +915,9 @@ PgfConcrRevision pgf_clone_concrete(PgfDB *db, PgfRevision revision, clone->ref_count = 1; clone->ref_count_ex = 1; clone->cflags = concr->cflags; + clone->lins = concr->lins; + clone->lincats = concr->lincats; + clone->printnames = concr->printnames; clone->prev = 0; clone->next = 0; memcpy(&clone->name, name, sizeof(PgfText)+name->size+1); diff --git a/src/runtime/c/pgf/reader.cxx b/src/runtime/c/pgf/reader.cxx index 5e892ef3e..62c2cb161 100644 --- a/src/runtime/c/pgf/reader.cxx +++ b/src/runtime/c/pgf/reader.cxx @@ -6,6 +6,8 @@ PgfReader::PgfReader(FILE *in) { this->in = in; + this->abstract = 0; + this->concrete = 0; } uint8_t PgfReader::read_uint8() @@ -425,18 +427,198 @@ ref PgfReader::read_abscat() void PgfReader::read_abstract(ref abstract) { + this->abstract = abstract; + abstract->name = read_name(); abstract->aflags = read_namespace(&PgfReader::read_flag); abstract->funs = read_namespace(&PgfReader::read_absfun); abstract->cats = read_namespace(&PgfReader::read_abscat); } +ref PgfReader::read_lindex() +{ + size_t i0 = read_int(); + size_t n_terms = read_len(); + ref lindex = + PgfDB::malloc(n_terms*sizeof(PgfConcrLIndex::terms[0])); + lindex->i0 = i0; + lindex->n_terms = n_terms; + + for (size_t i = 0; i < n_terms; i++) { + lindex->terms[i].factor = read_int(); + lindex->terms[i].var = read_int(); + } + + return lindex; +} + +void PgfReader::read_linarg(ref linarg) +{ + size_t size = read_len(); + PgfText* name = (PgfText*) alloca(sizeof(PgfText)+size+1); + name->size = size; + + // If reading the extra bytes causes EOF, it is an encoding + // error, not a legitimate end of character stream. + fread(name->text, size, 1, in); + if (feof(in)) + throw pgf_error("utf8 decoding error"); + if (ferror(in)) + throw pgf_error("an error occured while reading the grammar"); + + name->text[size] = 0; + + + linarg->lincat = namespace_lookup(this->concrete->lincats, name); + if (linarg->lincat == 0) + throw pgf_error("Encountered an unknown category"); + linarg->param = read_lindex(); +} + +void PgfReader::read_linres(ref linres) +{ + size_t size = read_len(); + PgfText* name = (PgfText*) alloca(sizeof(PgfText)+size+1); + name->size = size; + + // If reading the extra bytes causes EOF, it is an encoding + // error, not a legitimate end of character stream. + fread(name->text, size, 1, in); + if (feof(in)) + throw pgf_error("utf8 decoding error"); + if (ferror(in)) + throw pgf_error("an error occured while reading the grammar"); + + name->text[size] = 0; + + + linres->lincat = namespace_lookup(this->concrete->lincats, name); + if (linres->lincat == 0) + throw pgf_error("Encountered an unknown category"); + linres->param = read_lindex(); +} + +template +ref PgfReader::read_symbol_idx() +{ + size_t d = read_int(); + size_t i0 = read_int(); + size_t n_terms = read_len(); + ref sym_idx = + PgfDB::malloc(n_terms*sizeof(PgfConcrLIndex::terms[0])); + sym_idx->d = d; + sym_idx->r.i0 = i0; + sym_idx->r.n_terms = n_terms; + + for (size_t i = 0; i < n_terms; i++) { + sym_idx->r.terms[i].factor = read_int(); + sym_idx->r.terms[i].var = read_int(); + } + + return sym_idx; +} + +PgfSymbol PgfReader::read_symbol() +{ + PgfSymbol sym = 0; + + uint8_t tag = read_tag(); + switch (tag) { + case PgfSymbolCat::tag: { + ref sym_cat = read_symbol_idx(); + sym = ref::tagged(sym_cat); + break; + } + case PgfSymbolLit::tag: { + ref sym_lit = read_symbol_idx(); + sym = ref::tagged(sym_lit); + break; + } + case PgfSymbolVar::tag: { + ref sym_var = PgfDB::malloc(); + sym_var->d = read_int(); + sym_var->r = read_int(); + sym = ref::tagged(sym_var); + break; + } + case PgfSymbolKS::tag: { + ref sym_ks = read_text(&PgfSymbolKS::token); + sym = ref::tagged(sym_ks); + break; + } + case PgfSymbolKP::tag: { + ref sym_kp = PgfDB::malloc(); + sym = ref::tagged(sym_kp); + break; + } + case PgfSymbolBIND::tag: { + sym = ref::tagged(0); + break; + } + case PgfSymbolSOFTBIND::tag: { + sym = ref::tagged(0); + break; + } + case PgfSymbolNE::tag: { + sym = ref::tagged(0); + break; + } + case PgfSymbolSOFTSPACE::tag: { + sym = ref::tagged(0); + break; + } + case PgfSymbolCAPIT::tag: { + sym = ref::tagged(0); + break; + } + case PgfSymbolALLCAPIT::tag: { + sym = ref::tagged(0); + break; + } + default: + throw pgf_error("Unknown symbol tag"); + } + + return sym; +} + +ref PgfReader::read_lincat() +{ + ref lincat = read_name(&PgfConcrLincat::name); + lincat->ref_count = 1; + lincat->fields = read_vector(&PgfReader::read_text2); + return lincat; +} + +ref PgfReader::read_lin() +{ + ref lin = read_name(&PgfConcrLin::name); + lin->ref_count = 1; + lin->args = read_vector(&PgfReader::read_linarg); + lin->res = read_vector(&PgfReader::read_linres); + lin->seqs = read_vector(&PgfReader::read_seq2); + return lin; +} + +ref PgfReader::read_printname() +{ + ref printname = read_name(&PgfConcrPrintname::name); + printname->ref_count = 1; + printname->printname = read_text(); + return printname; +} + ref PgfReader::read_concrete() { ref concr = read_name(&PgfConcr::name); + this->concrete = concr; + concr->ref_count = 1; concr->ref_count_ex = 0; concr->cflags = read_namespace(&PgfReader::read_flag); + concr->lincats = read_namespace(&PgfReader::read_lincat); + concr->lins = read_namespace(&PgfReader::read_lin); + concr->printnames = read_namespace(&PgfReader::read_printname); concr->prev = 0; concr->next = 0; return concr; diff --git a/src/runtime/c/pgf/reader.h b/src/runtime/c/pgf/reader.h index c3570c85b..537f94ee4 100644 --- a/src/runtime/c/pgf/reader.h +++ b/src/runtime/c/pgf/reader.h @@ -60,23 +60,39 @@ public: ref read_flag(); PgfPatt read_patt(); - void read_patt2(ref r) { *r = read_patt(); }; - void read_defn(ref> defn); ref read_absfun(); ref read_abscat(); void read_abstract(ref abstract); + ref read_lincat(); + ref read_lindex(); + void read_linarg(ref linarg); + void read_linres(ref linres); + PgfSymbol read_symbol(); + ref read_lin(); + ref read_printname(); + ref read_concrete(); ref read_pgf(); private: FILE *in; + ref abstract; + ref concrete; object read_name_internal(size_t struct_size); object read_text_internal(size_t struct_size); + + void read_patt2(ref r) { *r = read_patt(); }; + void read_text2(ref> r) { *r = read_text(); }; + void read_symbol2(ref r) { *r = read_symbol(); }; + void read_seq2(ref> r) { *r = read_vector(&PgfReader::read_symbol2); } + + template + ref read_symbol_idx(); }; #endif diff --git a/src/runtime/c/pgf/writer.cxx b/src/runtime/c/pgf/writer.cxx index feebfb186..e5006c859 100644 --- a/src/runtime/c/pgf/writer.cxx +++ b/src/runtime/c/pgf/writer.cxx @@ -385,10 +385,105 @@ void PgfWriter::write_abstract(ref abstract) this->abstract = 0; } +void PgfWriter::write_lincat(ref lincat) +{ + write_name(&lincat->name); + write_vector(lincat->fields, &PgfWriter::write_text); +} + +void PgfWriter::write_lindex(ref lindex) +{ + write_int(lindex->i0); + write_len(lindex->n_terms); + for (size_t i = 0; i < lindex->n_terms; i++) { + write_int(lindex->terms[i].factor); + write_int(lindex->terms[i].var); + } +} + +void PgfWriter::write_linarg(ref linarg) +{ + write_name(&linarg->lincat->name); + write_lindex(linarg->param); +} + +void PgfWriter::write_linres(ref linres) +{ + write_name(&linres->lincat->name); + write_lindex(linres->param); +} + +void PgfWriter::write_symbol(PgfSymbol sym) +{ + auto tag = ref::get_tag(sym); + write_tag(tag); + + switch (tag) { + case PgfSymbolCat::tag: { + auto sym_cat = ref::untagged(sym); + write_int(sym_cat->d); + write_lindex(ref::from_ptr(&sym_cat->r)); + break; + } + case PgfSymbolLit::tag: { + auto sym_lit = ref::untagged(sym); + write_int(sym_lit->d); + write_lindex(ref::from_ptr(&sym_lit->r)); + break; + } + case PgfSymbolVar::tag: { + auto sym_var = ref::untagged(sym); + write_int(sym_var->d); + write_int(sym_var->r); + break; + } + case PgfSymbolKS::tag: { + auto sym_ks = ref::untagged(sym); + write_text(&sym_ks->token); + break; + } + case PgfSymbolKP::tag: { + auto sym_ks = ref::untagged(sym); + break; + } + case PgfSymbolBIND::tag: + case PgfSymbolSOFTBIND::tag: + case PgfSymbolNE::tag: + case PgfSymbolSOFTSPACE::tag: + case PgfSymbolCAPIT::tag: + case PgfSymbolALLCAPIT::tag: + break; + default: + throw pgf_error("Unknown symbol tag"); + } +} + +void PgfWriter::write_seq(ref seq) +{ + write_vector(seq, &PgfWriter::write_symbol); +} + +void PgfWriter::write_lin(ref lin) +{ + write_name(&lin->name); + write_vector(lin->args, &PgfWriter::write_linarg); + write_vector(lin->res, &PgfWriter::write_linres); + write_vector(lin->seqs, &PgfWriter::write_seq); +} + +void PgfWriter::write_printname(ref printname) +{ + write_name(&printname->name); + write_text(printname->printname); +} + void PgfWriter::write_concrete(ref concr) { write_name(&concr->name); write_namespace(concr->cflags, &PgfWriter::write_flag); + write_namespace(concr->lincats, &PgfWriter::write_lincat); + write_namespace(concr->lins, &PgfWriter::write_lin); + write_namespace(concr->printnames, &PgfWriter::write_printname); } void PgfWriter::write_pgf(ref pgf) diff --git a/src/runtime/c/pgf/writer.h b/src/runtime/c/pgf/writer.h index 3fcca4483..1d961a591 100644 --- a/src/runtime/c/pgf/writer.h +++ b/src/runtime/c/pgf/writer.h @@ -33,7 +33,6 @@ public: void write_type(ref ty); void write_patt(PgfPatt patt); - void write_patt(ref r) { write_patt(*r); }; void write_defn(ref> r); void write_flag(ref flag); @@ -42,6 +41,15 @@ public: void write_abscat(ref abscat); void write_abstract(ref abstract); + void write_lincat(ref lincat); + void write_lindex(ref lindex); + void write_linarg(ref linarg); + void write_linres(ref linres); + void write_symbol(PgfSymbol sym); + void write_seq(ref seq); + void write_lin(ref lin); + void write_printname(ref printname); + void write_concrete(ref concr); void write_pgf(ref pgf); @@ -50,6 +58,11 @@ private: template void write_namespace_helper(Namespace nmsp, void (PgfWriter::*write_value)(ref)); + void write_patt(ref r) { write_patt(*r); }; + void write_text(ref> r) { write_text(&(**r)); }; + void write_seq(ref> r) { write_seq(*r); }; + void write_symbol(ref r) { write_symbol(*r); }; + FILE *out; ref abstract; };