diff --git a/src/runtime/c/pgf/linearizer.c b/src/runtime/c/pgf/linearizer.c
index 6a3eb8c9d..4bb8e9153 100644
--- a/src/runtime/c/pgf/linearizer.c
+++ b/src/runtime/c/pgf/linearizer.c
@@ -454,19 +454,22 @@ pgf_lzr_concretize(PgfConcr* concr, PgfExpr expr, GuPool* pool)
}
void
-pgf_lzr_linearize_sequence(PgfConcr* concr,
- PgfCncTreeApp* fapp, PgfSequence* seq,
+pgf_lzr_linearize_sequence(PgfConcr* concr, PgfCncTreeApp* fapp,
+ PgfSequence* seq, uint16_t seq_idx,
PgfLinFuncs** fnsp)
{
size_t nsyms = gu_seq_length(seq);
PgfSymbol* syms = gu_seq_data(seq);
- for (size_t i = 0; i < nsyms; i++) {
+ for (size_t i = seq_idx; i < nsyms; i++) {
PgfSymbol sym = syms[i];
GuVariantInfo sym_i = gu_variant_open(sym);
switch (sym_i.tag) {
case PGF_SYMBOL_CAT:
case PGF_SYMBOL_VAR:
case PGF_SYMBOL_LIT: {
+ if (fapp == NULL)
+ return;
+
PgfSymbolIdx* sidx = sym_i.data;
gu_assert((unsigned) sidx->d < fapp->n_args);
@@ -484,11 +487,19 @@ pgf_lzr_linearize_sequence(PgfConcr* concr,
case PGF_SYMBOL_KP: {
// TODO: correct prefix-dependencies
PgfSymbolKP* kp = sym_i.data;
- pgf_lzr_linearize_sequence(concr, fapp, kp->default_form, fnsp);
+ pgf_lzr_linearize_sequence(concr, fapp, kp->default_form, 0, fnsp);
break;
}
case PGF_SYMBOL_NE: {
- // Nothing to be done here
+ if ((*fnsp)->symbol_ne) {
+ (*fnsp)->symbol_ne(fnsp);
+ }
+ break;
+ }
+ case PGF_SYMBOL_BIND: {
+ if ((*fnsp)->symbol_bind) {
+ (*fnsp)->symbol_bind(fnsp);
+ }
break;
}
default:
@@ -518,7 +529,7 @@ pgf_lzr_linearize(PgfConcr* concr, PgfCncTree ctree, size_t lin_idx, PgfLinFuncs
gu_require(lin_idx < fun->n_lins);
PgfSequence* seq = fun->lins[lin_idx];
- pgf_lzr_linearize_sequence(concr, fapp, seq, fnsp);
+ pgf_lzr_linearize_sequence(concr, fapp, seq, 0, fnsp);
if (fns->end_phrase) {
fns->end_phrase(fnsp,
@@ -572,11 +583,22 @@ typedef struct PgfSimpleLin PgfSimpleLin;
struct PgfSimpleLin {
PgfLinFuncs* funcs;
- int n_tokens;
+ bool bind;
GuOut* out;
GuExn* err;
};
+GU_DEFINE_TYPE(PgfLinNonExist, abstract, _);
+
+static void
+pgf_file_lzn_put_space(PgfSimpleLin* flin)
+{
+ if (flin->bind)
+ flin->bind = false;
+ else
+ gu_putc(' ', flin->out, flin->err);
+}
+
static void
pgf_file_lzn_symbol_token(PgfLinFuncs** funcs, PgfToken tok)
{
@@ -584,12 +606,9 @@ pgf_file_lzn_symbol_token(PgfLinFuncs** funcs, PgfToken tok)
if (!gu_ok(flin->err)) {
return;
}
- if (flin->n_tokens > 0)
- gu_putc(' ', flin->out, flin->err);
+ pgf_file_lzn_put_space(flin);
gu_string_write(tok, flin->out, flin->err);
-
- flin->n_tokens++;
}
static void
@@ -600,8 +619,7 @@ pgf_file_lzn_expr_literal(PgfLinFuncs** funcs, PgfLiteral lit)
return;
}
- if (flin->n_tokens > 0)
- gu_putc(' ', flin->out, flin->err);
+ pgf_file_lzn_put_space(flin);
GuVariantInfo i = gu_variant_open(lit);
switch (i.tag) {
@@ -623,8 +641,20 @@ pgf_file_lzn_expr_literal(PgfLinFuncs** funcs, PgfLiteral lit)
default:
gu_impossible();
}
+}
- flin->n_tokens++;
+static void
+pgf_file_lzn_symbol_ne(PgfLinFuncs** funcs)
+{
+ PgfSimpleLin* flin = gu_container(funcs, PgfSimpleLin, funcs);
+ gu_raise(flin->err, PgfLinNonExist);
+}
+
+static void
+pgf_file_lzn_symbol_bind(PgfLinFuncs** funcs)
+{
+ PgfSimpleLin* flin = gu_container(funcs, PgfSimpleLin, funcs);
+ flin->bind = true;
}
static PgfLinFuncs pgf_file_lin_funcs = {
@@ -632,6 +662,8 @@ static PgfLinFuncs pgf_file_lin_funcs = {
.expr_literal = pgf_file_lzn_expr_literal,
.begin_phrase = NULL,
.end_phrase = NULL,
+ .symbol_ne = pgf_file_lzn_symbol_ne,
+ .symbol_bind = pgf_file_lzn_symbol_bind
};
void
@@ -640,9 +672,34 @@ pgf_lzr_linearize_simple(PgfConcr* concr, PgfCncTree ctree,
{
PgfSimpleLin flin = {
.funcs = &pgf_file_lin_funcs,
- .n_tokens = 0,
+ .bind = true,
.out = out,
.err = err
};
pgf_lzr_linearize(concr, ctree, lin_idx, &flin.funcs);
}
+
+GuString
+pgf_get_tokens(PgfSequence* seq, uint16_t seq_idx, GuPool* pool)
+{
+ GuPool* tmp_pool = gu_new_pool();
+ GuExn* err = gu_new_exn(NULL, gu_kind(type), tmp_pool);
+ GuStringBuf* sbuf = gu_string_buf(tmp_pool);
+ GuOut* out = gu_string_buf_out(sbuf);
+
+ PgfSimpleLin flin = {
+ .funcs = &pgf_file_lin_funcs,
+ .bind = true,
+ .out = out,
+ .err = err
+ };
+
+ pgf_lzr_linearize_sequence(NULL, NULL, seq, seq_idx, &flin.funcs);
+
+ GuString tokens = gu_ok(err) ? gu_string_buf_freeze(sbuf, pool)
+ : gu_empty_string;
+
+ gu_pool_free(tmp_pool);
+
+ return tokens;
+}
diff --git a/src/runtime/c/pgf/linearizer.h b/src/runtime/c/pgf/linearizer.h
index ea240dc32..63ab2705a 100644
--- a/src/runtime/c/pgf/linearizer.h
+++ b/src/runtime/c/pgf/linearizer.h
@@ -1,21 +1,5 @@
-/*
- * Copyright 2010-2011 University of Helsinki.
- *
- * This file is part of libpgf.
- *
- * Libpgf is free software: you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation, either version 3 of the License, or (at your
- * option) any later version.
- *
- * Libpgf is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with libpgf. If not, see .
- */
+#ifndef PGF_LINEARIZER_H_
+#define PGF_LINEARIZER_H_
#include
#include
@@ -46,6 +30,11 @@ typedef GuEnum PgfCncTreeEnum;
PgfCncTreeEnum*
pgf_lzr_concretize(PgfConcr* concr, PgfExpr expr, GuPool* pool);
+typedef struct {
+} PgfLinNonExist;
+
+extern GU_DECLARE_TYPE(PgfLinNonExist, abstract);
+
typedef struct PgfLinFuncs PgfLinFuncs;
struct PgfLinFuncs
@@ -61,6 +50,12 @@ struct PgfLinFuncs
/// End phrase
void (*end_phrase)(PgfLinFuncs** self, PgfCId cat, int fid, int lindex, PgfCId fun);
+
+ /// handling nonExist
+ void (*symbol_ne)(PgfLinFuncs** self);
+
+ /// token binding
+ void (*symbol_bind)(PgfLinFuncs** self);
};
@@ -76,3 +71,10 @@ pgf_lzr_linearize(PgfConcr* concr, PgfCncTree ctree, size_t lin_idx,
void
pgf_lzr_linearize_simple(PgfConcr* concr, PgfCncTree ctree,
size_t lin_idx, GuOut* out, GuExn* err);
+#endif
+
+#ifdef PGF_PARSER_H_
+// Used internally in the parser
+GuString
+pgf_get_tokens(PgfSequence* seq, uint16_t seq_idx, GuPool* pool);
+#endif
diff --git a/src/runtime/c/pgf/parser.c b/src/runtime/c/pgf/parser.c
index 188672dd3..c83873b5e 100644
--- a/src/runtime/c/pgf/parser.c
+++ b/src/runtime/c/pgf/parser.c
@@ -1,4 +1,5 @@
#include
+#include
#include
#include
@@ -1734,38 +1735,6 @@ typedef struct {
PgfParseState* state;
} PgfPrefixTokenState;
-static GuString
-pgf_get_tokens(PgfSequence* seq, uint16_t seq_idx, GuPool* pool)
-{
- GuPool* tmp_pool = gu_new_pool();
- GuExn* err = gu_new_exn(NULL, gu_kind(type), tmp_pool);
- GuStringBuf* sbuf = gu_string_buf(tmp_pool);
- GuOut* out = gu_string_buf_out(sbuf);
-
- // collect the tokens in the production
- size_t len = gu_seq_length(seq);
- for (size_t i = seq_idx; i < len; i++) {
- PgfSymbol sym = gu_seq_get(seq, PgfSymbol, i);
-
- GuVariantInfo i = gu_variant_open(sym);
- switch (i.tag) {
- case PGF_SYMBOL_KS: {
- PgfSymbolKS* symks = i.data;
- gu_string_write(symks->token, out, err);
- }
- default:
- goto end;
- }
- }
-
-end:;
- GuString tokens = gu_string_buf_freeze(sbuf, pool);
-
- gu_pool_free(tmp_pool);
-
- return tokens;
-}
-
static bool
pgf_prefix_match_token(PgfTokenState* ts0, PgfToken tok, PgfItem* item)
{
diff --git a/src/runtime/python/pypgf.c b/src/runtime/python/pypgf.c
index b5ff53af0..a76344ca7 100644
--- a/src/runtime/python/pypgf.c
+++ b/src/runtime/python/pypgf.c
@@ -1378,8 +1378,12 @@ Concr_linearize(ConcrObject* self, PyObject *args)
pgf_linearize(self->concr, pyexpr->expr, out, err);
if (!gu_ok(err)) {
- PyErr_SetString(PGFError, "The abstract tree cannot be linearized");
- return NULL;
+ if (gu_exn_caught(err) == gu_type(PgfLinNonExist))
+ Py_RETURN_NONE;
+ else {
+ PyErr_SetString(PGFError, "The abstract tree cannot be linearized");
+ return NULL;
+ }
}
GuString str = gu_string_buf_freeze(sbuf, tmp_pool);