mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-08-19 10:46:22 -06:00
handle empty variants
This commit is contained in:
@@ -56,7 +56,7 @@ PgfLinearizer::TreeNode::TreeNode(PgfLinearizer *linearizer)
|
||||
linearizer->prev = this;
|
||||
}
|
||||
|
||||
void PgfLinearizer::TreeNode::linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r)
|
||||
bool PgfLinearizer::TreeNode::linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r)
|
||||
{
|
||||
TreeNode *arg = args;
|
||||
while (d > 0) {
|
||||
@@ -67,7 +67,7 @@ void PgfLinearizer::TreeNode::linearize_arg(PgfLinearizationOutputIface *out, Pg
|
||||
}
|
||||
if (arg == NULL)
|
||||
throw pgf_error("Missing argument");
|
||||
arg->linearize(out, linearizer, r);
|
||||
return arg->linearize(out, linearizer, r);
|
||||
}
|
||||
|
||||
void PgfLinearizer::TreeNode::linearize_var(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r)
|
||||
@@ -87,7 +87,7 @@ void PgfLinearizer::TreeNode::linearize_var(PgfLinearizationOutputIface *out, Pg
|
||||
out->symbol_token(linearizer->printer.get_text());
|
||||
}
|
||||
|
||||
void PgfLinearizer::TreeNode::linearize_item(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, Item *item, vector<PgfSymbol> syms)
|
||||
bool PgfLinearizer::TreeNode::linearize_item(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, Item *item, vector<PgfSymbol> syms)
|
||||
{
|
||||
for (size_t i = 0; i < syms.size(); i++) {
|
||||
PgfSymbol sym = syms[i];
|
||||
@@ -96,13 +96,15 @@ void PgfLinearizer::TreeNode::linearize_item(PgfLinearizationOutputIface *out, P
|
||||
case PgfSymbolCat::tag: {
|
||||
auto sym_cat = ref<PgfSymbolCat>::untagged(sym);
|
||||
size_t r = item->eval(ref<PgfLParam>::from_ptr(&sym_cat->r));
|
||||
linearize_arg(out, linearizer, sym_cat->d, r);
|
||||
if (!linearize_arg(out, linearizer, sym_cat->d, r))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case PgfSymbolLit::tag: {
|
||||
auto sym_lit = ref<PgfSymbolLit>::untagged(sym);
|
||||
size_t r = item->eval(ref<PgfLParam>::from_ptr(&sym_lit->r));
|
||||
linearize_arg(out, linearizer, sym_lit->d, r);
|
||||
if (!linearize_arg(out, linearizer, sym_lit->d, r))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case PgfSymbolVar::tag: {
|
||||
@@ -205,6 +207,8 @@ void PgfLinearizer::TreeNode::linearize_item(PgfLinearizationOutputIface *out, P
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PgfLinearizer::TreeLinNode::TreeLinNode(PgfLinearizer *linearizer, ref<PgfConcrLin> lin)
|
||||
@@ -261,13 +265,6 @@ bool PgfLinearizer::TreeLinNode::resolve(PgfLinearizer *linearizer)
|
||||
rule_index++;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < lin->lincat->fields.size(); i++) {
|
||||
if (items[i] == NULL) {
|
||||
rule_index = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -276,8 +273,11 @@ bool PgfLinearizer::TreeLinNode::check_category(PgfLinearizer *linearizer, PgfTe
|
||||
return (textcmp(&lin->absfun->type->name, cat) == 0);
|
||||
}
|
||||
|
||||
void PgfLinearizer::TreeLinNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex)
|
||||
bool PgfLinearizer::TreeLinNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex)
|
||||
{
|
||||
if (items[lindex] == NULL)
|
||||
return false;
|
||||
|
||||
PgfText *cat = &lin->absfun->type->name;
|
||||
PgfText *field = &*lin->lincat->fields[lindex];
|
||||
|
||||
@@ -294,8 +294,9 @@ void PgfLinearizer::TreeLinNode::linearize(PgfLinearizationOutputIface *out, Pgf
|
||||
linearizer->pre_stack->bracket_stack = bracket;
|
||||
}
|
||||
|
||||
linearize_item(out, linearizer,
|
||||
items[lindex],items[lindex]->rule->syms.as_vector());
|
||||
if (!linearize_item(out, linearizer,
|
||||
items[lindex],items[lindex]->rule->syms.as_vector()))
|
||||
return false;
|
||||
|
||||
if (linearizer->pre_stack == NULL)
|
||||
out->end_phrase(cat, fid, field, &lin->name);
|
||||
@@ -309,6 +310,8 @@ void PgfLinearizer::TreeLinNode::linearize(PgfLinearizationOutputIface *out, Pgf
|
||||
bracket->fun = &lin->name;
|
||||
linearizer->pre_stack->bracket_stack = bracket;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ref<PgfConcrLincat> PgfLinearizer::TreeLinNode::get_lincat(PgfLinearizer *linearizer)
|
||||
@@ -410,23 +413,24 @@ bool PgfLinearizer::TreeLindefNode::check_category(PgfLinearizer *linearizer, Pg
|
||||
return true;
|
||||
}
|
||||
|
||||
void PgfLinearizer::TreeLindefNode::linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r)
|
||||
bool PgfLinearizer::TreeLindefNode::linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r)
|
||||
{
|
||||
linearizer->flush_pre_stack(out, literal);
|
||||
out->symbol_token(literal);
|
||||
|
||||
TreeNode *arg = args;
|
||||
while (arg != NULL) {
|
||||
arg->linearize(out,linearizer,0);
|
||||
if (!arg->linearize(out,linearizer,0))
|
||||
return false;
|
||||
arg = arg->next_arg;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PgfLinearizer::TreeLindefNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex)
|
||||
bool PgfLinearizer::TreeLindefNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex)
|
||||
{
|
||||
if (lincat==0) {
|
||||
linearize_arg(out, linearizer, 0, 0);
|
||||
return;
|
||||
return linearize_arg(out, linearizer, 0, 0);
|
||||
}
|
||||
|
||||
PgfText *cat = &lincat->name;
|
||||
@@ -445,8 +449,9 @@ void PgfLinearizer::TreeLindefNode::linearize(PgfLinearizationOutputIface *out,
|
||||
linearizer->pre_stack->bracket_stack = bracket;
|
||||
}
|
||||
|
||||
linearize_item(out, linearizer,
|
||||
items[lindex],items[lindex]->rule->syms.as_vector());
|
||||
if (!linearize_item(out, linearizer,
|
||||
items[lindex],items[lindex]->rule->syms.as_vector()))
|
||||
return false;
|
||||
|
||||
if (linearizer->pre_stack == NULL)
|
||||
out->end_phrase(cat, fid, field, linearizer->wild);
|
||||
@@ -460,6 +465,7 @@ void PgfLinearizer::TreeLindefNode::linearize(PgfLinearizationOutputIface *out,
|
||||
bracket->fun = linearizer->wild;
|
||||
linearizer->pre_stack->bracket_stack = bracket;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ref<PgfConcrLincat> PgfLinearizer::TreeLindefNode::get_lincat(PgfLinearizer *linearizer)
|
||||
@@ -537,13 +543,13 @@ bool PgfLinearizer::TreeLinrefNode::resolve(PgfLinearizer *linearizer)
|
||||
return true;
|
||||
}
|
||||
|
||||
void PgfLinearizer::TreeLinrefNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex)
|
||||
bool PgfLinearizer::TreeLinrefNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex)
|
||||
{
|
||||
ref<PgfConcrLincat> lincat = args->get_lincat(linearizer);
|
||||
if (lincat != 0) {
|
||||
linearize_item(out, linearizer, item, item->rule->syms.as_vector());
|
||||
return linearize_item(out, linearizer, item, item->rule->syms.as_vector());
|
||||
} else {
|
||||
args->linearize(out, linearizer, lindex);
|
||||
return args->linearize(out, linearizer, lindex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,7 +575,7 @@ bool PgfLinearizer::TreeLitNode::check_category(PgfLinearizer *linearizer, PgfTe
|
||||
return (textcmp(&lincat->name, cat) == 0);
|
||||
}
|
||||
|
||||
void PgfLinearizer::TreeLitNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex)
|
||||
bool PgfLinearizer::TreeLitNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex)
|
||||
{
|
||||
PgfText *field = NULL;
|
||||
if (lincat != 0) {
|
||||
@@ -583,6 +589,8 @@ void PgfLinearizer::TreeLitNode::linearize(PgfLinearizationOutputIface *out, Pgf
|
||||
out->symbol_token(literal);
|
||||
if (lincat != 0)
|
||||
out->end_phrase(&lincat->name, fid, field, linearizer->wild);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ref<PgfConcrLincat> PgfLinearizer::TreeLitNode::get_lincat(PgfLinearizer *linearizer)
|
||||
|
||||
@@ -83,10 +83,10 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller {
|
||||
TreeNode(PgfLinearizer *linearizer);
|
||||
virtual bool resolve(PgfLinearizer *linearizer) { return true; };
|
||||
virtual bool check_category(PgfLinearizer *linearizer, PgfText *cat)=0;
|
||||
virtual void linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r);
|
||||
virtual bool linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r);
|
||||
virtual void linearize_var(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r);
|
||||
virtual void linearize_item(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, Item *item, vector<PgfSymbol> syms);
|
||||
virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex)=0;
|
||||
virtual bool linearize_item(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, Item *item, vector<PgfSymbol> syms);
|
||||
virtual bool linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex)=0;
|
||||
virtual ref<PgfConcrLincat> get_lincat(PgfLinearizer *linearizer)=0;
|
||||
virtual ~TreeNode() { free(hoas_vars); };
|
||||
};
|
||||
@@ -99,7 +99,7 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller {
|
||||
TreeLinNode(PgfLinearizer *linearizer, ref<PgfConcrLin> lin);
|
||||
virtual bool resolve(PgfLinearizer *linearizer);
|
||||
virtual bool check_category(PgfLinearizer *linearizer, PgfText *cat);
|
||||
virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex);
|
||||
virtual bool linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex);
|
||||
virtual ref<PgfConcrLincat> get_lincat(PgfLinearizer *linearizer);
|
||||
virtual ~TreeLinNode();
|
||||
};
|
||||
@@ -114,8 +114,8 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller {
|
||||
TreeLindefNode(PgfLinearizer *linearizer, PgfText *fun, PgfText *lit);
|
||||
virtual bool resolve(PgfLinearizer *linearizer);
|
||||
virtual bool check_category(PgfLinearizer *linearizer, PgfText *cat);
|
||||
virtual void linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r);
|
||||
virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex);
|
||||
virtual bool linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, size_t r);
|
||||
virtual bool linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex);
|
||||
virtual ref<PgfConcrLincat> get_lincat(PgfLinearizer *linearizer);
|
||||
~TreeLindefNode();
|
||||
};
|
||||
@@ -127,7 +127,7 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller {
|
||||
TreeLinrefNode(PgfLinearizer *linearizer, TreeNode *root);
|
||||
virtual bool resolve(PgfLinearizer *linearizer);
|
||||
virtual bool check_category(PgfLinearizer *linearizer, PgfText *cat) { return true; };
|
||||
virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex);
|
||||
virtual bool linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex);
|
||||
virtual ref<PgfConcrLincat> get_lincat(PgfLinearizer *linearizer);
|
||||
~TreeLinrefNode();
|
||||
};
|
||||
@@ -138,7 +138,7 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller {
|
||||
|
||||
TreeLitNode(PgfLinearizer *linearizer, ref<PgfConcrLincat> lincat, PgfText *lit);
|
||||
virtual bool check_category(PgfLinearizer *linearizer, PgfText *cat);
|
||||
virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex);
|
||||
virtual bool linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex);
|
||||
virtual ref<PgfConcrLincat> get_lincat(PgfLinearizer *linearizer);
|
||||
~TreeLitNode() { free(literal); };
|
||||
};
|
||||
@@ -147,7 +147,7 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller {
|
||||
TreeChunksNode(PgfLinearizer *linearizer);
|
||||
virtual bool resolve(PgfLinearizer *linearizer);
|
||||
virtual bool check_category(PgfLinearizer *linearizer, PgfText *cat);
|
||||
virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex);
|
||||
virtual bool linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex);
|
||||
virtual ref<PgfConcrLincat> get_lincat(PgfLinearizer *linearizer);
|
||||
};
|
||||
|
||||
@@ -191,9 +191,11 @@ public:
|
||||
|
||||
bool resolve();
|
||||
void reverse_and_label(bool add_linref);
|
||||
void linearize(PgfLinearizationOutputIface *out, size_t lindex) {
|
||||
prev->linearize(out, this, lindex);
|
||||
bool linearize(PgfLinearizationOutputIface *out, size_t lindex) {
|
||||
if (!prev->linearize(out, this, lindex))
|
||||
return false;
|
||||
flush_pre_stack(out, NULL);
|
||||
return true;
|
||||
}
|
||||
ref<PgfConcrLincat> get_lincat() {
|
||||
return prev->get_lincat(this);
|
||||
|
||||
@@ -2530,7 +2530,10 @@ PgfText *pgf_linearize(PgfDB *db, PgfConcrRevision revision,
|
||||
m->match_expr(&linearizer, expr);
|
||||
linearizer.reverse_and_label(true);
|
||||
if (linearizer.resolve()) {
|
||||
linearizer.linearize(&out, 0);
|
||||
if (!linearizer.linearize(&out, 0)) {
|
||||
free(out.get_text());
|
||||
return NULL;
|
||||
}
|
||||
return out.get_text();
|
||||
}
|
||||
} PGF_API_END
|
||||
@@ -2594,12 +2597,13 @@ PgfText **pgf_tabular_linearize(PgfDB *db, PgfConcrRevision revision,
|
||||
throw pgf_systemerror(ENOMEM);
|
||||
size_t pos = 0;
|
||||
for (size_t i = 0; i < lincat->fields.size(); i++) {
|
||||
linearizer.linearize(&out, i);
|
||||
|
||||
bool ok = linearizer.linearize(&out, i);
|
||||
PgfText *text = out.get_text();
|
||||
if (text != NULL) {
|
||||
if (ok) {
|
||||
res[pos++] = textdup(&*lincat->fields[i]);
|
||||
res[pos++] = text;
|
||||
} else {
|
||||
free(text);
|
||||
}
|
||||
}
|
||||
res[pos++] = NULL;
|
||||
|
||||
Reference in New Issue
Block a user