blob: c8cef3b210766bf3967ad229200b9514e4ed748c [file] [log] [blame]
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* $Id$
*
* */
%{
#include <string>
#include <stdio.h>
#include <assert.h>
#include "mem/slicc/ast/ASTs.hh"
#include <vector>
#define YYMAXDEPTH 100000
#define YYERROR_VERBOSE
extern char* yytext;
extern "C" void yyerror(char*);
extern "C" int yylex();
%}
%union {
string* str_ptr;
Vector<string>* string_vector_ptr;
std::vector<string*>* stdstring_vector_ptr;
// Decls
DeclAST* decl_ptr;
DeclListAST* decl_list_ptr;
Vector<DeclAST*>* decl_vector_ptr;
// TypeField
TypeFieldAST* type_field_ptr;
Vector<TypeFieldAST*>* type_field_vector_ptr;
// Type
TypeAST* type_ptr;
Vector<TypeAST*>* type_vector_ptr;
// Formal Params
FormalParamAST* formal_param_ptr;
Vector<FormalParamAST*>* formal_param_vector_ptr;
// Statements
StatementAST* statement_ptr;
StatementListAST* statement_list_ptr;
Vector<StatementAST*>* statement_vector_ptr;
// Pairs
PairAST* pair_ptr;
PairListAST* pair_list_ptr;
// Expressions
VarExprAST* var_expr_ptr;
ExprAST* expr_ptr;
Vector<ExprAST*>* expr_vector_ptr;
}
%type <type_ptr> type void type_or_void
%type <type_vector_ptr> types type_list
// Formal Params
%type <formal_param_ptr> formal_param
%type <formal_param_vector_ptr> formal_params formal_param_list
%type <str_ptr> ident field
%type <string_vector_ptr> ident_list idents
%type <statement_ptr> statement if_statement
%type <statement_list_ptr> statement_list
%type <statement_vector_ptr> statements
%type <decl_ptr> decl
%type <decl_list_ptr> decl_list
%type <decl_vector_ptr> decls
%type <type_field_vector_ptr> type_members type_enums type_methods
%type <type_field_ptr> type_member type_enum type_method
%type <var_expr_ptr> var
%type <expr_ptr> expr literal enumeration
%type <expr_vector_ptr> expr_list
%type <pair_ptr> pair
%type <pair_list_ptr> pair_list pairs
%token <str_ptr> IDENT STRING NUMBER FLOATNUMBER LIT_BOOL VOID
%token <str_ptr> IMBED IMBED_TYPE
%token CHIP THIS
%token ASSIGN DOUBLE_COLON DOT SEMICOLON COLON
%token GLOBAL_DECL MACHINE_DECL IN_PORT_DECL OUT_PORT_DECL
%token PEEK ENQUEUE COPY_HEAD CHECK_ALLOCATE CHECK_STOP_SLOTS
//%token DEQUEUE REMOVE_EARLY SKIP_EARLY PEEK_EARLY
%token DEBUG_EXPR_TOKEN DEBUG_MSG_TOKEN
%token ACTION_DECL TRANSITION_DECL TYPE_DECL STRUCT_DECL EXTERN_TYPE_DECL ENUM_DECL
%token TYPE_FIELD OTHER IF ELSE RETURN NEW
%token <str_ptr> EQ NE '<' '>' LE GE NOT AND OR PLUS DASH STAR SLASH RIGHTSHIFT LEFTSHIFT
%left OR
%left AND
%nonassoc EQ NE
%nonassoc '<' '>' GE LE
%left PLUS DASH
%left STAR SLASH
%nonassoc NOT
%nonassoc DOUBLE_COLON DOT '['
%%
file: decl_list { g_decl_list_ptr = $1; }
decl_list: decls { $$ = new DeclListAST($1); }
decls: decl decls { $2->insertAtTop($1); $$ = $2; }
| { $$ = new Vector<DeclAST*>; }
;
decl: MACHINE_DECL '(' ident pair_list ')' ':' formal_param_list '{' decl_list '}' { $$ = new MachineAST($3, $4, $7, $9); }
| ACTION_DECL '(' ident pair_list ')' statement_list { $$ = new ActionDeclAST($3, $4, $6); }
| IN_PORT_DECL '(' ident ',' type ',' var pair_list ')' statement_list { $$ = new InPortDeclAST($3, $5, $7, $8, $10); }
| OUT_PORT_DECL '(' ident ',' type ',' var pair_list ')' SEMICOLON { $$ = new OutPortDeclAST($3, $5, $7, $8); }
| TRANSITION_DECL '(' ident_list ',' ident_list ',' ident pair_list ')' ident_list { $$ = new TransitionDeclAST($3, $5, $7, $8, $10); }
| TRANSITION_DECL '(' ident_list ',' ident_list pair_list ')' ident_list { $$ = new TransitionDeclAST($3, $5, NULL, $6, $8); }
| EXTERN_TYPE_DECL '(' type pair_list ')' SEMICOLON { $4->addPair(new PairAST("external", "yes")); $$ = new TypeDeclAST($3, $4, NULL); }
| EXTERN_TYPE_DECL '(' type pair_list ')' '{' type_methods '}' { $4->addPair(new PairAST("external", "yes")); $$ = new TypeDeclAST($3, $4, $7); }
| GLOBAL_DECL '(' type pair_list ')' '{' type_members '}' { $4->addPair(new PairAST("global", "yes"));$$ = new TypeDeclAST($3, $4, $7); }
| STRUCT_DECL '(' type pair_list ')' '{' type_members '}' { $$ = new TypeDeclAST($3, $4, $7); }
| ENUM_DECL '(' type pair_list ')' '{' type_enums '}' { $4->addPair(new PairAST("enumeration", "yes")); $$ = new EnumDeclAST($3, $4, $7); }
| type ident pair_list SEMICOLON { $$ = new ObjDeclAST($1, $2, $3); }
| type ident '(' formal_param_list ')' pair_list SEMICOLON { $$ = new FuncDeclAST($1, $2, $4, $6, NULL); } // non-void function
| void ident '(' formal_param_list ')' pair_list SEMICOLON { $$ = new FuncDeclAST($1, $2, $4, $6, NULL); } // void function
| type ident '(' formal_param_list ')' pair_list statement_list { $$ = new FuncDeclAST($1, $2, $4, $6, $7); } // non-void function
| void ident '(' formal_param_list ')' pair_list statement_list { $$ = new FuncDeclAST($1, $2, $4, $6, $7); } // void function
;
// Type fields
type_members: type_member type_members { $2->insertAtTop($1); $$ = $2; }
| { $$ = new Vector<TypeFieldAST*>; }
;
type_member: type ident pair_list SEMICOLON { $$ = new TypeFieldMemberAST($1, $2, $3, NULL); }
| type ident ASSIGN expr SEMICOLON { $$ = new TypeFieldMemberAST($1, $2, new PairListAST(), $4); }
;
// Methods
type_methods: type_method type_methods { $2->insertAtTop($1); $$ = $2; }
| { $$ = new Vector<TypeFieldAST*>; }
;
type_method: type_or_void ident '(' type_list ')' pair_list SEMICOLON { $$ = new TypeFieldMethodAST($1, $2, $4, $6); }
;
// Enum fields
type_enums: type_enum type_enums { $2->insertAtTop($1); $$ = $2; }
| { $$ = new Vector<TypeFieldAST*>; }
;
type_enum: ident pair_list SEMICOLON { $$ = new TypeFieldEnumAST($1, $2); }
;
// Type
type_list : types { $$ = $1; }
| { $$ = new Vector<TypeAST*>; }
;
types : type ',' types { $3->insertAtTop($1); $$ = $3; }
| type { $$ = new Vector<TypeAST*>; $$->insertAtTop($1); }
;
type: ident { $$ = new TypeAST($1); }
;
void: VOID { $$ = new TypeAST($1); }
;
type_or_void: type { $$ = $1; }
| void { $$ = $1; }
;
// Formal Param
formal_param_list : formal_params { $$ = $1; }
| { $$ = new Vector<FormalParamAST*>; }
;
formal_params : formal_param ',' formal_params { $3->insertAtTop($1); $$ = $3; }
| formal_param { $$ = new Vector<FormalParamAST*>; $$->insertAtTop($1); }
;
formal_param : type ident { $$ = new FormalParamAST($1, $2); }
;
// Idents and lists
ident: IDENT { $$ = $1; };
ident_list: '{' idents '}' { $$ = $2; }
| ident { $$ = new Vector<string>; $$->insertAtTop(*($1)); delete $1; }
;
idents: ident SEMICOLON idents { $3->insertAtTop(*($1)); $$ = $3; delete $1; }
| ident ',' idents { $3->insertAtTop(*($1)); $$ = $3; delete $1; }
| ident idents { $2->insertAtTop(*($1)); $$ = $2; delete $1; }
| { $$ = new Vector<string>; }
;
// Pair and pair lists
pair_list: ',' pairs { $$ = $2; }
| { $$ = new PairListAST(); }
pairs : pair ',' pairs { $3->addPair($1); $$ = $3; }
| pair { $$ = new PairListAST(); $$->addPair($1); }
;
pair : ident '=' STRING { $$ = new PairAST($1, $3); }
| ident '=' ident { $$ = new PairAST($1, $3); }
| STRING { $$ = new PairAST(new string("short"), $1); }
;
// Below are the rules for action descriptions
statement_list: '{' statements '}' { $$ = new StatementListAST($2); }
;
statements: statement statements { $2->insertAtTop($1); $$ = $2; }
| { $$ = new Vector<StatementAST*>; }
;
expr_list: expr ',' expr_list { $3->insertAtTop($1); $$ = $3; }
| expr { $$ = new Vector<ExprAST*>; $$->insertAtTop($1); }
| { $$ = new Vector<ExprAST*>; }
;
statement: expr SEMICOLON { $$ = new ExprStatementAST($1); }
| expr ASSIGN expr SEMICOLON { $$ = new AssignStatementAST($1, $3); }
| ENQUEUE '(' var ',' type pair_list ')' statement_list { $$ = new EnqueueStatementAST($3, $5, $6, $8); }
| PEEK '(' var ',' type ')' statement_list { $$ = new PeekStatementAST($3, $5, $7, "peek"); }
// | PEEK_EARLY '(' var ',' type ')' statement_list { $$ = new PeekStatementAST($3, $5, $7, "peekEarly"); }
| COPY_HEAD '(' var ',' var pair_list ')' SEMICOLON { $$ = new CopyHeadStatementAST($3, $5, $6); }
| CHECK_ALLOCATE '(' var ')' SEMICOLON { $$ = new CheckAllocateStatementAST($3); }
| CHECK_STOP_SLOTS '(' var ',' STRING ',' STRING ')' SEMICOLON { $$ = new CheckStopSlotsStatementAST($3, $5, $7); }
| if_statement { $$ = $1; }
| RETURN expr SEMICOLON { $$ = new ReturnStatementAST($2); }
;
if_statement: IF '(' expr ')' statement_list ELSE statement_list { $$ = new IfStatementAST($3, $5, $7); }
| IF '(' expr ')' statement_list { $$ = new IfStatementAST($3, $5, NULL); }
| IF '(' expr ')' statement_list ELSE if_statement { $$ = new IfStatementAST($3, $5, new StatementListAST($7)); }
;
expr: var { $$ = $1; }
| literal { $$ = $1; }
| enumeration { $$ = $1; }
| ident '(' expr_list ')' { $$ = new FuncCallExprAST($1, $3); }
| NEW type { $$ = new NewExprAST($2); }
// globally access a local chip component and call a method
| THIS DOT var '[' expr ']' DOT var DOT ident '(' expr_list ')' { $$ = new ChipComponentAccessAST($3, $5, $8, $10, $12 ); }
// globally access a local chip component and access a data member
| THIS DOT var '[' expr ']' DOT var DOT field { $$ = new ChipComponentAccessAST($3, $5, $8, $10 ); }
// globally access a specified chip component and call a method
| CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT ident '(' expr_list ')' { $$ = new ChipComponentAccessAST($3, $6, $8, $11, $13, $15 ); }
// globally access a specified chip component and access a data member
| CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT field { $$ = new ChipComponentAccessAST($3, $6, $8, $11, $13 ); }
| expr DOT field { $$ = new MemberExprAST($1, $3); }
| expr DOT ident '(' expr_list ')' { $$ = new MethodCallExprAST($1, $3, $5); }
| type DOUBLE_COLON ident '(' expr_list ')' { $$ = new MethodCallExprAST($1, $3, $5); }
| expr '[' expr_list ']' { $$ = new MethodCallExprAST($1, new string("lookup"), $3); }
| expr STAR expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
| expr SLASH expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
| expr PLUS expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
| expr DASH expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
| expr '<' expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
| expr '>' expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
| expr LE expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
| expr GE expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
| expr EQ expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
| expr NE expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
| expr AND expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
| expr OR expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
| expr RIGHTSHIFT expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
| expr LEFTSHIFT expr { $$ = new InfixOperatorExprAST($1, $2, $3); }
// | NOT expr { $$ = NULL; } // FIXME - unary not
// | DASH expr %prec NOT { $$ = NULL; } // FIXME - unary minus
| '(' expr ')' { $$ = $2; }
;
literal: STRING { $$ = new LiteralExprAST($1, "string"); }
| NUMBER { $$ = new LiteralExprAST($1, "int"); }
| FLOATNUMBER { $$ = new LiteralExprAST($1, "int"); }
| LIT_BOOL { $$ = new LiteralExprAST($1, "bool"); }
;
enumeration: ident ':' ident { $$ = new EnumExprAST(new TypeAST($1), $3); }
;
var: ident { $$ = new VarExprAST($1); }
;
field: ident { $$ = $1; }
;
%%
extern FILE *yyin;
DeclListAST* parse(string filename)
{
FILE *file;
file = fopen(filename.c_str(), "r");
if (!file) {
cerr << "Error: Could not open file: " << filename << endl;
exit(1);
}
g_line_number = 1;
g_file_name() = filename;
yyin = file;
g_decl_list_ptr = NULL;
yyparse();
return g_decl_list_ptr;
}
extern "C" void yyerror(char* s)
{
fprintf(stderr, "%s:%d: %s at %s\n", g_file_name().c_str(), g_line_number, s, yytext);
exit(1);
}