Skip to content

Instantly share code, notes, and snippets.

@Hotshot824
Created January 3, 2024 16:51
Show Gist options
  • Save Hotshot824/71cee7b2c6a6d7e8da23149ea34b4780 to your computer and use it in GitHub Desktop.
Save Hotshot824/71cee7b2c6a6d7e8da23149ea34b4780 to your computer and use it in GitHub Desktop.
An example of how bison uses negative stack
/*
This program is a simple calculator that can add binary numbers and floating point numbers.
Consider the following grammar
S -> L . R
L -> B Ls
Ls -> B Ls | 𝜺
R -> B Rs
Rs -> B Rs | 𝜺
B -> 0 | 1
that represents the set of binary numbers. For example, the binary number 1010.0101 denotes the digital number 10.3125.
Give an attribute grammar that computes the corresponding digital number value from the binary number representation.
To turn in this assignment, upload a pdf file hw8.pdf that contains the solutions for this homework to the eCourse2 site.
*/
%{
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
extern int yylex();
extern int yyparse();
extern FILE* yyin;
void yyerror(const char* s);
int lex = 0;
int right_pow = 0;
%}
%union {
int ival;
struct{
int val;
int pow;
int in;
} Left;
struct{
float val;
int pow;
int in;
} Right;
}
%token<ival> T_ZERO T_ONE
%token '.' T_NEWLINE T_QUIT
%type<ival> B RSP
%type<Left> L LS
%type<Right> R RS
%start start
%%
start: L '.' R { printf("L.val: %d, R.val: %f, S.val: %f\n", $1.val, $3.val, $1.val + $3.val); }
;
L: B LS { $$.val = $1 * pow(2, $2.pow) + $2.val; }
;
LS: B LS { $$.pow = $2.pow + 1; $$.val = $1 * pow(2, $2.pow) + $2.val; }
| { $$.val = 0; $$.pow = 0; }
;
R: B RSP RS { $$.val = $1 * pow(2, -1) + $3.val;}
;
RS: B RSP RS { $$.val = $1 * pow(2, $<ival>0) + $3.val;}
| { $$.val = 0; }
;
RSP: /* empty */ { right_pow -= 1; $$ = right_pow - 1; }
;
B: T_ZERO { $$ = 0; }
| T_ONE { $$ = 1; }
;
%%
int main() {
yyin = stdin;
do {
yyparse();
} while(!feof(yyin));
return 0;
}
void yyerror(const char* s) {
fprintf(stderr, "Parse error: %s\n", s);
exit(1);
}
%{
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
extern int yylex();
extern int yyparse();
extern FILE* yyin;
void yyerror(const char* s);
int lex = 0;
int right_pow = 0;
%}
%union {
int ival;
struct{
int val;
int pow;
int in;
} Left;
struct{
float val;
int pow;
int in;
} Right;
}
%token<ival> T_ZERO T_ONE
%token '.' T_NEWLINE T_QUIT
%type<ival> B RSP
%type<Left> L LS
%type<Right> R RS
%start start
%%
start: L '.' R { printf("L.val: %d, R.val: %f, S.val: %f\n", $1.val, $3.val, $1.val + $3.val); }
;
L: B LS { $$.val = $1 * pow(2, $2.pow) + $2.val; }
;
LS: B LS { $$.pow = $2.pow + 1; $$.val = $1 * pow(2, $2.pow) + $2.val; }
| { $$.val = 0; $$.pow = 0; }
;
R: B RSP RS { $$.val = $1 * pow(2, -1) + $3.val;}
;
RS: B RSP RS { $$.val = $1 * pow(2, $<ival>0) + $3.val;}
| { $$.val = 0; }
;
RSP: /* empty */ { right_pow -= 1; $$ = right_pow - 1; }
;
B: T_ZERO { $$ = 0; }
| T_ONE { $$ = 1; }
;
%%
int main() {
yyin = stdin;
do {
yyparse();
} while(!feof(yyin));
return 0;
}
void yyerror(const char* s) {
fprintf(stderr, "Parse error: %s\n", s);
exit(1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment