123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- %{
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- typedef struct _term term_t;
- struct _term {
- int kind;
- union {
- char c;
- char* s;
- term_t* t;
- } u;
- term_t* next;
- };
- static FILE* outf;
- static int yylex ();
- static void yyerror (char*);
- static void xlate (term_t* ts);
- static void
- nonTerm (char* s)
- {
- fprintf (outf, "<I>%s</I>", s);
- }
- static void
- gen (char* name, term_t* ts)
- {
- fprintf (outf, "<TR>\n <TD STYLE=\"text-align: right;\">");
- nonTerm (name);
- fprintf (outf, "</TD>\n <TD>:</TD>\n <TD>");
- xlate (ts);
- fprintf (outf, "</TD>\n</TR>\n");
- for (ts = ts->next; ts; ts = ts->next) {
- fprintf (outf, "<TR>\n <TD></TD>\n <TD>|</TD>\n <TD>");
- xlate (ts);
- fprintf (outf, "</TD>\n</TR>\n");
- }
- }
- static term_t*
- mkLiteral (char c, int kind)
- {
- term_t* nt = malloc(sizeof(term_t));
- nt->kind = kind;
- nt->u.c = c;
- nt->next = 0;
- return nt;
- }
- static term_t*
- mkID (char* s, int kind)
- {
- term_t* nt = malloc(sizeof(term_t));
- nt->kind = kind;
- nt->u.s = s;
- nt->next = 0;
- return nt;
- }
- static term_t*
- mkSeq (term_t* t1, term_t* t2, int kind)
- {
- term_t* nt = malloc(sizeof(term_t));
- nt->kind = kind;
- nt->u.t = t1;
- t1->next = t2;
- nt->next = 0;
- return nt;
- }
- static term_t*
- mkTerm (term_t* t, int kind)
- {
- term_t* nt = malloc(sizeof(term_t));
- nt->kind = kind;
- nt->u.t = t;
- nt->next = 0;
- return nt;
- }
- %}
- %union {
- char c;
- char* str;
- term_t* term;
- }
- %token <c> T_literal
- %token <str> T_name T_token T_opt T_seq T_choice
- %type <term> atomterm term rule rulelist
- %start prods
- %%
- prods : prods prod
- | prod
- ;
- prod : T_name '=' rulelist '\n'
- { gen ($1, $3); }
- rulelist : rule '|' rulelist { $1->next = $3; $$ = $1; }
- | rule { $$ = $1; }
- ;
- rule : term rule
- { if ($2->kind == T_seq) { $1->next = $2->u.t; $2->u.t = $1; $$ = $2;}
- else $$ = mkSeq ($1, $2, T_seq); }
- | term { $$ = $1; }
- ;
- term : '[' rule ']' { $$ = mkTerm ($2, T_opt); }
- | '(' rulelist ')' { $$ = mkTerm ($2, T_choice); }
- | atomterm { $$ = $1; }
- ;
- atomterm : T_literal { $$ = mkLiteral($1, T_literal); }
- | T_token { $$ = mkID($1, T_token); }
- | T_name { $$ = mkID($1, T_name); }
- ;
- %%
- static void
- xlate (term_t* ts)
- {
- term_t* t;
- switch (ts->kind) {
- case T_name :
- nonTerm (ts->u.s);
- break;
- case T_literal :
- fprintf (outf, "<B>'%c'</B>", ts->u.c);
- break;
- case T_token :
- fprintf (outf, "<B>%s</B>", ts->u.s);
- break;
- case T_opt :
- fprintf (outf, "[ ");
- xlate (ts->u.t);
- fprintf (outf, " ]");
- break;
- case T_seq :
- t = ts->u.t;
- xlate (t);
- for (t = t->next; t; t = t->next) {
- fprintf (outf, " ");
- xlate (t);
- }
- break;
- case T_choice :
- fprintf (outf, "(");
- t = ts->u.t;
- xlate (t);
- for (t = t->next; t; t = t->next) {
- fprintf (outf, " | ");
- xlate (t);
- }
- fprintf (outf, ")");
- break;
- }
- }
- #define BSIZE 2048
- static FILE* inf;
- static char buf[BSIZE];
- static char* lexptr;
- static int lineno;
- static char*
- skipSpace (char* p)
- {
- int c;
- while (isspace ((c = *p)) && (c != '\n')) p++;
- return p;
- }
- static char*
- mystrndup (char* p, int sz)
- {
- char* s = malloc (sz+1);
- memcpy (s, p, sz);
- s[sz] = '\0';
- return s;
- }
- static char*
- readLiteral (char* p)
- {
- int c;
- char* s = p;
- while (((c = *p) != '\'') && (c != '\0')) p++;
- if (c == '\0') {
- fprintf (stderr, "Unclosed literal '%s, line %d\n", s, lineno);
- exit (1);
- }
- yylval.c = *s;
- return (p+1);
- }
- static char*
- readName (char* p)
- {
- int c;
- char* s = p;
- while (!isspace ((c = *p)) && (c != '\0')) p++;
- yylval.str = mystrndup (s, p-s);
- return p;
- }
- static void
- yyerror (char* msg)
- {
- fprintf (stderr, "%s, line %d\n", msg, lineno);
- }
- static void
- lexinit ()
- {
- lexptr = buf;
- }
- #ifdef DEBUG
- static int _yylex ();
- int yylex()
- { /* for debugging */
- int rv = _yylex();
- fprintf(stderr, "returning %d\n", rv);
- switch (rv) {
- case T_name :
- case T_token :
- fprintf(stderr, "string val is '%s'\n", yylval.str);
- break;
- case T_literal :
- fprintf(stderr, "string val is '%c'\n", yylval.c);
- break;
- }
- return rv;
- }
- #define yylex _yylex
- #endif
- static int
- yylex ()
- {
- int c;
- do {
- if (*lexptr == '\0') {
- if (!fgets (buf, BSIZE, inf)) return EOF;
- lineno++;
- lexptr = buf;
- }
- lexptr = skipSpace (lexptr);
- } while (*lexptr == '\0');
-
- switch (c = *lexptr++) {
- case '\n' :
- case '|' :
- case '=' :
- case '(' :
- case ')' :
- case '[' :
- case ']' :
- return c;
- break;
- case '\'' :
- lexptr = readLiteral (lexptr);
- return T_literal;
- break;
- case 'T' :
- if (*lexptr == '_') {
- lexptr = readName (lexptr+1);
- return T_token;
- }
- else {
- lexptr = readName (lexptr-1);
- return T_name;
- }
- break;
- default :
- lexptr = readName (lexptr-1);
- return T_name;
- break;
- }
- }
- #ifdef DEBUG
- #undef yylex
- #endif
- static FILE*
- openF (char* fname, char* mode)
- {
- FILE* f = fopen (fname, mode);
- if (!f) {
- fprintf (stderr, "Could not open %s for %s\n", fname, mode);
- exit(1);
- }
- return f;
- }
- int
- main (int argc, char* argv[])
- {
- if (argc != 3) {
- fprintf (stderr, "mklang: 2 arguments required\n");
- exit(1);
- }
- inf = openF (argv[1], "r");
- outf = openF (argv[2], "w");
- lexinit();
- yyparse ();
- return (0);
- }
|