%{ /* * This file is part of rasdaman community. * * Rasdaman community 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 * (at your option) any later version. * * Rasdaman community 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 rasdaman community. If not, see . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . */ //============================================================================== // // // // DESCRIPTION : Grammar description used to parse ODL files. // //============================================================================== #include #include #include #include "parse.hh" #include "yparse.hh" #include "symbtbl.hh" #include "raslib/minterval.hh" int yyparse(); extern int yylex(); extern long lineNumber; extern int columnNumber; YSymbolTable *Symbols=new YSymbolTable(); YSymbol *unique_symbol(const char*name,const YWhere&); // error handling void yyerror(const char* s); extern const YWhere *error_where; // associatted place in source code with error is NULL if no available extern const YWhere *error_source; // place where source of error extern const char *error_token; // outputs an error with an argument like "...%s.." or "...%i.." #define error_arg(OUTPUT,ARGUMENT,WHERE) \ { \ char buffer[1024]; \ sprintf(buffer,OUTPUT,ARGUMENT); \ \ error_where =WHERE; \ yyerror(buffer); \ }; %} %union{ // types for LEX struct { YWhere where; const char *name; } Entry; struct { YWhere where; int command; } Command; struct { YWhere where; long value; } LEX_integer; struct { YWhere where; double value; } Real; struct { YWhere where; char character; } Character; struct { YWhere where; const char *string; } String; // types for YACC YSymbol* Symbol; Parse_type* Type; Parse_interface* Interface; Parse_composite::Element* element; Parse_interface::Base_class* Base_Classes; Parse_interface::Lifetime Persistence; Parse_enum::Enumerator* enumerator; bool Boolean; rINT_list* INT_list; YLiteral Literal; YDeclarator* Declarator; // spatial domain r_Sinterval* dimension; struct { r_Minterval* domain; unsigned long dimensionality; } domainSpec; r_Minterval* domain; int dummyValue; } %token Identifier %token IntegerLiteral %token SEMI LPAR RPAR COLON COMMA TIMES TYPEDEF PFLOAT PDOUBLE PLONG PSHORT PUNSIGNED PCHAR PBOOLEAN POCTET PCOMPLEX1 PCOMPLEX2 PSTRUCT LEFT RIGHT LEPAR REPAR SET MARRAY /* types of nonterminals */ %type model,specification,definition; %type literal,primary_expr %type member,member_list %type scoped_name // enum_name %type type_spec,simple_type_spec,type_declarator, floating_pt_type,integer_type,signed_int,signed_long_int, signed_short_int,unsigned_int,unsigned_long_int, unsigned_short_int,char_type,boolean_type,octet_type,complex1_type,complex2_type, struct_type,marray_type, type_dcl,constr_type_spec, opt_marray_base,collection_type,base_type_spec, template_type_spec %type declarator,declarators,simple_declarator %type dimension_spec %type opt_spatial_domain %type spatial_domain,dimension_spec_list %% /*(0)*/ model : { Symbols->push_scope(NULL); } specification { Symbols->pop_scope(); } /*(1)*/ specification : definition | definition specification /*(2)*/ definition : type_dcl SEMI { $$ = NULL; } /*(11)*/ /**/ scoped_name : Identifier { if(!Symbols->search_scopes($1.name,$$)) error_arg("undefined symbol[%s]",$1.name,&$1.where); } /*(23)*/ /**/ primary_expr : literal { $$ = $1; } /*(24)*/ /**/ literal : IntegerLiteral { $$.Integer =$1.value; $$.type =YLiteral::dLinteger; } /*(27)*/ type_dcl : TYPEDEF type_declarator { $$ = $2; } | struct_type /*(28)*/ type_declarator : type_spec declarators { // for each declarator there exists a symbol // therefore generate only aliases for(YDeclarator*scan=$2;scan!=NULL;scan=scan->next) { Parse_alias *alias=new Parse_alias; alias->type=$1; alias->name=scan->symbol->get_name(); alias->symbol=scan->symbol; scan->symbol->Type =alias; scan->symbol->type =YSymbol::dParse_Type; scan->symbol->owned_by_symbol =false; // never owned by symbol }; } /*(29)*/ /**/ type_spec : simple_type_spec | constr_type_spec { Parse_typereference *reference=new Parse_typereference; reference->type=$1; reference->setParseInfo( $1->getParseInfo() ); $$=reference; } /*(30)*/ /**/ simple_type_spec : base_type_spec | template_type_spec | scoped_name { Parse_typereference *reference=new Parse_typereference; reference->type=$1->Type; reference->setParseInfo( Parse_info( $1->where, $1->get_name() ) ); $$=reference; } /*(31)*/ /**/ base_type_spec : floating_pt_type | integer_type | char_type | boolean_type | octet_type | complex1_type | complex2_type /*(32)*/ /**/ template_type_spec : collection_type | marray_type /*(32a)*/ /**/ collection_type : SET LEFT simple_type_spec RIGHT { $$=new Parse_set; $$->setParseInfo( Parse_info( $1.where, "Set" ) ); ((Parse_set*)$$)->base_type=$3; }; /*(33)*/ /**/ constr_type_spec : struct_type /*(34)*/ /**/ declarators : declarator | declarator COMMA declarators { $1->next =$3; $$ =$1; }; /*(35)*/ /**/ declarator : simple_declarator /*(36)*/ /**/ simple_declarator : Identifier { YSymbol *symbol=unique_symbol($1.name,$1.where); $$=new YDeclarator; $$->next =NULL; $$->symbol =symbol; $$->array_size =NULL; } /*(38)*/ /**/ floating_pt_type : PFLOAT { Parse_float *real=new Parse_float; real->accurance=Parse_float::Single; real->setParseInfo( Parse_info( $1.where, "float") ); $$=real; } | PDOUBLE { Parse_float *real=new Parse_float; real->accurance=Parse_float::Double; real->setParseInfo( Parse_info( $1.where, "double") ); $$=real; } /*(39)*/ /**/ integer_type : signed_int | unsigned_int /*(40)*/ /**/ signed_int : signed_long_int | signed_short_int /*(41)*/ /**/ signed_long_int : PLONG { Parse_int *integer=new Parse_int; integer->width =Parse_int::Long; integer->sign =Parse_int::Signed; integer->setParseInfo( Parse_info( $1.where, "long") ); $$=integer; } /*(42)*/ /**/ signed_short_int : PSHORT { Parse_int *integer=new Parse_int; integer->width =Parse_int::Short; integer->sign =Parse_int::Signed; integer->setParseInfo( Parse_info( $1.where, "short") ); $$=integer; } /*(43)*/ /**/ unsigned_int : unsigned_long_int | unsigned_short_int /*(44)*/ /**/ unsigned_long_int : PUNSIGNED PLONG { Parse_int *integer=new Parse_int; integer->width =Parse_int::Long; integer->sign =Parse_int::Unsigned; integer->setParseInfo( Parse_info( $1.where, "unsigned long") ); $$=integer; } /*(45)*/ /**/ unsigned_short_int : PUNSIGNED PSHORT { Parse_int *integer=new Parse_int; integer->width =Parse_int::Short; integer->sign =Parse_int::Unsigned; integer->setParseInfo( Parse_info( $1.where, "unsigned short") ); $$=integer; } /*(46)*/ /**/ char_type : PCHAR { $$=new Parse_char; $$->setParseInfo( Parse_info( $1.where, "char") ); } /*(47)*/ /**/ boolean_type : PBOOLEAN { $$=new Parse_boolean; $$->setParseInfo( Parse_info( $1.where, "boolean") ); } /*(48)*/ /**/ octet_type : POCTET { $$=new Parse_octet; $$->setParseInfo( Parse_info( $1.where, "octet") ); } /*(48a)*/ /**/ complex1_type : PCOMPLEX1 { $$=new Parse_complex1; $$->setParseInfo( Parse_info( $1.where, "complex") ); } /*(48b)*/ /**/ complex2_type : PCOMPLEX2 { $$=new Parse_complex2; $$->setParseInfo( Parse_info( $1.where, "complexd") ); } /*(50)*/ /**/ struct_type : PSTRUCT Identifier { YSymbol *symbol=unique_symbol($2.name,$1.where); symbol->type =YSymbol::dParse_Type; symbol->Type =new Parse_struct; symbol->Type->symbol =symbol; symbol->owned_by_symbol =false; // never owned by a symbol symbol->Type->setParseInfo( Parse_info( $1.where, "struct") ); Symbols->push_scope(symbol); } LPAR member_list RPAR { const YSymbol *symbol=Symbols->pop_scope(); $$=symbol->Type; $$->name =symbol->get_name(); ((Parse_struct*)$$)->elements =$5; } /*(51)*/ /**/ member_list : member | member member_list { Parse_composite::Element *scan=$1; while(scan->next!=NULL) scan=scan->next; scan->next=$2; $$=$1; } /*(52)*/ /**/ member : type_spec declarators SEMI { YDeclarator *scan=$2; Parse_composite::Element *current=NULL; for(;scan!=NULL;scan=scan->next) { if(current==NULL) { current=new Parse_composite::Element; $$=current; } else { current->next=new Parse_composite::Element; current=current->next; }; current->type=$1; current->name=scan->symbol->get_name(); }; }; /*(75)*/ /**/ marray_type : MARRAY LEFT opt_marray_base opt_spatial_domain RIGHT { $$=new Parse_MDD; ((Parse_MDD*)$$)->base_type =$3; ((Parse_MDD*)$$)->domain =$4.domain; ((Parse_MDD*)$$)->dimensionality =$4.dimensionality; } /**/ opt_marray_base : { $$=NULL; } | simple_type_spec /**/ opt_spatial_domain : { $$.domain=NULL; $$.dimensionality = 0; } | COMMA primary_expr { $$.domain=NULL; $$.dimensionality = $2.Integer; } | COMMA spatial_domain { $$.domain=$2; $$.dimensionality = 0; }; /*(76)*/ /**/ spatial_domain : LEPAR dimension_spec_list REPAR { $$ = $2; } /*(77)*/ /**/ dimension_spec_list : dimension_spec { $$ = new r_Minterval(1); (*$$)[0] = (*$1); delete $1; $1=NULL; } | dimension_spec COMMA dimension_spec_list { $$ = new r_Minterval( $3->dimension() + 1 ); (*$$)[0] = (*$1); delete $1; $1=NULL; for( int i=0; i<$3->dimension(); i++ ) (*$$)[i+1] = (*$3)[i]; delete $3; $3=NULL; } /*(78)*/ /**/ dimension_spec : primary_expr COLON primary_expr { $$=new r_Sinterval( (r_Range)$1.Integer, (r_Range)$3.Integer ); } | TIMES COLON primary_expr { $$=new r_Sinterval( '*' , (r_Range)$3.Integer ); } | primary_expr COLON TIMES { $$=new r_Sinterval( (r_Range)$1.Integer, '*' ); } | TIMES COLON TIMES { $$=new r_Sinterval( '*' , '*' ); } %% //**************************************************************************** // // name : unique_symbol // purpose : tries to create an unique symbol within scope // remarks : calls yyerror if name already exists in scope // //**************************************************************************** YSymbol *unique_symbol(const char*name,const YWhere&where) { YSymbol *symbol; if(!Symbols->scoped_symbol(&symbol,name,where)) { error_source=&symbol->where; error_token =name; error_arg("[%s] symbol already defined within scope",name,&where); }; return(symbol); }; const YWhere *error_source =NULL; const YWhere *error_where =NULL; const char *error_token =NULL; // associatted place in source code with error // is NULL if no available void yyerror(const char* s) { std::cout<<"error!\n"; if(error_where!=NULL) { std::cerr<<"\n pos : line "<line<<" colmun "<column; if(error_where->file!=NULL) std::cerr<<" in \""<file<<"\""; std::cerr<<".\n"; } else std::cerr<<"\n near : line "< "; std::cerr<<"error : "<line<<" column "<column; if(error_source->file!=NULL) std::cerr<<" in \""<file<<"\""; std::cerr<<".\n"; }; error_where =NULL; error_source=NULL; exit(-2); };