ゆの in yacc

パーサかませばなんでもありだな……

%{
#include <stdio.h>
#include <string.h>
%}

%union {
    char *str;
}

%token X
%token <str> STRING
%type  <str> face mouths left_part right_part mouth

%%

sayhello:
	face '<' STRING '!'
		{
		    fputs($1, stdout);
		    fputc(' ', stdout);
		    fputs($3, stdout);
		    fputc('!', stdout);
		    fputs("\n", stdout);

		    free($1);
		}

face:
	left_part mouths right_part
		{
		    $$ = malloc(strlen($1) + strlen($2) + strlen($3) + 1);
		    strcpy($$, $1);
		    strcat($$, $2);
		    strcat($$, $3);

		    free($1);
		    free($2);
		    free($3);
		}

mouths:
	mouth
		{
		    $$ = $1;
		}
	| mouth mouths
		{
		    $$ = malloc(strlen($1) + strlen($2) + 1);
		    strcpy($$, $1);
		    strcat($$, $2);

		    free($1);
		    free($2);
		}

left_part:
	X '/'
		{ $$ = strdup("ひだまりスケッチ"); }

right_part:
	'/' X
		{ $$ = strdup("365"); }

mouth:
	'_'
		{ $$ = strdup("×"); }

%%

int
yylex(void)
{
    int c;
    static char str[1024];
    char *p;

    c = fgetc(stdin);
    while (c != EOF && isspace(c))
        c = fgetc(stdin);
    if (c == EOF)
        return 0;
    if (ispunct(c))
        return c;

    p = str;
    while (c != EOF && ! isspace(c) && ! ispunct(c)) {
        *p++ = c;
        c = fgetc(stdin);
    }
    if (c != EOF)
        ungetc(c, stdin);
    *p++ = 0;

    if (! strcmp(str, "X"))
        return X;

    yylval.str = str;
    return STRING;
}

int yyerror(const char *msg)
{
    fprintf(stderr, "parser error: %s\n", msg);
    return 0;
}

int main(int argc, char *argv[])
{
    yyparse();
}

バッファオーバーフロー等未対策。念のため。

% bison yuno.y

% gcc -o yuno yuno.tab.c

% ./yuno

X / _ / X < 来週も見てくださいね!
ひだまりスケッチ×365 来週も見てくださいね!

X  /  ___  /  X < 来週も見てくださいね!
ひだまりスケッチ×××365 来週も見てくださいね!