Flex/Bison based compiler and interpreter written in C++ (using Boost)
Detail souboru
Obsah souboru
/*
* Copyright (C) 2008 Kamil Dudka <xdudka00@stud.fit.vutbr.cz>
*
* This file is part of vyp08 (compiler and interpreter of VYP08 language).
*
* vyp08 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* vyp08 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with vyp08. If not, see <http://www.gnu.org/licenses/>.
*/
%{
#include <string>
/* scanner module binding */
#include "scanner.h"
#define YYSTYPE Token
/* bison callback interface */
class IBisonListener {
public:
virtual ~IBisonListener() { }
virtual void setType(EToken type) = 0; ///< token type detected
virtual void glVar(Token token) = 0; ///< global variable
virtual void fncInit(Token token) = 0; ///< fnc decl/def detected
virtual void fncDecl() = 0; ///< fnc declaration complete
virtual void fncDefEnter() = 0; ///< fnc definition body enter
virtual void fncDefLeave() = 0; ///< fnc definition body leave
virtual void argDecl() = 0; ///< arg in fnc declaration
virtual void argDef(Token token) = 0; ///< arg in fnc definition
virtual void lcVar(Token token) = 0; ///< local variable in fnc def
virtual void assign(Token token) = 0; ///< assign command
virtual void ifEnter(Token token) = 0; ///< if statement, if part
virtual void ifElse() = 0; ///< if statement, else part
virtual void ifLeave() = 0; ///< if statement complete
virtual void whileInit(Token token) = 0; ///< while, B_EXPR follows
virtual void whileEnter() = 0; ///< while, CMD_LIST follows
virtual void whileLeave() = 0; ///< while statement complete
virtual void fncCallInit(Token token) = 0; ///< fnc call detected
virtual void fncCallArg() = 0; ///< fnc call arg
virtual void fncCallPrintArg() = 0; ///< fnc call arg of print()
virtual void fncCallAsCmd() = 0; ///< fnc call as command
virtual void fncCallAsExpr() = 0; ///< fnc call as expression
virtual void pushToken(Token token) = 0; ///< push token
virtual void evalUnOp(Token token) = 0; ///< eval unary operator
virtual void evalBinOp(Token token) = 0; ///< eval binary operator
};
namespace yy {
/* scanner module binding (token, location, scanner) */
int yylex (Token *, location *, IScanner *);
}
%}
/* basic bison configuration */
%skeleton "lalr1.cc"
%defines
%locations
%define "parser_class_name" "BisonParser"
/* turn on debugging */
%debug
%error-verbose
/* BisonParser arguments */
%parse-param { IScanner *scanner }
%parse-param { IBisonListener *listener }
%parse-param { std::string fileName }
/* yylex() extra arguments */
%lex-param { IScanner *scanner }
/* start symbol represents whole program */
%start START
/* basic blocks */
%token '{' '}'
%token ';'
%token ','
/* keywords */
%token T_VAR
%token T_VOID T_INT T_DOUBLE T_STRING
%token T_IF T_ELSE T_WHILE
/* atoms */
%token T_ID
%token T_INT_LIT T_DOUBLE_LIT T_STRING_LIT
%token T_ASSIGN
/* expressions alphabet */
%token T_OR T_AND
%left T_EQ T_NEQ
%left '<' '>' T_LE T_GE
%left '+' '-'
%left '*' '/' T_DIV
%token T_NOT
%token '(' ')'
%%
/* Grammar rules */
START : GL_VARS FNCS
;
GL_VARS : /* empty */
| T_VAR GL_VAR_LIST
;
FNCS : /* empty */
| FNC FNCS
;
GL_VAR_LIST : GL_VAR
| GL_VAR ',' GL_VAR_LIST
;
GL_VAR : TYPE T_ID { listener->glVar($2); }
;
TYPE : T_INT { listener->setType(ETOKEN_KW_INT); }
| T_DOUBLE { listener->setType(ETOKEN_KW_DOUBLE); }
| T_STRING { listener->setType(ETOKEN_KW_STRING); }
;
FNC : FNC_INIT '(' ARGS ')' FNC_DECL_DEF
;
FNC_INIT : T_VOID T_ID { listener->setType(ETOKEN_KW_VOID);
listener->fncInit($2); }
| TYPE T_ID { listener->fncInit($2); }
;
ARGS : /* empty */
| ARGS_DECL
| ARGS_DEF
;
FNC_DECL_DEF: ';' { listener->fncDecl(); }
| LC_VARS FNC_DEF_INIT CMD_LIST '}'
{ listener->fncDefLeave(); }
;
FNC_DEF_INIT: '{' { listener->fncDefEnter(); }
ARGS_DECL : ARG_DECL
| ARG_DECL ';' ARGS_DECL
;
ARG_DECL : TYPE { listener->argDecl(); }
;
ARGS_DEF : ARG_DEF
| ARG_DEF ';' ARGS_DEF
;
ARG_DEF : TYPE T_ID { listener->argDef($2); }
;
LC_VARS : /* empty */
| T_VAR LC_VAR_LIST ';'
;
LC_VAR_LIST : LC_VAR
| LC_VAR ',' LC_VAR_LIST
;
LC_VAR : TYPE T_ID { listener->lcVar($2); }
;
CMD_BLOCK : '{' CMD_LIST '}'
;
CMD_LIST : /* empty */
| CMD ';' CMD_LIST
;
CMD : /* empty */
| T_ID T_ASSIGN N_EXPR { listener->assign($1); }
| IF_INIT IF_BLOCK T_ELSE ELSE_BLOCK
| WHILE WHILE_BLOCK
| FNC_CALL { listener->fncCallAsCmd(); }
;
IF_INIT : T_IF B_EXPR { listener->ifEnter($1); }
;
IF_BLOCK : CMD_BLOCK { listener->ifElse(); }
;
ELSE_BLOCK : CMD_BLOCK { listener->ifLeave(); }
;
WHILE : WHILE_INIT B_EXPR { listener->whileEnter(); }
;
WHILE_INIT : T_WHILE { listener->whileInit($1); }
;
WHILE_BLOCK : CMD_BLOCK { listener->whileLeave(); }
;
FNC_CALL : FNC_CALL_INIT FNC_CALL_ARGS ')'
;
FNC_CALL_INIT : T_ID '(' { listener->fncCallInit($1); }
;
FNC_CALL_ARGS : /* empty */
| FNC_CALL_ARG_LIST
| TYPE N_EXPR { listener->fncCallPrintArg(); }
;
FNC_CALL_ARG_LIST : N_EXPR { listener->fncCallArg(); }
| N_EXPR ',' FNC_CALL_ARGS
{ listener->fncCallArg(); }
;
N_EXPR : FNC_CALL { listener->fncCallAsExpr(); }
| T_ID { listener->pushToken($1); }
| T_INT_LIT { listener->pushToken($1); }
| T_DOUBLE_LIT { listener->pushToken($1); }
| T_STRING_LIT { listener->pushToken($1); }
| '-' N_EXPR { listener->evalUnOp($1); }
| N_EXPR '+' N_EXPR { listener->evalBinOp($2); }
| N_EXPR '-' N_EXPR { listener->evalBinOp($2); }
| N_EXPR '*' N_EXPR { listener->evalBinOp($2); }
| N_EXPR '/' N_EXPR { listener->evalBinOp($2); }
| N_EXPR T_DIV N_EXPR { listener->evalBinOp($2); }
| '(' N_EXPR ')'
;
B_EXPR : B_EXPR1
| B_EXPR1 T_OR B_EXPR { listener->evalBinOp($2); }
;
B_EXPR1 : B_EXPR2
| B_EXPR2 T_AND B_EXPR1 { listener->evalBinOp($2); }
B_EXPR2 : T_NOT B_EXPR2 { listener->evalUnOp($1); }
| N_EXPR '<' N_EXPR { listener->evalBinOp($2); }
| N_EXPR '>' N_EXPR { listener->evalBinOp($2); }
| N_EXPR T_LE N_EXPR { listener->evalBinOp($2); }
| N_EXPR T_GE N_EXPR { listener->evalBinOp($2); }
| N_EXPR T_EQ N_EXPR { listener->evalBinOp($2); }
| N_EXPR T_NEQ N_EXPR { listener->evalBinOp($2); }
| '(' B_EXPR ')'
;
%%