support naming of generating functions, and 0-weighting of symbols
This commit is contained in:
parent
1e95eac6cd
commit
24e9e9de7f
2 changed files with 45 additions and 159 deletions
|
|
@ -1,152 +0,0 @@
|
||||||
//
|
|
||||||
// Created by Mikael Vejdemo Johansson on 4/7/15.
|
|
||||||
//
|
|
||||||
// Intention: read in a parser, generate the system of equations for its
|
|
||||||
// generating functions
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include "../src/backends/contextfree.h"
|
|
||||||
#include "../src/backends/lr.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
static const char *nonterminal_name(const HCFGrammar *g, const HCFChoice *nt)
|
|
||||||
{
|
|
||||||
static char buf[16] = {0}; // 14 characters in base 26 are enough for 64 bits
|
|
||||||
|
|
||||||
// find nt's number in g
|
|
||||||
size_t n = (uintptr_t)h_hashtable_get(g->nts, nt);
|
|
||||||
|
|
||||||
// NB the start symbol (number 0) is always "A".
|
|
||||||
int i;
|
|
||||||
for(i=14; i>=0 && (n>0 || i==14); i--) {
|
|
||||||
buf[i] = 'A' + n%26;
|
|
||||||
n = n/26; // shift one digit
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf+i+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void readsequence(FILE *file, uint32_t *count, uint32_t *length,
|
|
||||||
const HCFGrammar *g, const HCFSequence *seq) {
|
|
||||||
// tally up numbers of choices, and lengths of emitted strings.
|
|
||||||
// Immediately emit any nonterminals encountered.
|
|
||||||
HCFChoice** x = seq->items;
|
|
||||||
|
|
||||||
if (*x == NULL) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
fprintf(file, "1");
|
|
||||||
HCharset cs;
|
|
||||||
unsigned int i, cscount=0;
|
|
||||||
for(; *x; x++) {
|
|
||||||
switch((*x)->type) {
|
|
||||||
case HCF_CHAR:
|
|
||||||
(*length)++;
|
|
||||||
break;
|
|
||||||
case HCF_END:
|
|
||||||
break;
|
|
||||||
case HCF_CHARSET:
|
|
||||||
cs = (*x)->charset;
|
|
||||||
for(i=0; i<256; i++) {
|
|
||||||
if (charset_isset(cs, i)) {
|
|
||||||
cscount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*count *= cscount;
|
|
||||||
break;
|
|
||||||
default: // HCF_CHOICE, non-terminal symbol
|
|
||||||
fprintf(file, "*%s(t)", nonterminal_name(g, *x));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For each nt in g->nts
|
|
||||||
// For each choice in nt->key->seq
|
|
||||||
// For all elements in sequence
|
|
||||||
// Accumulate counts
|
|
||||||
// Accumulate string lengths
|
|
||||||
// Emit count*t^length
|
|
||||||
void h_pprint_gfeqns(FILE *file, const HCFGrammar *g) {
|
|
||||||
if (g->nts->used < 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// determine maximum string length of symbol names
|
|
||||||
int len;
|
|
||||||
size_t s;
|
|
||||||
for(len=1, s=26; s < g->nts->used; len++, s*=26);
|
|
||||||
|
|
||||||
// iterate over g->nts
|
|
||||||
size_t i;
|
|
||||||
HHashTableEntry *hte;
|
|
||||||
for(i=0; i < g->nts->capacity; i++) {
|
|
||||||
for(hte = &g->nts->contents[i]; hte; hte = hte->next) {
|
|
||||||
if (hte->key == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const HCFChoice *nt = hte->key;
|
|
||||||
fprintf(file, "%s(t) = ", nonterminal_name(g, nt));
|
|
||||||
|
|
||||||
|
|
||||||
for(HCFSequence **seq = nt->seq; *seq; seq++) {
|
|
||||||
if (seq != nt->seq) {
|
|
||||||
fprintf(file, " + ");
|
|
||||||
}
|
|
||||||
uint32_t count=1, length=0;
|
|
||||||
readsequence(file, &count, &length, g, *seq);
|
|
||||||
if(count == 1) {
|
|
||||||
if(length == 1) {
|
|
||||||
fprintf(file, "*t");
|
|
||||||
}
|
|
||||||
if(length > 1) {
|
|
||||||
fprintf(file, "*t^%d", length);
|
|
||||||
}
|
|
||||||
} else if(count > 1) {
|
|
||||||
if(length == 0) {
|
|
||||||
fprintf(file, "*%d", count);
|
|
||||||
}
|
|
||||||
if(length == 1) {
|
|
||||||
fprintf(file, "*%d*t", count);
|
|
||||||
}
|
|
||||||
if (length > 1) {
|
|
||||||
fprintf(file, "*%d*t^%d", count, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(file, "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
HAllocator *mm__ = &system_allocator;
|
|
||||||
|
|
||||||
HParser *n = h_ch('n');
|
|
||||||
HParser *E = h_indirect();
|
|
||||||
HParser *T = h_choice(h_sequence(h_ch('('), E, h_ch(')'), NULL), n, NULL);
|
|
||||||
HParser *E_ = h_choice(h_sequence(E, h_ch('-'), T, NULL), T, NULL);
|
|
||||||
h_bind_indirect(E, E_);
|
|
||||||
HParser *p = E;
|
|
||||||
|
|
||||||
HCFGrammar *g = h_cfgrammar_(mm__, h_desugar_augmented(mm__, p));
|
|
||||||
if (g == NULL) {
|
|
||||||
fprintf(stderr, "h_cfgrammar failed\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
printf("\n==== Generating functions ====\n");
|
|
||||||
h_pprint_gfeqns(stdout, g);
|
|
||||||
|
|
||||||
printf("\n==== Grammar ====\n");
|
|
||||||
h_pprint_grammar(stdout, g, 0);
|
|
||||||
}
|
|
||||||
|
|
@ -10,8 +10,30 @@
|
||||||
#include "../src/backends/lr.h"
|
#include "../src/backends/lr.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char *nonterminal_name(const HCFGrammar *g, const HCFChoice *nt)
|
|
||||||
{
|
HAllocator *mm__;
|
||||||
|
|
||||||
|
// If a parser has user_data set, the generating function systems will try
|
||||||
|
// to interpret it as a string:
|
||||||
|
//
|
||||||
|
// If this string for an h_ch starts with the character 0, then that character
|
||||||
|
// will have weight 0 in the generating function.
|
||||||
|
//
|
||||||
|
// Use the remaining string to set the preferred name of that parser in the
|
||||||
|
// generating function.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const char *nonterminal_name(const HCFGrammar *g, const HCFChoice *nt) {
|
||||||
|
if(nt->user_data != NULL) {
|
||||||
|
if(*(char*)(nt->user_data) != '0') {
|
||||||
|
// user_data is a non-empty string
|
||||||
|
return nt->user_data;
|
||||||
|
} else {
|
||||||
|
return nt->user_data+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static char buf[16] = {0}; // 14 characters in base 26 are enough for 64 bits
|
static char buf[16] = {0}; // 14 characters in base 26 are enough for 64 bits
|
||||||
|
|
||||||
// find nt's number in g
|
// find nt's number in g
|
||||||
|
|
@ -38,13 +60,16 @@ void readsequence(FILE *file, uint32_t *count, uint32_t *length,
|
||||||
if (*x == NULL) {
|
if (*x == NULL) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
char has_user_data = (*x)->user_data != NULL && *(char*)(*x)->user_data != 0;
|
||||||
fprintf(file, "1");
|
fprintf(file, "1");
|
||||||
HCharset cs;
|
HCharset cs;
|
||||||
unsigned int i, cscount=0;
|
unsigned int i, cscount=0;
|
||||||
for(; *x; x++) {
|
for(; *x; x++) {
|
||||||
switch((*x)->type) {
|
switch((*x)->type) {
|
||||||
case HCF_CHAR:
|
case HCF_CHAR:
|
||||||
(*length)++;
|
if(!(has_user_data && *(char*)(*x)->user_data == '0')) {
|
||||||
|
(*length)++;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case HCF_END:
|
case HCF_END:
|
||||||
break;
|
break;
|
||||||
|
|
@ -182,7 +207,21 @@ HParser* finkmaoTW() {
|
||||||
h_epsilon_p(),
|
h_epsilon_p(),
|
||||||
NULL);
|
NULL);
|
||||||
h_bind_indirect(pairstar, pstar_);
|
h_bind_indirect(pairstar, pstar_);
|
||||||
return h_sequence(prefix, pairstar, tuck, NULL);
|
|
||||||
|
HParser* tie = h_sequence(prefix, pairstar, tuck, NULL);
|
||||||
|
h_desugar_augmented(mm__, tie);
|
||||||
|
|
||||||
|
|
||||||
|
T->desugared->user_data = "T";
|
||||||
|
W->desugared->user_data = "W";
|
||||||
|
U->desugared->user_data = "0U";
|
||||||
|
prefix->desugared->user_data = "prefix";
|
||||||
|
pair->desugared->user_data = "pair";
|
||||||
|
tuck->desugared->user_data = "tuck";
|
||||||
|
pstar_->desugared->user_data = "pairstar";
|
||||||
|
tie->desugared->user_data = "tie";
|
||||||
|
|
||||||
|
return tie;
|
||||||
}
|
}
|
||||||
|
|
||||||
HParser* depth1TW() {
|
HParser* depth1TW() {
|
||||||
|
|
@ -341,9 +380,8 @@ HParser* depthNTW() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv) {
|
||||||
{
|
mm__ = &system_allocator;
|
||||||
HAllocator *mm__ = &system_allocator;
|
|
||||||
|
|
||||||
HParser *p = finkmaoTW();
|
HParser *p = finkmaoTW();
|
||||||
HCFGrammar *g = h_cfgrammar_(mm__, h_desugar_augmented(mm__, p));
|
HCFGrammar *g = h_cfgrammar_(mm__, h_desugar_augmented(mm__, p));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue