mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-23 19:42:50 -06:00
a very simple linearization for partial abstract trees in the C runtime
This commit is contained in:
@@ -108,6 +108,7 @@ struct PgfLzn {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PGF_CNC_TREE_APP,
|
PGF_CNC_TREE_APP,
|
||||||
|
PGF_CNC_TREE_CHUNKS,
|
||||||
PGF_CNC_TREE_LIT,
|
PGF_CNC_TREE_LIT,
|
||||||
} PgfCncTreeTag;
|
} PgfCncTreeTag;
|
||||||
|
|
||||||
@@ -117,6 +118,11 @@ typedef struct {
|
|||||||
PgfCncTree args[];
|
PgfCncTree args[];
|
||||||
} PgfCncTreeApp;
|
} PgfCncTreeApp;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GuLength n_args;
|
||||||
|
PgfCncTree args[];
|
||||||
|
} PgfCncTreeChunks;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PgfLiteral lit;
|
PgfLiteral lit;
|
||||||
} PgfCncTreeLit;
|
} PgfCncTreeLit;
|
||||||
@@ -127,11 +133,6 @@ pgf_print_cnc_tree(PgfCncTree ctree, GuWriter* wtr, GuExn* err)
|
|||||||
{
|
{
|
||||||
GuVariantInfo ti = gu_variant_open(ctree);
|
GuVariantInfo ti = gu_variant_open(ctree);
|
||||||
switch (ti.tag) {
|
switch (ti.tag) {
|
||||||
case PGF_CNC_TREE_LIT: {
|
|
||||||
PgfCncTreeLit* clit = ti.data;
|
|
||||||
pgf_print_literal(clit->lit, wtr, err);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PGF_CNC_TREE_APP: {
|
case PGF_CNC_TREE_APP: {
|
||||||
PgfCncTreeApp* capp = ti.data;
|
PgfCncTreeApp* capp = ti.data;
|
||||||
if (capp->n_args > 0) gu_putc('(', wtr, err);
|
if (capp->n_args > 0) gu_putc('(', wtr, err);
|
||||||
@@ -143,6 +144,25 @@ pgf_print_cnc_tree(PgfCncTree ctree, GuWriter* wtr, GuExn* err)
|
|||||||
if (capp->n_args > 0) gu_putc(')', wtr, err);
|
if (capp->n_args > 0) gu_putc(')', wtr, err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PGF_CNC_TREE_CHUNKS: {
|
||||||
|
PgfCncTreeChunks* chunks = ti.data;
|
||||||
|
if (chunks->n_args > 0) gu_putc('(', wtr, err);
|
||||||
|
gu_putc('?', wtr, err);
|
||||||
|
for (size_t i = 0; i < chunks->n_args; i++) {
|
||||||
|
gu_putc(' ', wtr, err);
|
||||||
|
pgf_print_cnc_tree(chunks->args[i], wtr, err);
|
||||||
|
}
|
||||||
|
if (chunks->n_args > 0) gu_putc(')', wtr, err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PGF_CNC_TREE_LIT: {
|
||||||
|
PgfCncTreeLit* clit = ti.data;
|
||||||
|
pgf_print_literal(clit->lit, wtr, err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GU_VARIANT_NULL:
|
||||||
|
gu_puts("null", wtr, err);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
gu_impossible();
|
gu_impossible();
|
||||||
}
|
}
|
||||||
@@ -292,13 +312,34 @@ pgf_lzn_resolve(PgfLzn* lzn, PgfExpr expr, PgfCCat* ccat, GuPool* pool)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
case PGF_EXPR_META: {
|
case PGF_EXPR_META: {
|
||||||
if (ccat == NULL || ccat->lindefs == NULL) {
|
if (ccat == NULL) {
|
||||||
|
size_t n_args = gu_buf_length(args);
|
||||||
|
|
||||||
|
PgfCncTreeChunks* chunks =
|
||||||
|
gu_new_flex_variant(PGF_CNC_TREE_CHUNKS,
|
||||||
|
PgfCncTreeChunks,
|
||||||
|
args, n_args, &ret, pool);
|
||||||
|
chunks->n_args = n_args;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n_args; i++) {
|
||||||
|
PgfExpr earg = gu_buf_get(args, PgfExpr, n_args-i-1);
|
||||||
|
chunks->args[i] = pgf_lzn_resolve(lzn, earg, NULL, pool);
|
||||||
|
if (gu_variant_is_null(chunks->args[i])) {
|
||||||
|
ret = gu_null_variant;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
} else {
|
||||||
|
if (ccat->lindefs == NULL) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuString s = gu_str_string("?", pool);
|
||||||
|
ret = pgf_lzn_resolve_def(lzn, ccat->lindefs, s, pool);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
GuString s = gu_str_string("?", pool);
|
|
||||||
ret = pgf_lzn_resolve_def(lzn, ccat->lindefs, s, pool);
|
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
case PGF_EXPR_FUN: {
|
case PGF_EXPR_FUN: {
|
||||||
PgfExprFun* efun = i.data;
|
PgfExprFun* efun = i.data;
|
||||||
@@ -318,7 +359,7 @@ pgf_lzn_resolve(PgfLzn* lzn, PgfExpr expr, PgfCCat* ccat, GuPool* pool)
|
|||||||
gu_putc('[', wtr, err);
|
gu_putc('[', wtr, err);
|
||||||
gu_string_write(efun->fun, wtr, err);
|
gu_string_write(efun->fun, wtr, err);
|
||||||
gu_putc(']', wtr, err);
|
gu_putc(']', wtr, err);
|
||||||
GuString s = gu_string_buf_freeze(sbuf, tmp_pool);
|
GuString s = gu_string_buf_freeze(sbuf, pool);
|
||||||
|
|
||||||
ret = pgf_lzn_resolve_def(lzn, ccat->lindefs, s, pool);
|
ret = pgf_lzn_resolve_def(lzn, ccat->lindefs, s, pool);
|
||||||
|
|
||||||
@@ -399,23 +440,6 @@ pgf_lzr_concretize(PgfConcr* concr, PgfExpr expr, GuPool* pool)
|
|||||||
return &lzn->en;
|
return &lzn->en;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
pgf_cnc_tree_dimension(PgfCncTree ctree)
|
|
||||||
{
|
|
||||||
GuVariantInfo cti = gu_variant_open(ctree);
|
|
||||||
switch (cti.tag) {
|
|
||||||
case PGF_CNC_TREE_LIT:
|
|
||||||
return 1;
|
|
||||||
case PGF_CNC_TREE_APP: {
|
|
||||||
PgfCncTreeApp* fapp = cti.data;
|
|
||||||
return fapp->fun->n_lins;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
gu_impossible();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pgf_lzr_linearize(PgfConcr* concr, PgfCncTree ctree, size_t lin_idx, PgfLinFuncs** fnsp)
|
pgf_lzr_linearize(PgfConcr* concr, PgfCncTree ctree, size_t lin_idx, PgfLinFuncs** fnsp)
|
||||||
{
|
{
|
||||||
@@ -423,14 +447,6 @@ pgf_lzr_linearize(PgfConcr* concr, PgfCncTree ctree, size_t lin_idx, PgfLinFuncs
|
|||||||
GuVariantInfo cti = gu_variant_open(ctree);
|
GuVariantInfo cti = gu_variant_open(ctree);
|
||||||
|
|
||||||
switch (cti.tag) {
|
switch (cti.tag) {
|
||||||
case PGF_CNC_TREE_LIT: {
|
|
||||||
gu_require(lin_idx == 0);
|
|
||||||
PgfCncTreeLit* flit = cti.data;
|
|
||||||
if (fns->expr_literal) {
|
|
||||||
fns->expr_literal(fnsp, flit->lit);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PGF_CNC_TREE_APP: {
|
case PGF_CNC_TREE_APP: {
|
||||||
PgfCncTreeApp* fapp = cti.data;
|
PgfCncTreeApp* fapp = cti.data;
|
||||||
PgfCncFun* fun = fapp->fun;
|
PgfCncFun* fun = fapp->fun;
|
||||||
@@ -475,7 +491,23 @@ pgf_lzr_linearize(PgfConcr* concr, PgfCncTree ctree, size_t lin_idx, PgfLinFuncs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} // case PGF_CNC_TREE_APP
|
}
|
||||||
|
case PGF_CNC_TREE_CHUNKS: {
|
||||||
|
gu_require(lin_idx == 0);
|
||||||
|
PgfCncTreeChunks* fchunks = cti.data;
|
||||||
|
for (size_t i = 0; i < fchunks->n_args; i++) {
|
||||||
|
pgf_lzr_linearize(concr, fchunks->args[i], 0, fnsp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PGF_CNC_TREE_LIT: {
|
||||||
|
gu_require(lin_idx == 0);
|
||||||
|
PgfCncTreeLit* flit = cti.data;
|
||||||
|
if (fns->expr_literal) {
|
||||||
|
fns->expr_literal(fnsp, flit->lit);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
gu_impossible();
|
gu_impossible();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,24 +48,6 @@ typedef GuEnum PgfCncTreeEnum;
|
|||||||
PgfCncTreeEnum*
|
PgfCncTreeEnum*
|
||||||
pgf_lzr_concretize(PgfConcr* concr, PgfExpr expr, GuPool* pool);
|
pgf_lzr_concretize(PgfConcr* concr, PgfExpr expr, GuPool* pool);
|
||||||
|
|
||||||
/** @}
|
|
||||||
*
|
|
||||||
* @name Linearizing concrete syntax trees
|
|
||||||
*
|
|
||||||
* An individual concrete syntax tree has several different
|
|
||||||
* linearizations, corresponding to the various fields and cases of
|
|
||||||
* corresponding GF values. The number of these linearizations, called
|
|
||||||
* the \e dimension of the tree, can be retrieved with
|
|
||||||
* #pgf_cnc_tree_dimension.
|
|
||||||
*
|
|
||||||
* A single linearization of a concrete syntax tree is performed by
|
|
||||||
* #pgf_lzr_linearize. The linearization is realized as a sequence of
|
|
||||||
* events that are notified by calling the functions of a #PgfLinFuncs
|
|
||||||
* structure that the client provides.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// Callback functions for linearization.
|
/// Callback functions for linearization.
|
||||||
typedef struct PgfLinFuncs PgfLinFuncs;
|
typedef struct PgfLinFuncs PgfLinFuncs;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user