Česky
Kamil Dudka

Flex/Bison based compiler and interpreter written in C++ (using Boost)

File detail

Name:Downloadparser.yy [Download]
Location: vyp08 > vyp08-1.0pre1 > src
Size:8.3 KB
Last modification:2009-07-04 19:51

File content

/*
 * 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 ')'
            ;

%%