/* * 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 #include #include #include "mem/slicc/ast/ASTs.hh" #include #define YYMAXDEPTH 100000 #define YYERROR_VERBOSE extern char* yytext; extern "C" void yyerror(char*); extern "C" int yylex(); %} %union { string* str_ptr; Vector* string_vector_ptr; std::vector* stdstring_vector_ptr; // Decls DeclAST* decl_ptr; DeclListAST* decl_list_ptr; Vector* decl_vector_ptr; // TypeField TypeFieldAST* type_field_ptr; Vector* type_field_vector_ptr; // Type TypeAST* type_ptr; Vector* type_vector_ptr; // Formal Params FormalParamAST* formal_param_ptr; Vector* formal_param_vector_ptr; // Statements StatementAST* statement_ptr; StatementListAST* statement_list_ptr; Vector* statement_vector_ptr; // Pairs PairAST* pair_ptr; PairListAST* pair_list_ptr; // Expressions VarExprAST* var_expr_ptr; ExprAST* expr_ptr; Vector* expr_vector_ptr; } %type type void type_or_void %type types type_list // Formal Params %type formal_param %type formal_params formal_param_list %type ident field %type ident_list idents %type statement if_statement %type statement_list %type statements %type decl %type decl_list %type decls %type type_members type_enums type_methods %type type_member type_enum type_method %type var %type expr literal enumeration %type expr_list %type myrule %type pair %type pair_list pairs %token IDENT STRING NUMBER FLOATNUMBER LIT_BOOL VOID %token 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 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; } ; decl: MACHINE_DECL '(' ident pair_list ')' ':' myrule '{' decl_list '}' { $$ = new MachineAST($3, $4, NULL, $7, $9); } // | MACHINE_DECL '(' ident pair_list ')' ':' type_members '{' decl_list '}' { $$ = new MachineAST($3, $4, $7, string_vector, $9); } | MACHINE_DECL '(' ident pair_list ')' '{' decl_list '}' { $$ = new MachineAST($3, $4, NULL, new vector(), $7); } | 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; } ; 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; } ; 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; } ; type_enum: ident pair_list SEMICOLON { $$ = new TypeFieldEnumAST($1, $2); } ; // Type type_list : types { $$ = $1; } | { $$ = new Vector; } ; types : type ',' types { $3->insertAtTop($1); $$ = $3; } | type { $$ = new Vector; $$->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; } ; formal_params : formal_param ',' formal_params { $3->insertAtTop($1); $$ = $3; } | formal_param { $$ = new Vector; $$->insertAtTop($1); } ; formal_param : type ident { $$ = new FormalParamAST($1, $2); } ; // Idents and lists ident: IDENT { $$ = $1; }; ident_list: '{' idents '}' { $$ = $2; } | ident { $$ = new Vector; $$->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; } ; // 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; } ; expr_list: expr ',' expr_list { $3->insertAtTop($1); $$ = $3; } | expr { $$ = new Vector; $$->insertAtTop($1); } | { $$ = new Vector; } ; 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; } ; myrule: myrule IDENT { $1->push_back($2); } | IDENT { $$ = new vector(1, $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); }