190 lines
4.1 KiB
Plaintext
190 lines
4.1 KiB
Plaintext
|
|
/*
|
|
Declare token types at the top of the bison file,
|
|
causing them to be automatically generated in parser.tab.h
|
|
for use by scanner.c.
|
|
*/
|
|
|
|
%debug
|
|
%define parse.error detailed
|
|
|
|
%token TOKEN_ASSIGNMENT
|
|
%token TOKEN_COMMA
|
|
%token TOKEN_DIV
|
|
%token TOKEN_EQUAL_EQUAL
|
|
%token TOKEN_GREATER_THAN
|
|
%token TOKEN_GREATER_THAN_OR_EQUAL
|
|
%token TOKEN_ID
|
|
%token TOKEN_INT
|
|
%token TOKEN_INTEGER
|
|
%token TOKEN_KEYWORD_ENDIF
|
|
%token TOKEN_KEYWORD_IF
|
|
%token TOKEN_KEYWORD_PRINT
|
|
%token TOKEN_KEYWORD_THEN
|
|
%token TOKEN_LBRACKET
|
|
%token TOKEN_LESS_THAN
|
|
%token TOKEN_LESS_THAN_OR_EQUAL
|
|
%token TOKEN_LPAREN
|
|
%token TOKEN_MINUS
|
|
%token TOKEN_MUL
|
|
%token TOKEN_NOT_EQUAL
|
|
%token TOKEN_PLUS
|
|
%token TOKEN_RBRACKET
|
|
%token TOKEN_RPAREN
|
|
%token TOKEN_SEMI
|
|
|
|
%union {
|
|
struct stmt *stmt;
|
|
struct expr *expr;
|
|
struct decl *decl;
|
|
};
|
|
|
|
%type <stmt> program statement_list statement print_statement assignment_statement if_statement block
|
|
%type <expr> expr term factor name sum array_subscript star_expr
|
|
%type <decl> declaration
|
|
|
|
%{
|
|
#define YYDEBUG 1
|
|
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "expr.h"
|
|
|
|
|
|
/*
|
|
Clunky: Manually declare the interface to the scanner generated by flex.
|
|
*/
|
|
|
|
extern int yylineno;
|
|
extern char *yytext;
|
|
extern int yylex();
|
|
extern void yyerror(const char*);
|
|
|
|
/*
|
|
Clunky: Keep the final result of the parse in a global variable,
|
|
so that it can be retrieved by main().
|
|
*/
|
|
|
|
struct stmt * parser_result = 0;
|
|
|
|
%}
|
|
|
|
%%
|
|
|
|
/* Here is the grammar: program is the start symbol. */
|
|
|
|
program : statement_list
|
|
{ parser_result = $1; return 0; }
|
|
;
|
|
|
|
statement_list : statement
|
|
{ $$ = $1; }
|
|
| statement statement_list
|
|
{ $$ = $1; $1->next = $2; }
|
|
;
|
|
|
|
block : statement
|
|
{ $$ = $1; }
|
|
| statement block
|
|
{ $$ = $1; $1->next = $2; }
|
|
;
|
|
|
|
statement : assignment_statement TOKEN_SEMI
|
|
{ $$ = $1; }
|
|
| print_statement TOKEN_SEMI
|
|
{ $$ = $1; }
|
|
| if_statement
|
|
{ $$ = $1; }
|
|
;
|
|
|
|
assignment_statement : declaration
|
|
{ $$ = stmt_create(STMT_DECL,$1,0,0,0,0,0,0); }
|
|
;
|
|
|
|
print_statement : TOKEN_KEYWORD_PRINT expr
|
|
{ $$ = stmt_create(STMT_PRINT,0,0,$2,0,0,0,0); }
|
|
;
|
|
|
|
if_statement : TOKEN_KEYWORD_IF expr TOKEN_KEYWORD_THEN block TOKEN_KEYWORD_ENDIF
|
|
{ $$ = stmt_create(STMT_IF,0,0,$2,0,$4,0,0); }
|
|
;
|
|
|
|
declaration : name TOKEN_ASSIGNMENT expr
|
|
{ $$ = decl_create($1,0,$3,0,0); }
|
|
| array_subscript TOKEN_ASSIGNMENT expr
|
|
{ $$ = decl_create($1,0,$3,0,0); }
|
|
;
|
|
|
|
name : TOKEN_ID
|
|
{ $$ = expr_create_name(yytext); }
|
|
;
|
|
|
|
array_subscript : name TOKEN_LBRACKET expr TOKEN_RBRACKET
|
|
{ $$ = expr_create(EXPR_SUBSCRIPT,$1,$3); }
|
|
;
|
|
|
|
star_expr : expr
|
|
{ $$ = expr_create(EXPR_ARRAY,$1,0); }
|
|
| expr TOKEN_COMMA star_expr
|
|
{ $$ = expr_create(EXPR_ARRAY,$1,$3); }
|
|
;
|
|
|
|
expr : sum TOKEN_LESS_THAN sum
|
|
{ $$ = expr_create(EXPR_LESS_THAN,$1,$3); }
|
|
| sum TOKEN_LESS_THAN_OR_EQUAL sum
|
|
{ $$ = expr_create(EXPR_LESS_THAN_OR_EQUAL,$1,$3); }
|
|
| sum TOKEN_GREATER_THAN sum
|
|
{ $$ = expr_create(EXPR_GREATER_THAN,$1,$3); }
|
|
| sum TOKEN_GREATER_THAN_OR_EQUAL sum
|
|
{ $$ = expr_create(EXPR_GREATER_THAN_OR_EQUAL,$1,$3); }
|
|
| sum TOKEN_EQUAL_EQUAL sum
|
|
{ $$ = expr_create(EXPR_EQUAL_EQUAL,$1,$3); }
|
|
| sum TOKEN_NOT_EQUAL sum
|
|
{ $$ = expr_create(EXPR_NOT_EQUAL,$1,$3); }
|
|
| sum
|
|
{ $$ = $1; }
|
|
;
|
|
|
|
sum : sum TOKEN_PLUS term
|
|
{ $$ = expr_create(EXPR_ADD,$1,$3); }
|
|
| sum TOKEN_MINUS term
|
|
{ $$ = expr_create(EXPR_SUBTRACT,$1,$3); }
|
|
| term
|
|
{ $$ = $1; }
|
|
;
|
|
|
|
term : term TOKEN_MUL factor
|
|
{ $$ = expr_create(EXPR_MULTIPLY,$1,$3); }
|
|
| term TOKEN_DIV factor
|
|
{ $$ = expr_create(EXPR_DIVIDE,$1,$3); }
|
|
| factor
|
|
{ $$ = $1; }
|
|
;
|
|
|
|
factor : TOKEN_LPAREN expr TOKEN_RPAREN
|
|
{ $$ = $2; }
|
|
| TOKEN_MINUS factor
|
|
{ $$ = expr_create(EXPR_SUBTRACT,expr_create_integer_literal(0),$2); }
|
|
| TOKEN_INT
|
|
{ $$ = expr_create_integer_literal(atoi(yytext)); }
|
|
| TOKEN_LBRACKET star_expr TOKEN_RBRACKET
|
|
{ $$ = $2; }
|
|
| array_subscript
|
|
{ $$ = $1; }
|
|
| name
|
|
{ $$ = $1; }
|
|
;
|
|
|
|
%%
|
|
|
|
/*
|
|
This function will be called by bison if the parse should
|
|
encounter an error. In principle, "str" will contain something
|
|
useful. In practice, it often does not.
|
|
*/
|
|
|
|
void yyerror(const char* msg) {
|
|
fprintf(stderr, "Error | Line: %d\n%s\n", yylineno, msg);
|
|
}
|