Skip to content

Instantly share code, notes, and snippets.

@VienosNotes
Last active January 3, 2016 04:59
Show Gist options
  • Select an option

  • Save VienosNotes/8412351 to your computer and use it in GitHub Desktop.

Select an option

Save VienosNotes/8412351 to your computer and use it in GitHub Desktop.
all: y.tab.c lex.yy.c
cc -DYYERROR_VERBOSE -DYYDEBUG -o Parse y.tab.c lex.yy.c
y.tab.c:
yacc -dv parser.y
lex.yy.c: y.tab.c
lex parser.l
%{
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h"
int yywrap(void) { return 1; }
%}
digit [0-9]
ops [-+*/=]
symbol [a-z]
%%
{ops} {
switch (yytext[0]) {
case '+':
return PLUS;
case '-':
return MINUS;
case '*':
return MUL;
case '/':
return DIV;
case '=':
return EQ;
}
}
{digit}+ {
yylval.int_value = atoi(yytext);
return NUM;
}
"print" {
return PRINT;
}
\; { return EOL; }
\( { return PAREN_L; }
\) { return PAREN_R; }
{symbol}+ {
char* varname = malloc(yyleng);
strlcpy(varname, yytext, yyleng+1);
yylval.var.name = varname;
return VAR;
}
%%
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define YYDEBUG 1
void addvar(char* name, int val);
int search(char* name);
int yylex(void);
int yyerror(char const *str);
void hoge();
struct _unit {};
struct _unit* unit;
%}
%union {
int int_value;
struct _unit* unit;
struct {
char* name;
int value;
} var;
}
%token <int_value> NUM
%token <var> VAR
%right EQ
%left PLUS MINUS
%left MUL DIV
%token PRINT EOL PAREN_L PAREN_R
%type <int_value> expression number
%type <unit> assignment print_statement program
%type <var> variable
%%
program : statement EOL { $$ = unit; }
| program statement EOL { $$ = unit; }
statement: print_statement | assignment
assignment: variable EQ expression {
addvar($1.name, $3);
$$ = unit; }
;
print_statement : PRINT expression { printf("%d", $2); $$ = unit; }
;
expression : expression PLUS expression { $$ = $1 + $3; }
| expression MINUS expression { $$ = $1 - $3; }
| expression MUL expression { $$ = $1 * $3; }
| expression DIV expression { $$ = $1 / $3; }
| variable { $$ = search($1.name); }
| number
| PAREN_L expression PAREN_R { $$ = $2; }
;
variable: VAR { $$ = $1; }
;
number: NUM
;
%%
typedef struct _varlist {
char* name;
int value;
struct _varlist* next;
} varlist;
varlist* head;
varlist* last;
int search(char* name) { // 環境から名前を探す
varlist* tmp = head->next;
while (tmp != NULL) {
if (strcmp(name, tmp->name) == 0) { return tmp->value; }
else { tmp = tmp->next; }
}
printf("undefined variable: %s", name);
exit(1);
}
void addvar(char* name, int val) { //環境に変数を追加する
if (head == NULL) {
head = malloc(sizeof(varlist));
last = head;
}
varlist* tmp = malloc(sizeof(varlist));
tmp->name = name;
tmp->value = val;
last->next = tmp;
last = tmp;
}
int yyerror(char const *str)
{
extern char *yytext;
printf("err, %s\n", str);
return 0;
}
int main(void)
{
yyparse();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment