/////////////
// Compile
/////////////
bison -d modified.y
flex modified.l
g++ modified.tab.c lex.yy.c -ll
/////////////
// Example Inputs
/////////////
COLOR goldenrod
TEXT hello doggie
TEXT why? why is this happening to me? why!?
TEXT basketballl
BEGIN SCRIPT
LET x = 5
PRINT x
IF x THEN
PRINT x
IF x + 2 THEN
PRINT x + 2
ENDIF
ENDIF
/////////////
// modified.y
/////////////
%define parse.error detailed
/* This line does not work in older versions of Bison,
if you get an immediate syntax error, try this instead:
%error-verbose
*/
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int yylineno;
int yylex(void);
void yyerror(const char *s);
/* Alternative grammar */
//script
// : script BEGINS EOL { printf("\n"); } ENDS EOL
// | /* epsilon "script program" has many conflicts! */
// | EOL
// ;
%}
%union {
char *s;
}
%token LET PRINT IF THEN ELSE ENDIF EOL BEGINS ENDS
%token <s> ATOM COLOR TEXT
%type <s> expr much_text
%left '+'
%%
script
: COLOR { printf("<body style=\"background-color:%s\">\n", $1); free($1); } EOL
much_text { printf("%s",$4); free($4); }
script
BEGINS EOL
{ printf("<script>\n"); } program { printf("</script>\n"); }
| /* empty */
| EOL
;
much_text
: TEXT EOL { $$ = $1; }
| much_text TEXT EOL
{
size_t n = strlen($1) + strlen($2) + 6;
char* buf = (char*)malloc(n);
snprintf(buf,n,"%s<br>\n%s",$1,$2);
$$ = buf;
}
program
: /* empty */
| program line
;
line
: LET ATOM '=' expr EOL
{ printf("var %s = %s;\n", $2, $4); free($2); free($4); }
| PRINT expr EOL
{ printf("console.log(%s);\n", $2); free($2); }
| if_stmt
| EOL
{ }
;
if_stmt
: IF expr THEN EOL
{ printf("if (%s) {\n\t", $2); free($2); }
block
ENDIF EOL
{ printf("}\n"); }
;
block
: /* empty */
| block line
;
expr
: ATOM
{ $$ = $1; }
| expr '+' expr
{
size_t n = strlen($1) + strlen($3) + 4;
char *buf = (char*)malloc(n);
snprintf(buf, n, "%s + %s", $1, $3);
$$ = buf;
}
;
%%
int main(void) {
yyparse();
return 0;
}
void yyerror(const char *s) {
fprintf(stderr, "Error on line %d: %s\n", yylineno, s);
}
////////////
// modified.l
////////////
%option noyywrap
%option yylineno
%{
#include "modified.tab.h"
#include <string.h>
%}
ID [A-Za-z_][A-Za-z0-9_]*
NUM [0-9]+
%%
"BEGIN SCRIPT" return BEGINS;
"END SCRIPT" return ENDS;
"LET" return LET;
"PRINT" return PRINT;
"IF" return IF;
"THEN" return THEN;
"ELSE" return ELSE;
"ENDIF" return ENDIF;
"COLOR ".*/\n { yylval.s = strdup(yytext+6); return COLOR;}
"TEXT ".*/\n { yylval.s = strdup(yytext+5); return TEXT;}
{ID} { yylval.s = strdup(yytext); return ATOM; }
{NUM} { yylval.s = strdup(yytext); return ATOM; }
"=" return '=';
"\n" return EOL;
[ \t\r] ;
. return yytext[0];
%%