modules/up/src/rpsl/rpsl/rpsl.y

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. yyparse
  2. enable_yy_parser_debugging
  3. handleArgumentTypeError
  4. searchMethod

   1 %{
   2 //  $Id: rpsl.y,v 1.5 2001/03/16 14:10:31 engin Exp $
   3 //
   4 //  Copyright (c) 1994 by the University of Southern California
   5 //  All rights reserved.
   6 //
   7 //  Permission to use, copy, modify, and distribute this software and its
   8 //  documentation in source and binary forms for lawful non-commercial
   9 //  purposes and without fee is hereby granted, provided that the above
  10 //  copyright notice appear in all copies and that both the copyright
  11 //  notice and this permission notice appear in supporting documentation,
  12 //  and that any documentation, advertising materials, and other materials
  13 //  related to such distribution and use acknowledge that the software was
  14 //  developed by the University of Southern California, Information
  15 //  Sciences Institute. The name of the USC may not be used to endorse or
  16 //  promote products derived from this software without specific prior
  17 //  written permission.
  18 //
  19 //  THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
  20 //  REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
  21 //  PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  22 //  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  23 //  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
  24 //  TITLE, AND NON-INFRINGEMENT.
  25 //
  26 //  IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
  27 //  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
  28 //  OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
  29 //  OR PERFORMANCE OF THIS SOFTWARE.
  30 //
  31 //  Questions concerning this software should be directed to
  32 //  ratoolset@isi.edu.
  33 //
  34 //  Author(s): Cengiz Alaettinoglu <cengiz@ISI.EDU>
  35 
  36 #include "config.h"
  37 #include "time.h"
  38 #include "schema.hh"
  39 #include "object.hh"
  40 #include "regexp.hh"
  41 #include "rptype.hh"
  42 
  43 #ifdef DEBUG
  44 #define YYDEBUG 1
  45 #endif // DEBUG
  46 #if YYDEBUG != 0
  47 // stdio is needed for yydebug
  48 #include <cstdio>
  49 #endif
  50 
  51 extern void handle_error(char *, ...);
  52 extern void handle_object_error(char *, ...);
  53 extern void handle_warning(char *, ...);
  54 extern int yylex();
  55 char *token_name(int token_id);
  56 void rpslerror(char *s, ...);
  57 Attr *changeCurrentAttr(Attr *b);
  58 void handleArgumentTypeError(char *attr, char *method, int position,
  59                              const RPType *correctType, 
  60                              bool isOperator = false);
  61 const AttrMethod *searchMethod(const AttrRPAttr *rp_attr, char *method, ItemList *args);
  62 
  63 /* argument to yyparse result of parsing should be stored here */
  64 #define YYPARSE_PARAM object    
  65 #define yyschema schema
  66 #define enable_yy_parser_debugging enable_rpsl_parser_debugging
  67 
  68 extern Object *current_object;
  69 
  70 %}
  71 
  72 %expect 1
  73 
  74 %union {
  75    long long int      i;
  76    double             real;
  77    char              *string;
  78    void              *ptr;
  79    time_t             time;
  80    Item              *item;
  81    ItemList          *list;
  82    regexp            *re;
  83    SymID              sid;
  84    IPAddr            *ip;
  85    Prefix            *prfx;
  86    PrefixRange       *prfxrng;
  87    RPType            *typenode;
  88 
  89    Filter                    *filter;
  90    FilterMS                  *moreSpecOp;
  91    PolicyPeering             *peering;
  92    PolicyActionList          *actionList;
  93    PolicyAction              *actionNode;
  94    PolicyFactor              *policyFactor;
  95    PolicyTerm                *policyTerm;
  96    PolicyExpr                *policyExpr;
  97    List<PolicyPeeringAction> *peeringActionList;
  98 
  99    Attr               *attr;
 100    AttrAttr           *rpslattr;
 101    AttrMethod         *method;
 102    const AttrRPAttr   *rp_attr;
 103    const AttrProtocol *protocol;
 104    AttrProtocolOption *protocol_option;
 105    List<AttrProtocolOption> *protocol_option_list;
 106 
 107    AttrPeerOption       *peer_option;
 108    List<AttrPeerOption> *peer_option_list;
 109 
 110    List<RPTypeNode> *typelist;
 111    List<AttrMethod> *methodlist;
 112    List<WordNode>   *wordlist;
 113 
 114    List<AttrMntRoutes::MntPrfxPair> *listMntPrfxPair;
 115    AttrMntRoutes::MntPrfxPair       *mntPrfxPair;
 116 }
 117 
 118 %token          KEYW_TRUE
 119 %token          KEYW_FALSE
 120 %token          KEYW_ACTION
 121 %token          KEYW_ACCEPT
 122 %token          KEYW_ANNOUNCE
 123 %token          KEYW_FROM
 124 %token          KEYW_TO
 125 %token          KEYW_AT
 126 %token          KEYW_ANY
 127 %token          KEYW_REFINE
 128 %token          KEYW_EXCEPT
 129 %token          KEYW_STATIC
 130 %token          KEYW_NETWORKS
 131 %token          KEYW_MASKLEN
 132 %token          KEYW_UNION
 133 %token          KEYW_RANGE
 134 %token          KEYW_LIST
 135 %token          KEYW_OF
 136 %token          KEYW_OPERATOR
 137 %token          KEYW_SYNTAX
 138 %token          KEYW_SPECIAL
 139 %token          KEYW_OPTIONAL
 140 %token          KEYW_MANDATORY
 141 %token          KEYW_INTERNAL
 142 %token          KEYW_SINGLEVALUED
 143 %token          KEYW_MULTIVALUED
 144 %token          KEYW_LOOKUP
 145 %token          KEYW_KEY
 146 %token          KEYW_DELETED
 147 %token    KEYW_GENERATED
 148 %token          KEYW_OBSOLETE
 149 %token          KEYW_PEERAS
 150 %token          KEYW_PROTOCOL
 151 %token          KEYW_INTO
 152 %token          KEYW_ATOMIC
 153 %token          KEYW_INBOUND
 154 %token          KEYW_OUTBOUND
 155 %token          KEYW_UPON
 156 %token          KEYW_HAVE_COMPONENTS
 157 %token          KEYW_EXCLUDE
 158 
 159 %token    KEYW_NONE
 160 %token    KEYW_MAILFROM
 161 %token    KEYW_CRYPTPW
 162 %token    KEYW_ASSIGNED
 163 %token    KEYW_ALLOCATED
 164 %token    KEYW_PI
 165 %token    KEYW_PA
 166 %token    KEYW_UNSPECIFIED
 167 %token    KEYW_EXT
 168 %token    KEYW_SIMPLE
 169 %token    KEYW_RIPE
 170 %token    KEYW_INTERNIC
 171 %token    KEYW_CLIENTADDRESS
 172 
 173 
 174 %token          TKN_ERROR
 175 %token          TKN_UNKNOWN_CLASS
 176 %token          TKN_EOA         /* end of attribute */
 177 %token          TKN_EOO         /* end of object */
 178 %token          TKN_FREETEXT
 179 %token <i>      TKN_INT
 180 %token <real>   TKN_REAL
 181 %token <string> TKN_STRING
 182 %token <time>   TKN_TIMESTAMP
 183 %token <string> TKN_BLOB
 184 %token <ip>     TKN_IPV4
 185 %token <string> TKN_PRFXV6 
 186 %token <prfx>   TKN_PRFXV4
 187 %token <prfxrng>   TKN_PRFXV4RNG
 188 %token <i>      TKN_ASNO
 189 %token <sid>    TKN_ASNAME
 190 %token <sid>    TKN_RSNAME
 191 %token <sid>    TKN_RTRSNAME
 192 %token <sid>    TKN_PRNGNAME
 193 %token <sid>    TKN_FLTRNAME
 194 %token <i>      TKN_BOOLEAN
 195 %token <string> TKN_WORD
 196 %token <rp_attr> TKN_RP_ATTR
 197 %token <sid>    TKN_DNS
 198 %token <string> TKN_EMAIL
 199 %token          TKN_3DOTS
 200 
 201 %token <string> TKN_NICHDL
 202 %token <string> TKN_KEYCRTNAME
 203 %token <string> TKN_CRYPTEDPW
 204 
 205 %token <attr> ATTR_GENERIC
 206 %token <attr> ATTR_BLOBS
 207 %token <attr> ATTR_IMPORT
 208 %token <attr> ATTR_EXPORT
 209 %token <attr> ATTR_DEFAULT
 210 %token <attr> ATTR_FREETEXT
 211 %token <attr> ATTR_CHANGED
 212 %token <attr> ATTR_IFADDR
 213 %token <attr> ATTR_PEER
 214 %token <attr> ATTR_INJECT
 215 %token <attr> ATTR_COMPONENTS
 216 %token <attr> ATTR_AGGR_MTD
 217 %token <attr> ATTR_AGGR_BNDRY
 218 %token <attr> ATTR_RS_MEMBERS
 219 %token <attr> ATTR_RP_ATTR
 220 %token <attr> ATTR_TYPEDEF
 221 %token <attr> ATTR_PROTOCOL
 222 %token <attr> ATTR_FILTER
 223 %token <attr> ATTR_PEERING
 224 %token <attr> ATTR_ATTR
 225 %token <attr> ATTR_MNT_ROUTES
 226 
 227 %token <attr> ATTR_NICHDL
 228 %token <attr> ATTR_AUTH
 229 %token <attr> ATTR_STATUS_INET
 230 %token <attr> ATTR_PHONE
 231 %token <attr> ATTR_SOURCE
 232 %token <attr> ATTR_REFER
 233 %token <attr> ATTR_COUNTRY
 234 %token <attr> ATTR_PERSON
 235 
 236 %left             OP_OR 
 237 %left             OP_AND
 238 %right            OP_NOT
 239 %nonassoc<moreSpecOp> OP_MS
 240 %nonassoc<string> TKN_OPERATOR
 241 
 242 %type<list>      generic_list
 243 %type<list>      rs_members_list
 244 %type<list>      opt_rs_members_list
 245 %type<list>      blobs_list
 246 %type<list>      generic_non_empty_list
 247 %type<item>      list_item
 248 %type<item>      list_item_0
 249 %type<item>      rs_member
 250 
 251 %type<string>    tkn_word
 252 %type<string>    tkn_word_from_keyw
 253 
 254 %type<string>    tkn_word_from_keyw_none
 255 %type<string>    tkn_word_from_keyw_mailfrom
 256 %type<string>    tkn_word_from_keyw_cryptpw
 257 %type<string>    tkn_word_from_keyw_assigned
 258 %type<string>    tkn_word_from_keyw_allocated
 259 %type<string>    tkn_word_from_keyw_pi
 260 %type<string>    tkn_word_from_keyw_pa
 261 %type<string>    tkn_word_from_keyw_unspecified
 262 %type<string>    tkn_word_from_keyw_ext
 263 %type<string>    tkn_word_from_keyw_simple
 264 %type<string>    tkn_word_from_keyw_ripe
 265 %type<string>    tkn_word_from_keyw_internic
 266 %type<string>    tkn_word_from_keyw_clientaddress
 267 
 268 %type<attr>      attribute
 269 %type<attr>      generic_attribute
 270 %type<attr>      blobs_attribute
 271 %type<attr>      changed_attribute
 272 %type<attr>      ifaddr_attribute
 273 %type<attr>      peer_attribute
 274 %type<attr>      components_attribute
 275 %type<attr>      inject_attribute
 276 %type<attr>      aggr_mtd_attribute
 277 %type<attr>      aggr_bndry_attribute
 278 
 279 %type<attr>      import_attribute
 280 %type<attr>      export_attribute
 281 %type<attr>      default_attribute
 282 %type<attr>      typedef_attribute
 283 %type<attr>      rpattr_attribute
 284 %type<attr>      rs_members_attribute
 285 %type<attr>      protocol_attribute
 286 %type<attr>      filter_attribute
 287 %type<attr>      peering_attribute
 288 %type<attr>      attr_attribute
 289 %type<attr>      freetext_attribute
 290 %type<attr>      mnt_routes_attribute
 291 
 292 %type<attr>      nichdl_attribute
 293 %type<attr>      auth_attribute
 294 %type<attr>      status_inet_attribute
 295 %type<attr>      phone_attribute
 296 %type<attr>      source_attribute
 297 %type<attr>      refer_attribute
 298 %type<attr>      country_attribute
 299 %type<attr>      person_attribute
 300 
 301 %type<filter>    filter
 302 %type<filter>    opt_default_filter
 303 %type<filter>    filter_term
 304 %type<filter>    filter_factor
 305 %type<filter>    filter_operand
 306 %type<filter>    filter_prefix
 307 %type<filter>    filter_prefix_operand
 308 %type<filter>    opt_filter_prefix_list
 309 %type<filter>    filter_prefix_list
 310 %type<prfxrng>   filter_prefix_list_prefix
 311 %type<filter>    filter_rp_attribute
 312 
 313 %type<filter>    opt_as_expr
 314 %type<filter>    as_expr
 315 %type<filter>    as_expr_term
 316 %type<filter>    as_expr_factor
 317 %type<filter>    as_expr_operand
 318 
 319 %type<filter>    opt_router_expr
 320 %type<filter>    opt_router_expr_with_at
 321 %type<filter>    router_expr
 322 %type<filter>    router_expr_term
 323 %type<filter>    router_expr_factor
 324 %type<filter>    router_expr_operand
 325 
 326 %type<filter>    opt_inject_expr
 327 %type<filter>    inject_expr
 328 %type<filter>    inject_expr_term
 329 %type<filter>    inject_expr_factor
 330 %type<filter>    inject_expr_operand
 331 
 332 %type<re>    filter_aspath
 333 %type<re>    filter_aspath_term
 334 %type<re>    filter_aspath_closure
 335 %type<re>    filter_aspath_factor
 336 %type<re>    filter_aspath_no
 337 %type<re>    filter_aspath_range
 338 
 339 %type<actionList>      action
 340 %type<actionList>      opt_action
 341 %type<actionNode>      single_action
 342 
 343 %type<peering>     peering
 344 
 345 %type<peeringActionList> import_peering_action_list
 346 %type<peeringActionList> export_peering_action_list
 347 %type<policyFactor>      import_factor
 348 %type<policyTerm>        import_factor_list
 349 %type<policyTerm>        import_term
 350 %type<policyExpr>        import_expr
 351 %type<policyFactor>      export_factor
 352 %type<policyTerm>        export_factor_list
 353 %type<policyTerm>        export_term
 354 %type<policyExpr>        export_expr
 355 %type<protocol>          opt_protocol_from
 356 %type<protocol>          opt_protocol_into
 357 
 358 %type<wordlist>    enum_list
 359 %type<typenode>    typedef_type
 360 %type<typelist>    typedef_type_list
 361 
 362 %type<method>      method
 363 %type<methodlist>      methods
 364 
 365 %type<protocol_option> protocol_option
 366 %type<protocol_option_list> protocol_options
 367 
 368 %type<peer_option> peer_option
 369 %type<peer_option_list> peer_options
 370 %type<peer_option_list> opt_peer_options
 371 %type<ip> peer_id
 372 
 373 %type<rpslattr>    opt_attr_options
 374 %type<rpslattr>    attr_options
 375 %type<rpslattr>    attr_option
 376 
 377 %type<listMntPrfxPair>  mnt_routes_list
 378 %type<mntPrfxPair>      mnt_routes_list_item
 379 
 380 %type<string> int_list
 381 %type<string> name_list
 382 
 383 %%
     /* [<][>][^][v][top][bottom][index][help] */
 384 object: attribute_list TKN_EOO {
 385    YYACCEPT;
 386 }
 387 | TKN_UNKNOWN_CLASS TKN_EOO {
 388    YYACCEPT;
 389 }
 390 | error TKN_EOO {
 391    handle_object_error("Error: syntax error\n");
 392    YYABORT;
 393 }
 394 | attribute_list { // end of file
 395    YYACCEPT;
 396 }
 397 | TKN_UNKNOWN_CLASS { // end of file
 398    YYACCEPT;
 399 }
 400 | error { // end of file
 401    handle_object_error("Error: syntax error\n");
 402    YYABORT;
 403 }
 404 | { // end of file
 405    YYABORT;
 406 }
 407 ;
 408 
 409 attribute_list: attribute {
 410    (*current_object) += $1;
 411 }
 412 | attribute_list attribute {
 413    (*current_object) += $2;
 414 }
 415 ;
 416 
 417 attribute: generic_attribute
 418 | blobs_attribute
 419 | changed_attribute
 420 | import_attribute
 421 | export_attribute
 422 | default_attribute
 423 | peer_attribute
 424 | ifaddr_attribute
 425 | components_attribute
 426 | inject_attribute
 427 | aggr_mtd_attribute
 428 | aggr_bndry_attribute
 429 | typedef_attribute
 430 | protocol_attribute
 431 | rpattr_attribute
 432 | rs_members_attribute
 433 | filter_attribute
 434 | peering_attribute
 435 | attr_attribute
 436 | freetext_attribute
 437 | mnt_routes_attribute
 438 | nichdl_attribute
 439 | auth_attribute
 440 | status_inet_attribute
 441 | phone_attribute
 442 | source_attribute
 443 | refer_attribute
 444 | country_attribute
 445 | person_attribute
 446 | TKN_ERROR TKN_EOA { // the current line started w/ non-attribute
 447    $$ = changeCurrentAttr(new Attr);
 448    handle_error("Error: syntax error\n");
 449 }
 450 | error TKN_EOA {
 451    $$ = changeCurrentAttr(new Attr);
 452    handle_error("Error: syntax error\n");
 453    yyerrok;
 454 }
 455 ;
 456 
 457 //**** Generic Attributes ************************************************
 458 
 459 changed_attribute: ATTR_CHANGED TKN_EMAIL TKN_INT TKN_EOA {
 460    free($2);
 461    $$ = $1;
 462 }
 463 | ATTR_CHANGED TKN_EMAIL TKN_EOA {
 464    free($2);
 465    $$ = $1;
 466 }
 467 | ATTR_CHANGED error TKN_EOA {
 468    handle_error("Error: \"changed: <email> <YYYYMMDD>\" expected\n");
 469    yyerrok;
 470 }
 471 ;
 472 
 473 
 474 nichdl_attribute: ATTR_NICHDL TKN_NICHDL TKN_EOA {
 475    free($2);
 476    $$ = $1;
 477 }
 478 | ATTR_NICHDL error TKN_EOA {
 479   handle_error("Error: \"%s: <nic-handle>\" expected\n",$1->type->name());
 480   yyerrok; 
 481 }
 482 
 483 auth_attribute: ATTR_AUTH tkn_word_from_keyw_none TKN_EOA {
 484    $$ = $1;
 485 }
 486 | ATTR_AUTH tkn_word_from_keyw_mailfrom TKN_EMAIL TKN_EOA {
 487    free($3);
 488    $$ = $1;
 489 }
 490 | ATTR_AUTH tkn_word_from_keyw_cryptpw TKN_CRYPTEDPW TKN_EOA {
 491    free($3);
 492    $$ = $1; 
 493 }
 494 | ATTR_AUTH TKN_KEYCRTNAME TKN_EOA {
 495    free($2);
 496    $$ = $1;
 497 }
 498 | ATTR_AUTH error  TKN_EOA {
 499    handle_error("Error: \"auth: MAIL-FROM <regexp>\""
 500                 ", \"auth: NONE\", \"auth: CRYPT-PW <cryptedpaswd>\""
 501                 "  or \"auth: PGPKEY-<pgpid>\"  expected\n");
 502    yyerrok;
 503    
 504 } 
 505 ;
 506 
 507 
 508 
 509 status_inet_attribute: ATTR_STATUS_INET tkn_word_from_keyw_assigned tkn_word_from_keyw_pi TKN_EOA {
 510   $$ = $1;
 511 }
 512 | ATTR_STATUS_INET tkn_word_from_keyw_assigned tkn_word_from_keyw_pa TKN_EOA {
 513   $$ = $1;
 514 }
 515 | ATTR_STATUS_INET tkn_word_from_keyw_allocated tkn_word_from_keyw_pi TKN_EOA {
 516   $$ = $1;
 517 }
 518 | ATTR_STATUS_INET tkn_word_from_keyw_allocated tkn_word_from_keyw_pa TKN_EOA {
 519   $$ = $1;
 520 }
 521 | ATTR_STATUS_INET tkn_word_from_keyw_allocated tkn_word_from_keyw_unspecified TKN_EOA {
 522   $$ = $1;
 523 }
 524 | ATTR_STATUS_INET error TKN_EOA {
 525    handle_error("Error: \"status\" attribute contains invalid keywords\n");
 526    yyerrok;  
 527 }
 528 ;   
 529 
 530 phone_attribute:  ATTR_PHONE '+' int_list TKN_EOA {
 531   $$ = $1;
 532 }
 533 | ATTR_PHONE '+' int_list '(' int_list ')' int_list TKN_EOA {
 534   $$ = $1; 
 535 }
 536 | ATTR_PHONE '+' int_list tkn_word_from_keyw_ext '.' int_list TKN_EOA {
 537   $$ = $1; 
 538 }
 539 | ATTR_PHONE '+' int_list '(' int_list ')' int_list tkn_word_from_keyw_ext '.' int_list TKN_EOA {
 540   $$ = $1; 
 541 }
 542 | ATTR_PHONE error TKN_EOA {
 543    handle_error("Error: intn'l phone number expected (with a preceding '+')\n");
 544    yyerrok;
 545 }
 546 
 547 
 548 int_list: TKN_INT {
 549   //sprintf($$, "%i", $1);
 550   $$ = strdup("phone"); // well, sprintf($$, "%i", $1) didn't work
 551 }
 552 | int_list TKN_INT{
 553   $$ = $1;
 554 }
 555 | int_list '-' TKN_INT{
 556   $$ = $1;
 557 }
 558 | int_list '.' TKN_INT{
 559   $$ = $1;
 560 }
 561 
 562 
 563 source_attribute: ATTR_SOURCE tkn_word TKN_EOA {
 564   if(yyschema.searchSource($2)){
 565     free($2);
 566     $$ = $1;
 567   }else{
 568     free($2);
 569     handle_error("Error: No such source\n");
 570   }
 571 }
 572 | ATTR_SOURCE error TKN_EOA {
 573    handle_error("Error: invalid source attribute\n");
 574    yyerrok;
 575 }
 576 
 577 refer_attribute: ATTR_REFER tkn_word_from_keyw_simple TKN_DNS TKN_EOA {
 578    $$ = $1;
 579 }
 580 | ATTR_REFER tkn_word_from_keyw_simple TKN_DNS TKN_INT TKN_EOA {
 581    $$ = $1;
 582 }
 583 | ATTR_REFER tkn_word_from_keyw_ripe TKN_DNS TKN_EOA {
 584    $$ = $1;
 585 }
 586 | ATTR_REFER tkn_word_from_keyw_ripe TKN_DNS TKN_INT TKN_EOA {
 587    $$ = $1;
 588 }
 589 | ATTR_REFER tkn_word_from_keyw_internic TKN_DNS TKN_EOA {
 590    $$ = $1;
 591 }
 592 | ATTR_REFER tkn_word_from_keyw_internic TKN_DNS TKN_INT TKN_EOA {
 593    $$ = $1;
 594 }
 595 | ATTR_REFER tkn_word_from_keyw_clientaddress TKN_DNS TKN_EOA {
 596    $$ = $1;
 597 }
 598 | ATTR_REFER tkn_word_from_keyw_clientaddress TKN_DNS TKN_INT TKN_EOA {
 599    $$ = $1;
 600 }
 601 | ATTR_REFER error TKN_EOA {
 602    handle_error("Error: invalid refer attribute\n");
 603    yyerrok;
 604 }
 605 
 606 country_attribute: ATTR_COUNTRY tkn_word TKN_EOA {
 607   if(yyschema.searchCountry($2)){
 608     free($2);
 609     $$ = $1;
 610   }else{
 611     free($2);
 612     handle_error("Error: No such country\n");
 613   }
 614 }
 615 | ATTR_COUNTRY error TKN_EOA {
 616    handle_error("Error: invalid country attribute\n");
 617    yyerrok;
 618 }
 619 
 620 person_attribute: ATTR_PERSON tkn_word name_list TKN_EOA {
 621   $$ = $1;
 622 }
 623 | ATTR_PERSON error TKN_EOA {
 624    handle_error("Error: invalid %s attribute\n",$1->type->name());
 625    yyerrok;
 626 }
 627 
 628 name_list: tkn_word {
 629   $$ = strdup($1);
 630 }
 631 | name_list tkn_word {
 632   $$ = strdup($2);
 633 }
 634 
 635 
 636 freetext_attribute: ATTR_FREETEXT TKN_EOA {
 637    char *start = strchr($1->object->contents + $1->offset, ':') + 1;
 638    int len = $1->object->contents + $1->offset + $1->len - start;
 639    ItemFREETEXT *ft = new ItemFREETEXT(start, len);
 640    ItemList *il = new ItemList;
 641    il->append(ft);
 642    
 643    $$ = changeCurrentAttr(new AttrGeneric($1->type, il));
 644 }
 645 ;
 646 
 647 generic_attribute: ATTR_GENERIC generic_list TKN_EOA {
 648    if (!$1->type->subsyntax()->validate($2)) {
 649       handle_error("Error: argument to %s should be %s.\n",
 650               $1->type->name(), $1->type->subsyntax()->name());
 651       delete $2;
 652       $$ = changeCurrentAttr(new AttrGeneric($1->type, NULL));
 653    } else 
 654       $$ = changeCurrentAttr(new AttrGeneric($1->type, $2));
 655 }
 656 | ATTR_GENERIC error TKN_EOA {
 657    $$ = $1;
 658    handle_error("Error: argument to %s should be %s.\n",
 659            $1->type->name(), $1->type->subsyntax()->name());
 660    yyerrok;
 661 }
 662 ;
 663 
 664 generic_list: /* empty list */ {
 665    $$ = new ItemList;
 666 }
 667 | generic_non_empty_list
 668 ;
 669 
 670 generic_non_empty_list: list_item {     
 671    $$ = new ItemList;
 672    $$->append($1);
 673 }
 674 | generic_non_empty_list ',' list_item {
 675    $$ = $1;
 676    $$->append($3);
 677 }
 678 ;
 679 
 680 blobs_attribute: ATTR_BLOBS blobs_list TKN_EOA {
 681    $$ = changeCurrentAttr(new AttrGeneric($1->type, $2));
 682 }
 683 | ATTR_BLOBS error TKN_EOA {
 684    $$ = $1;
 685    handle_error("Error: argument to %s should be blob sequence.\n",
 686            $1->type->name());
 687    yyerrok;
 688 }
 689 ;
 690 
 691 blobs_list: list_item {         
 692    $$ = new ItemList;
 693    $$->append($1);
 694 }
 695 | blobs_list list_item {
 696    $$ = $1;
 697    $$->append($2);
 698 }
 699 ;
 700 
 701 list_item: list_item_0 {
 702    $$ = $1;
 703 }
 704 | list_item_0 '-' list_item_0 {
 705    $$ = new ItemRange($1, $3);
 706 }
 707 ;
 708 
 709 list_item_0: TKN_ASNO {
 710    $$ = new ItemASNO($1);
 711 }
 712 | TKN_INT {
 713    $$ = new ItemINT($1);
 714 }
 715 | TKN_REAL {
 716    $$ = new ItemREAL($1);
 717 }
 718 | TKN_STRING {
 719    $$ = new ItemSTRING($1);
 720 }
 721 | TKN_TIMESTAMP {
 722    $$ = new ItemTimeStamp($1);
 723 }
 724 | TKN_IPV4 {
 725    $$ = new ItemIPV4($1);
 726 }
 727 | TKN_PRFXV4 {
 728    $$ = new ItemPRFXV4($1);
 729 }
 730 | TKN_PRFXV6 {
 731    $$ = new ItemPRFXV6($1);
 732 }
 733 | TKN_PRFXV4RNG {
 734    $$ = new ItemPRFXV4Range($1);
 735 }
 736 | TKN_IPV4 ':' TKN_INT {
 737    $$ = new ItemConnection($1, $3);
 738 }
 739 | TKN_IPV4 ':' TKN_INT ':' TKN_INT {
 740    $$ = new ItemConnection($1, $3, $5);
 741 }
 742 | TKN_DNS ':' TKN_INT {
 743    $$ = new ItemConnection($1, $3);
 744 }
 745 | TKN_DNS ':' TKN_INT ':' TKN_INT {
 746    $$ = new ItemConnection($1, $3, $5);
 747 }
 748 | TKN_ASNAME {
 749    $$ = new ItemASNAME($1);
 750 }
 751 | TKN_RSNAME {
 752    $$ = new ItemRSNAME($1);
 753 }
 754 | TKN_RTRSNAME {
 755    $$ = new ItemRTRSNAME($1);
 756 }
 757 | TKN_PRNGNAME {
 758    $$ = new ItemPRNGNAME($1);
 759 }
 760 | TKN_FLTRNAME {
 761    $$ = new ItemFLTRNAME($1);
 762 }
 763 | TKN_BOOLEAN {
 764    $$ = new ItemBOOLEAN($1);
 765 }
 766 | TKN_WORD {
 767    $$ = new ItemWORD($1);
 768 }
 769 | tkn_word_from_keyw {
 770    $$ = new ItemWORD($1);
 771 }
 772 | TKN_DNS {
 773    $$ = new ItemDNS($1);
 774 }
 775 | TKN_EMAIL {
 776    $$ = new ItemEMAIL($1);
 777 }
 778 | TKN_KEYCRTNAME {
 779    $$ = new ItemKEYCRTNAME($1);
 780 }
 781 | TKN_BLOB {
 782    $$ = new ItemBLOB($1);
 783 }
 784 | '{' generic_list '}'  {
 785    $$ = $2;
 786 }
 787 | '(' filter ')' {
 788    $$ = new ItemFilter($2);
 789 }
 790 ;
 791 
 792 tkn_word: TKN_WORD {
 793    $$ = $1;
 794 }
 795 | TKN_ASNO {
 796    char buffer[64];
 797    sprintf(buffer, "AS%d", $1);
 798    $$ = strdup(buffer);
 799 }
 800 | TKN_ASNAME {
 801    $$ = strdup($1);
 802 }
 803 | TKN_RSNAME {
 804    $$ = strdup($1);
 805 }
 806 | TKN_RTRSNAME {
 807    $$ = strdup($1);
 808 }
 809 | TKN_PRNGNAME {
 810    $$ = strdup($1);
 811 }
 812 | TKN_FLTRNAME {
 813    $$ = strdup($1);
 814 }
 815 | TKN_NICHDL {
 816    $$ = strdup($1);
 817 }
 818 | TKN_BOOLEAN {
 819    if ($1)
 820       $$ = strdup("true");
 821    else
 822       $$ = strdup("false");
 823 }
 824 | tkn_word_from_keyw
 825 | tkn_word_from_keyw_ripe
 826 | tkn_word_from_keyw_internic
 827 | tkn_word_from_keyw_simple
 828 | tkn_word_from_keyw_clientaddress
 829 ;
 830 
 831 tkn_word_from_keyw: KEYW_TRUE {
 832    $$ = strdup("true");
 833 }
 834 | KEYW_FALSE {
 835    $$ = strdup("false");
 836 }
 837 | KEYW_ACTION {
 838    $$ = strdup("action");
 839 }
 840 | KEYW_ACCEPT {
 841    $$ = strdup("accept");
 842 }
 843 | KEYW_ANNOUNCE {
 844    $$ = strdup("announce");
 845 }
 846 | KEYW_FROM {
 847    $$ = strdup("from");
 848 }
 849 | KEYW_TO {
 850    $$ = strdup("to");
 851 }
 852 | KEYW_AT {
 853    $$ = strdup("at");
 854 }
 855 | KEYW_ANY {
 856    $$ = strdup("any");
 857 }
 858 | KEYW_REFINE {
 859    $$ = strdup("refine");
 860 }
 861 | KEYW_EXCEPT {
 862    $$ = strdup("except");
 863 }
 864 | KEYW_STATIC {
 865    $$ = strdup("static");
 866 }
 867 | KEYW_NETWORKS {
 868    $$ = strdup("networks");
 869 }
 870 | KEYW_MASKLEN {
 871    $$ = strdup("masklen");
 872 }
 873 | KEYW_UNION {
 874    $$ = strdup("union");
 875 }
 876 | KEYW_RANGE {
 877    $$ = strdup("range");
 878 }
 879 | KEYW_LIST {
 880    $$ = strdup("list");
 881 }
 882 | KEYW_OF {
 883    $$ = strdup("of");
 884 }
 885 | KEYW_OPERATOR {
 886    $$ = strdup("operator");
 887 }
 888 | KEYW_SYNTAX {
 889    $$ = strdup("syntax");
 890 }
 891 | KEYW_SPECIAL {
 892    $$ = strdup("special");
 893 }
 894 | KEYW_OPTIONAL {
 895    $$ = strdup("optional");
 896 }
 897 | KEYW_MANDATORY {
 898    $$ = strdup("mandatory");
 899 }
 900 | KEYW_INTERNAL {
 901    $$ = strdup("internal");
 902 }
 903 | KEYW_DELETED {
 904    $$ = strdup("deleted");
 905 }
 906 | KEYW_SINGLEVALUED {
 907    $$ = strdup("singlevalued");
 908 }
 909 | KEYW_GENERATED {
 910    $$ = strdup("generated");
 911 }
 912 | KEYW_MULTIVALUED {
 913    $$ = strdup("multivalued");
 914 }
 915 | KEYW_LOOKUP {
 916    $$ = strdup("lookup");
 917 }
 918 | KEYW_KEY {
 919    $$ = strdup("key");
 920 }
 921 | KEYW_OBSOLETE {
 922    $$ = strdup("obsolete");
 923 }
 924 | KEYW_PEERAS {
 925    $$ = strdup("peeras");
 926 }
 927 | KEYW_PROTOCOL {
 928    $$ = strdup("protocol");
 929 }
 930 | KEYW_INTO {
 931    $$ = strdup("into");
 932 }
 933 | KEYW_ATOMIC {
 934    $$ = strdup("atomic");
 935 }
 936 | KEYW_INBOUND {
 937    $$ = strdup("inbound");
 938 }
 939 | KEYW_OUTBOUND {
 940    $$ = strdup("outbound");
 941 }
 942 ;
 943 
 944 tkn_word_from_keyw_none: KEYW_NONE {
 945    $$ = strdup("none");
 946 }
 947 
 948 tkn_word_from_keyw_mailfrom: KEYW_MAILFROM {
 949    $$ = strdup("mail-from");
 950 }
 951 
 952 tkn_word_from_keyw_cryptpw: KEYW_CRYPTPW {
 953    $$ = strdup("crypt-pw");
 954 }
 955 
 956 tkn_word_from_keyw_assigned: KEYW_ASSIGNED {
 957    $$ = strdup("assigned");
 958 }
 959 
 960 tkn_word_from_keyw_allocated: KEYW_ALLOCATED {
 961    $$ = strdup("allocated");
 962 }
 963 
 964 tkn_word_from_keyw_pi: KEYW_PI {
 965    $$ = strdup("pi");
 966 }
 967 
 968 tkn_word_from_keyw_pa: KEYW_PA {
 969    $$ = strdup("pa");
 970 }
 971 
 972 tkn_word_from_keyw_unspecified: KEYW_UNSPECIFIED {
 973    $$ = strdup("unspecified");
 974 }
 975 
 976 tkn_word_from_keyw_ext: KEYW_EXT {
 977    $$ = strdup("ext");
 978 }
 979 
 980 tkn_word_from_keyw_simple: KEYW_SIMPLE {
 981    $$ = strdup("simple");
 982 }
 983 
 984 tkn_word_from_keyw_ripe: KEYW_RIPE {
 985    $$ = strdup("ripe");
 986 }
 987 
 988 tkn_word_from_keyw_internic: KEYW_INTERNIC {
 989    $$ = strdup("internic");
 990 }
 991 
 992 tkn_word_from_keyw_clientaddress: KEYW_CLIENTADDRESS {
 993    $$ = strdup("clientaddress");
 994 }
 995 
 996 
 997 //**** aut-num class ******************************************************
 998 
 999 //// as_expr ////////////////////////////////////////////////////////////
1000 
1001 opt_as_expr: {
1002    $$ = new FilterASNAME(symbols.symID("AS-ANY"));
1003 }
1004 | as_expr 
1005 ;
1006 
1007 as_expr: as_expr OP_OR as_expr_term {
1008    $$ = new FilterOR($1, $3);
1009 }
1010 | as_expr_term
1011 ;
1012 
1013 as_expr_term: as_expr_term OP_AND as_expr_factor {
1014    $$ = new FilterAND($1, $3);
1015 }
1016 | as_expr_term KEYW_EXCEPT as_expr_factor {
1017    $$ = new FilterEXCEPT($1, $3);
1018 }
1019 | as_expr_factor
1020 ;
1021 
1022 as_expr_factor: '(' as_expr ')' {
1023    $$ = $2;
1024 }
1025 | as_expr_operand 
1026 ;
1027 
1028 as_expr_operand: TKN_ASNO {
1029    $$ = new FilterASNO($1);
1030 }
1031 | TKN_ASNAME {
1032    $$ = new FilterASNAME($1);
1033 }
1034 ;
1035 
1036 //// router_expr ///////////////////////////////////////////////////////////
1037 
1038 opt_router_expr: {
1039    $$ = new FilterANY;
1040 }
1041 | router_expr {
1042    $$ = $1;
1043 }
1044 ;
1045 
1046 opt_router_expr_with_at: {
1047    $$ = new FilterANY;
1048 }
1049 | KEYW_AT router_expr {
1050    $$ = $2;
1051 }
1052 ;
1053 
1054 router_expr: router_expr OP_OR router_expr_term {
1055    $$ = new FilterOR($1, $3);
1056 }
1057 | router_expr_term
1058 ;
1059 
1060 router_expr_term: router_expr_term OP_AND router_expr_factor {
1061    $$ = new FilterAND($1, $3);
1062 }
1063 | router_expr_term KEYW_EXCEPT router_expr_factor {
1064    $$ = new FilterEXCEPT($1, $3);
1065 }
1066 | router_expr_factor
1067 ;
1068 
1069 router_expr_factor: '(' router_expr ')' {
1070    $$ = $2;
1071 }
1072 | router_expr_operand 
1073 ;
1074 
1075 router_expr_operand: TKN_IPV4 {
1076    $$ = new FilterRouter($1);
1077 }
1078 | TKN_DNS {
1079    $$ = new FilterRouterName($1);
1080 }
1081 | TKN_RTRSNAME {
1082    $$ = new FilterRTRSNAME($1);
1083 }
1084 ;
1085 
1086 //// peering ////////////////////////////////////////////////////////////
1087 
1088 peering: as_expr opt_router_expr opt_router_expr_with_at {
1089    $$ = new PolicyPeering($1, $2, $3);
1090 }
1091 | TKN_PRNGNAME {
1092    $$ = new PolicyPeering($1);
1093 } 
1094 ;
1095 
1096 //// action /////////////////////////////////////////////////////////////
1097 
1098 opt_action: {
1099    $$ = new PolicyActionList;
1100 }
1101 | KEYW_ACTION action {
1102    $$ = $2;
1103 }
1104 ;
1105 
1106 action: single_action {
1107    $$ = new PolicyActionList;
1108    if ($1)
1109       $$->append($1);  
1110 }
1111 | action single_action {
1112    $$ = $1;
1113    if ($2)
1114       $$->append($2);  
1115 }
1116 ;
1117 
1118 single_action: TKN_RP_ATTR '.' TKN_WORD '(' generic_list ')' ';' {
1119    const AttrMethod *mtd = searchMethod($1, $3, $5);
1120    if (mtd)
1121       $$ = new PolicyAction($1, mtd, $5);
1122    else {
1123       delete $5;
1124       $$ = NULL;
1125    }
1126    free($3);
1127 }
1128 | TKN_RP_ATTR TKN_OPERATOR list_item ';'  {
1129    ItemList *plist = new ItemList;
1130    plist->append($3);
1131 
1132    const AttrMethod *mtd = searchMethod($1, $2, plist);
1133    if (mtd)
1134       $$ = new PolicyAction($1, mtd, plist);
1135    else {
1136       delete plist;
1137       $$ = NULL;
1138    }
1139    // Added by wlee
1140    free($2);
1141 }
1142 | TKN_RP_ATTR '(' generic_list ')' ';' {
1143    const AttrMethod *mtd = searchMethod($1, "()", $3);
1144    if (mtd)
1145       $$ = new PolicyAction($1, mtd, $3);
1146    else {
1147       delete $3;
1148       $$ = NULL;
1149    }
1150 }
1151 | TKN_RP_ATTR '[' generic_list ']' ';' {
1152    const AttrMethod *mtd = searchMethod($1, "[]", $3);
1153    if (mtd)
1154       $$ = new PolicyAction($1, mtd, $3);
1155    else {
1156       delete $3;
1157       $$ = NULL;
1158    }
1159 }
1160 | ';' {
1161    $$ = NULL;
1162 }
1163 ;
1164 
1165 //// filter /////////////////////////////////////////////////////////////
1166 
1167 filter: filter OP_OR filter_term {
1168    $$ = new FilterOR($1, $3);
1169 }
1170 | filter filter_term %prec OP_OR {
1171    $$ = new FilterOR($1, $2);
1172 }
1173 | filter_term
1174 ;
1175 
1176 filter_term : filter_term OP_AND filter_factor {
1177    $$ = new FilterAND($1, $3);
1178 }
1179 | filter_factor
1180 ;
1181 
1182 filter_factor :  OP_NOT filter_factor {
1183    $$ = new FilterNOT($2);
1184 }
1185 | '(' filter ')' {
1186    $$ = $2;
1187 }
1188 | filter_operand 
1189 ;
1190 
1191 filter_operand: KEYW_ANY {
1192    $$ = new FilterANY;
1193 }
1194 | '<' filter_aspath '>' {
1195    $$ = new FilterASPath($2);
1196 }
1197 | filter_rp_attribute {
1198    if ($1)
1199       $$ = $1;
1200    else
1201       $$ = new FilterNOT(new FilterANY);
1202 }
1203 | TKN_FLTRNAME {
1204    $$ = new FilterFLTRNAME($1);
1205 }
1206 | filter_prefix
1207 ;
1208 
1209 filter_prefix: filter_prefix_operand OP_MS {
1210    $2->f1 = $1;
1211    $$ = $2;
1212 }
1213 |  filter_prefix_operand
1214 ;
1215 
1216 filter_prefix_operand: TKN_ASNO {
1217    $$ = new FilterASNO($1);
1218 }
1219 | KEYW_PEERAS {
1220    $$ = new FilterPeerAS;
1221 }
1222 | TKN_ASNAME {
1223    $$ = new FilterASNAME($1);
1224 }
1225 | TKN_RSNAME {
1226    $$ = new FilterRSNAME($1);
1227 }
1228 | '{' opt_filter_prefix_list '}' { 
1229    $$ = $2; 
1230 }
1231 ;
1232 
1233 opt_filter_prefix_list: {
1234    $$ = new FilterPRFXList;
1235 }
1236 | filter_prefix_list
1237 ;
1238 
1239 filter_prefix_list: filter_prefix_list_prefix {
1240    ((FilterPRFXList *) ($$ = new FilterPRFXList))->add_high(*$1);
1241    delete $1;
1242 }
1243 | filter_prefix_list ',' filter_prefix_list_prefix {
1244    $$ = $1;
1245    ((FilterPRFXList *) ($$))->add_high(*$3);
1246    delete $3;
1247 }
1248 ;
1249 
1250 filter_prefix_list_prefix: TKN_PRFXV4 {
1251    $$ = $1;
1252 }
1253 | TKN_PRFXV4RNG {
1254    $$ = $1;
1255 }
1256 ;
1257 
1258 filter_aspath: filter_aspath '|' filter_aspath_term {
1259    $$ = new regexp_or($1, $3);
1260 }
1261 | filter_aspath_term
1262 ;
1263 
1264 filter_aspath_term: filter_aspath_term filter_aspath_closure {
1265    $$ = new regexp_cat($1, $2);
1266 }
1267 | filter_aspath_closure
1268 ;
1269 
1270 filter_aspath_closure: filter_aspath_closure '*' {
1271    $$ = new regexp_star($1);
1272 }
1273 | filter_aspath_closure '?' {
1274    $$ = new regexp_question($1);
1275 }
1276 | filter_aspath_closure '+' {
1277    $$ = new regexp_plus($1);
1278 }
1279 | filter_aspath_factor
1280 ;
1281 
1282 filter_aspath_factor: '^' {
1283    $$ = new regexp_bol;
1284 }
1285 | '$' {
1286    $$ = new regexp_eol;
1287 }
1288 | '(' filter_aspath ')' {
1289    $$ = $2;
1290 }
1291 | filter_aspath_no
1292 ;
1293 
1294 filter_aspath_no: TKN_ASNO {
1295    $$ = new regexp_symbol($1);
1296 }
1297 | KEYW_PEERAS {
1298    $$ = new regexp_symbol(symbols.symID("PEERAS"));
1299 }
1300 | TKN_ASNAME {
1301    $$ = new regexp_symbol($1);
1302 }
1303 | '.' {
1304    $$ = new regexp_symbol(regexp_symbol::MIN_AS, regexp_symbol::MAX_AS);
1305 }
1306 | '[' filter_aspath_range ']' {
1307    $$ = $2;
1308 }
1309 | '[' '^' filter_aspath_range ']' {
1310    $$ = $3;
1311    ((regexp_symbol *) $$)->complement();
1312 }
1313 ;
1314 
1315 filter_aspath_range: {
1316    $$ = new regexp_symbol;
1317 }
1318 | filter_aspath_range TKN_ASNO {
1319    ((regexp_symbol *) ($$ = $1))->add($2);
1320 }
1321 | filter_aspath_range KEYW_PEERAS {
1322    ((regexp_symbol *) ($$ = $1))->add(symbols.symID("PEERAS"));
1323 }
1324 | filter_aspath_range '.' {
1325    ((regexp_symbol *) ($$ = $1))->add(regexp_symbol::MIN_AS, regexp_symbol::MAX_AS);
1326 }
1327 | filter_aspath_range TKN_ASNO '-' TKN_ASNO {
1328    ((regexp_symbol *) ($$ = $1))->add($2, $4);
1329 }
1330 | filter_aspath_range TKN_ASNAME {
1331    ((regexp_symbol *) ($$ = $1))->add($2);
1332 }
1333 ;
1334 
1335 filter_rp_attribute: TKN_RP_ATTR '.' TKN_WORD '(' generic_list ')' {
1336    const AttrMethod *mtd = searchMethod($1, $3, $5);
1337    if (mtd)
1338       $$ = new FilterRPAttribute($1, mtd, $5);
1339    else {
1340       delete $5;
1341       $$ = NULL;
1342    }
1343    free($3);
1344 }
1345 | TKN_RP_ATTR TKN_OPERATOR list_item {
1346    ItemList *plist = new ItemList;
1347    plist->append($3);
1348 
1349    const AttrMethod *mtd = searchMethod($1, $2, plist);
1350    if (mtd)
1351       $$ = new FilterRPAttribute($1, mtd, plist);
1352    else {
1353       delete plist;
1354       $$ = NULL;
1355    }
1356    // Added by wlee
1357    free($2);
1358 }
1359 | TKN_RP_ATTR '(' generic_list ')' {
1360    const AttrMethod *mtd = searchMethod($1, "()", $3);
1361    if (mtd)
1362       $$ = new FilterRPAttribute($1, mtd, $3);
1363    else {
1364       delete $3;
1365       $$ = NULL;
1366    }
1367 }
1368 | TKN_RP_ATTR '[' generic_list ']' {
1369    const AttrMethod *mtd = searchMethod($1, "[]", $3);
1370    if (mtd)
1371       $$ = new FilterRPAttribute($1, mtd, $3);
1372    else {
1373       delete $3;
1374       $$ = NULL;
1375    }
1376 }
1377 ;
1378 
1379 //// peering action pair ////////////////////////////////////////////////
1380 
1381 import_peering_action_list: KEYW_FROM peering opt_action {
1382    $$ = new List<PolicyPeeringAction>;
1383    $$->append(new PolicyPeeringAction($2, $3));
1384 }
1385 | import_peering_action_list KEYW_FROM peering opt_action {
1386    $$ = $1;
1387    $$->append(new PolicyPeeringAction($3, $4));
1388 }
1389 ;
1390 
1391 export_peering_action_list: KEYW_TO peering opt_action {
1392    $$ = new List<PolicyPeeringAction>;
1393    $$->append(new PolicyPeeringAction($2, $3));
1394 }
1395 | export_peering_action_list KEYW_TO peering opt_action {
1396    $$ = $1;
1397    $$->append(new PolicyPeeringAction($3, $4));
1398 }
1399 ;
1400 
1401 //// import/export factor ///////////////////////////////////////////////
1402 
1403 import_factor: import_peering_action_list KEYW_ACCEPT filter  {
1404    $$ = new PolicyFactor($1, $3);
1405 }
1406 ;
1407 
1408 import_factor_list: import_factor ';' {
1409    $$ = new PolicyTerm;
1410    $$->append($1);
1411 }
1412 | import_factor_list import_factor ';' {
1413    $$ = $1;
1414    $$->append($2);
1415 }
1416 ;
1417 
1418 export_factor: export_peering_action_list KEYW_ANNOUNCE filter  {
1419    $$ = new PolicyFactor($1, $3);
1420 }
1421 ;
1422 
1423 export_factor_list: export_factor ';' {
1424    $$ = new PolicyTerm;
1425    $$->append($1);
1426 }
1427 | export_factor_list export_factor ';' {
1428    $$ = $1;
1429    $$->append($2);
1430 }
1431 ;
1432 
1433 //// import/export term /////////////////////////////////////////////////
1434 
1435 import_term: import_factor ';' {
1436    PolicyTerm *term = new PolicyTerm;
1437    term->append($1);
1438    $$ = term;
1439 }
1440 | '{' import_factor_list '}' {
1441    $$ = $2;
1442 }
1443 ;
1444 
1445 export_term: export_factor ';' {
1446    PolicyTerm *term = new PolicyTerm;
1447    term->append($1);
1448    $$ = term;
1449 }
1450 | '{' export_factor_list '}' {
1451    $$ = $2;
1452 }
1453 ;
1454 
1455 //// import/export expr /////////////////////////////////////////////////
1456 
1457 import_expr: import_term {
1458    $$ = $1;
1459 }
1460 | import_term KEYW_REFINE import_expr {
1461    $$ = new PolicyRefine($1, $3);
1462 }
1463 | import_term KEYW_EXCEPT import_expr {
1464    $$ = new PolicyExcept($1, $3);
1465 }
1466 ;
1467 
1468 export_expr: export_term {
1469    $$ = $1;
1470 }
1471 | export_term KEYW_REFINE export_expr {
1472    $$ = new PolicyRefine($1, $3);
1473 }
1474 | export_term KEYW_EXCEPT export_expr {
1475    $$ = new PolicyExcept($1, $3);
1476 }
1477 ;
1478 
1479 //// protocol ///////////////////////////////////////////////////////////
1480 
1481 opt_protocol_from: {
1482    $$ = schema.searchProtocol("BGP4");
1483 }
1484 | KEYW_PROTOCOL tkn_word {
1485    $$ = schema.searchProtocol($2);
1486    if (!$$) {
1487       handle_warning("Warning: unknown protocol %s, BGP4 assumed.\n", $2);
1488       $$ = schema.searchProtocol("BGP4");
1489    }
1490    free($2);
1491 }
1492 ;
1493 
1494 opt_protocol_into: {
1495    $$ = schema.searchProtocol("BGP4");
1496 }
1497 | KEYW_INTO tkn_word {
1498    $$ = schema.searchProtocol($2);
1499    if (!$$) {
1500       handle_warning("Warning: unknown protocol %s, BGP4 assumed.\n", $2);
1501       $$ = schema.searchProtocol("BGP4");
1502    }
1503    free($2);;
1504 }
1505 ;
1506 
1507 //**** import/export attributes *******************************************
1508 
1509 import_attribute: ATTR_IMPORT 
1510                   opt_protocol_from opt_protocol_into 
1511                   import_expr TKN_EOA {
1512    $$ = changeCurrentAttr(new AttrImport($2, $3, $4));
1513 }
1514 | ATTR_IMPORT opt_protocol_from opt_protocol_into import_factor TKN_EOA {
1515    PolicyTerm *term = new PolicyTerm;
1516    term->append($4);
1517 
1518    $$ = changeCurrentAttr(new AttrImport($2, $3, term));
1519 }
1520 | ATTR_IMPORT error TKN_EOA {
1521    $$ = $1;
1522    handle_error("Error: from <peering> expected.\n");
1523    yyerrok;
1524 }
1525 ;
1526 
1527 export_attribute: ATTR_EXPORT 
1528                   opt_protocol_from opt_protocol_into 
1529                   export_expr TKN_EOA {
1530    $$ = changeCurrentAttr(new AttrExport($2, $3, $4));
1531 }
1532 | ATTR_EXPORT opt_protocol_from opt_protocol_into export_factor TKN_EOA {
1533    PolicyTerm *term = new PolicyTerm;
1534    term->append($4);
1535 
1536    $$ = changeCurrentAttr(new AttrExport($2, $3, term));
1537 }
1538 | ATTR_EXPORT error TKN_EOA {
1539    $$ = $1;
1540    handle_error("Error: to <peering> expected.\n");
1541    yyerrok;
1542 }
1543 ;
1544 
1545 opt_default_filter: {
1546    $$ = new FilterANY;
1547 }
1548 | KEYW_NETWORKS filter {
1549    $$ = $2;
1550 }
1551 ;
1552 
1553 default_attribute: ATTR_DEFAULT KEYW_TO peering 
1554                                 opt_action 
1555                                 opt_default_filter TKN_EOA {
1556    $$ = changeCurrentAttr(new AttrDefault($3, $4, $5));
1557 }
1558 | ATTR_DEFAULT KEYW_TO peering error TKN_EOA {
1559    if ($3)
1560       delete $3;
1561    handle_error("Error: badly formed filter/action or keyword NETWORKS/ACTION missing.\n");
1562    yyerrok;
1563 }
1564 | ATTR_DEFAULT error TKN_EOA {
1565    handle_error("Error: TO <peer> missing.\n");
1566    yyerrok;
1567 }
1568 ;
1569 
1570 filter_attribute: ATTR_FILTER filter TKN_EOA {
1571    $$ = changeCurrentAttr(new AttrFilter($2));
1572 }
1573 | ATTR_FILTER error TKN_EOA {
1574    $$ = $1;
1575    handle_error("Error: badly formed filter.\n");
1576    yyerrok;
1577 }
1578 ;
1579 
1580 peering_attribute: ATTR_PEERING peering TKN_EOA {
1581    $$ = changeCurrentAttr(new AttrPeering($2));
1582 }
1583 | ATTR_PEERING error TKN_EOA {
1584    $$ = $1;
1585    handle_error("Error: badly formed filter.\n");
1586    yyerrok;
1587 }
1588 ;
1589 
1590 //**** inet-rtr class *****************************************************
1591 
1592 ifaddr_attribute: ATTR_IFADDR TKN_IPV4 KEYW_MASKLEN TKN_INT opt_action TKN_EOA {
1593    $$ = changeCurrentAttr(new AttrIfAddr($2->get_ipaddr(), $4, $5));
1594    delete $2;
1595 }
1596 | ATTR_IFADDR TKN_IPV4 KEYW_MASKLEN TKN_INT error TKN_EOA {
1597    delete $2;
1598    $$ = $1;
1599    handle_error("Error: in action specification.\n");
1600    yyerrok;
1601 }
1602 | ATTR_IFADDR TKN_IPV4 KEYW_MASKLEN error TKN_EOA {
1603    delete $2;
1604    $$ = $1;
1605    handle_error("Error: integer mask length expected.\n");
1606    yyerrok;
1607 }
1608 | ATTR_IFADDR TKN_IPV4 error TKN_EOA {
1609    delete $2;
1610    $$ = $1;
1611    handle_error("Error: MASKLEN <length> expected.\n");
1612    yyerrok;
1613 }
1614 | ATTR_IFADDR error TKN_EOA {
1615    $$ = $1;
1616    handle_error("Error: <ip_address> MASKLEN <length> [<action>] expected.\n");
1617    yyerrok;
1618 }
1619 ;
1620 
1621 //// peer attribute /////////////////////////////////////////////////////
1622 
1623 opt_peer_options: {
1624    $$ = new List<AttrPeerOption>;
1625 }
1626 | peer_options {
1627    $$ = $1;
1628 }
1629 ;
1630 
1631 peer_options: peer_option {
1632    $$ = new List<AttrPeerOption>;
1633    $$->append($1);
1634 }
1635 | peer_options ',' peer_option {
1636    $$ = $1;
1637    $$->append($3);
1638 }
1639 ;
1640 
1641 peer_option: tkn_word '(' generic_list ')' {
1642    $$ = new AttrPeerOption($1, $3);
1643 }
1644 ;
1645 
1646 peer_id: TKN_IPV4
1647 | TKN_DNS  {
1648    $$ = new IPAddr;
1649 }
1650 | TKN_RTRSNAME  {
1651    $$ = new IPAddr;
1652 }
1653 | TKN_PRNGNAME {
1654    $$ = new IPAddr;
1655 }
1656 ;
1657 
1658 peer_attribute: ATTR_PEER tkn_word peer_id opt_peer_options TKN_EOA {
1659    const AttrProtocol *protocol = schema.searchProtocol($2);
1660    int position;
1661    const RPType *correctType;
1662    bool error = false;
1663 
1664    if (!protocol) {
1665       handle_error("Error: unknown protocol %s.\n", $2);
1666       error = true;
1667    } else {
1668       ((AttrProtocol *) protocol)->startMandatoryCheck();
1669       for (AttrPeerOption *opt = $4->head(); opt; opt = $4->next(opt)) {
1670          const AttrProtocolOption *decl = protocol->searchOption(opt->option);
1671          if (!decl)  {
1672             handle_error("Error: protocol %s does not have option %s.\n", 
1673                          $2, opt->option);
1674             error = true;
1675          } else {
1676             for (; decl; decl = protocol->searchNextOption(decl))
1677                if (decl->option->validateArgs(opt->args, position, correctType))
1678                   break;
1679             if (! decl) {
1680                handleArgumentTypeError($2, opt->option, position, correctType);
1681                error = true;
1682             }
1683          }
1684       }
1685    }
1686 
1687    if (! error) {
1688       const AttrProtocolOption *missing = 
1689          ((AttrProtocol *) protocol)->missingMandatoryOption();
1690       if (missing) {
1691          handle_error("Error: mandatory option %s of protocol %s is missing.\n", 
1692                       missing->option->name, $2);
1693          error = true;
1694       }
1695    }
1696       
1697    if (!error)
1698       $$ = changeCurrentAttr(new AttrPeer(protocol, $3, $4));
1699    else {
1700       free($2);
1701       delete $3;
1702       delete $4;
1703    }
1704 }
1705 | ATTR_PEER tkn_word TKN_IPV4 error TKN_EOA {
1706    $$ = $1;
1707    free($2);
1708    delete $3;
1709    handle_error("Error: in peer option.\n");
1710    yyerrok;
1711 }
1712 | ATTR_PEER tkn_word error TKN_EOA {
1713    $$ = $1;
1714    free($2);
1715    handle_error("Error: missing peer ip_address.\n");
1716    yyerrok;
1717 }
1718 | ATTR_PEER error TKN_EOA {
1719    $$ = $1;
1720    handle_error("Error: missing protocol name.\n");
1721    yyerrok;
1722 }
1723 ;
1724 
1725 //**** route class ********************************************************
1726 
1727 aggr_bndry_attribute: ATTR_AGGR_BNDRY as_expr TKN_EOA {
1728    $$ = $1;
1729    delete $2;
1730 }
1731 | ATTR_AGGR_BNDRY error TKN_EOA {
1732    $$ = $1;
1733    handle_error("Error: <as-expression> expected.\n");
1734    yyerrok;
1735 }
1736 ;
1737 
1738 aggr_mtd_attribute: ATTR_AGGR_MTD KEYW_INBOUND TKN_EOA {
1739    $$ = $1;
1740 }
1741 | ATTR_AGGR_MTD KEYW_OUTBOUND opt_as_expr TKN_EOA {
1742    delete $3;
1743 }
1744 | ATTR_AGGR_MTD KEYW_OUTBOUND error TKN_EOA {
1745    $$ = $1;
1746    handle_error("Error: OUTBOUND <as-expression> expected.\n");
1747    yyerrok;
1748 }
1749 | ATTR_AGGR_MTD KEYW_INBOUND error TKN_EOA {
1750    $$ = $1;
1751    handle_error("Error: INBOUND can not be followed by anything.\n");
1752    yyerrok;
1753 }
1754 | ATTR_AGGR_MTD error TKN_EOA {
1755    $$ = $1;
1756    handle_error("Error: keyword INBOUND or OUTBOUND expected.\n");
1757    yyerrok;
1758 }
1759 ;
1760 
1761 //// inject attribute ///////////////////////////////////////////////////
1762 
1763 opt_inject_expr: {
1764    $$ = new FilterANY;
1765 }
1766 | KEYW_UPON inject_expr {
1767    $$ = $2;
1768 }
1769 ;
1770 
1771 inject_expr: inject_expr OP_OR inject_expr_term {
1772    $$ = new FilterOR($1, $3);
1773 }
1774 | inject_expr_term
1775 ;
1776 
1777 inject_expr_term: inject_expr_term OP_AND inject_expr_factor {
1778    $$ = new FilterAND($1, $3);
1779 }
1780 | inject_expr_factor
1781 ;
1782 
1783 inject_expr_factor: '(' inject_expr ')' {
1784    $$ = $2;
1785 }
1786 | inject_expr_operand 
1787 ;
1788 
1789 inject_expr_operand: KEYW_STATIC {
1790    $$ = new FilterANY;
1791 }
1792 | KEYW_HAVE_COMPONENTS '{' opt_filter_prefix_list '}' { 
1793    $$ = new FilterHAVE_COMPONENTS((FilterPRFXList *) $3); 
1794 } 
1795 | KEYW_EXCLUDE '{' opt_filter_prefix_list '}' { 
1796    $$ = new FilterEXCLUDE((FilterPRFXList *) $3); 
1797 } 
1798 ;
1799 
1800 inject_attribute: ATTR_INJECT opt_router_expr_with_at opt_action opt_inject_expr TKN_EOA {
1801    $$ = $1;
1802    delete $2;
1803    delete $3;
1804    delete $4;
1805 }
1806 | ATTR_INJECT error TKN_EOA {
1807    $$ = $1;
1808    handle_error("Error: [at <router-exp>] [action <action>] [upon <condition>] expected.\n");
1809    yyerrok;
1810 }
1811 ;
1812 
1813 //// components attribute ///////////////////////////////////////////////
1814 
1815 opt_atomic:
1816 | KEYW_ATOMIC
1817 ;
1818 
1819 components_list: {
1820 }
1821 | filter {
1822    delete $1;
1823 }
1824 | components_list KEYW_PROTOCOL tkn_word filter {
1825    free($3);
1826    delete $4;
1827 }
1828 ;
1829 
1830 components_attribute: ATTR_COMPONENTS opt_atomic components_list TKN_EOA {
1831    $$ = $1;
1832 }
1833 | ATTR_COMPONENTS error TKN_EOA {
1834    $$ = $1;
1835    handle_error("Error: [ATOMIC] [[<filter>] [PROTOCOL <protocol> <filter>] ...] expected.\n");
1836    yyerrok;
1837 }
1838 ;
1839 
1840 //**** route-set **********************************************************
1841 
1842 opt_rs_members_list: /* empty list */ {
1843    $$ = new ItemList;
1844 }
1845 | rs_members_list
1846 ;
1847 
1848 rs_members_list: rs_member {    
1849    $$ = new ItemList;
1850    $$->append($1);
1851 }
1852 | rs_members_list ',' rs_member {
1853    $$ = $1;
1854    $$->append($3);
1855 }
1856 ;
1857 
1858 rs_member: TKN_ASNO {
1859    $$ = new ItemASNO($1);
1860 }
1861 | TKN_ASNO OP_MS {
1862    $$ = new ItemMSItem(new ItemASNO($1), $2->code, $2->n, $2->m);
1863    delete $2;
1864 }
1865 | TKN_ASNAME {
1866    $$ = new ItemASNAME($1);
1867 }
1868 | TKN_ASNAME OP_MS {
1869    $$ = new ItemMSItem(new ItemASNAME($1), $2->code, $2->n, $2->m);
1870    delete $2;
1871 }
1872 | TKN_RSNAME {
1873    $$ = new ItemRSNAME($1);
1874 }
1875 | TKN_RSNAME OP_MS {
1876    $$ = new ItemMSItem(new ItemRSNAME($1), $2->code, $2->n, $2->m);
1877    delete $2;
1878 }
1879 | TKN_PRFXV4 {
1880    $$ = new ItemPRFXV4($1);
1881 }
1882 | TKN_PRFXV4RNG {
1883    $$ = new ItemPRFXV4Range($1);
1884 }
1885 ;
1886 
1887 rs_members_attribute: ATTR_RS_MEMBERS opt_rs_members_list TKN_EOA {
1888    $$ = changeCurrentAttr(new AttrGeneric($1->type, $2));
1889 }
1890 | ATTR_RS_MEMBERS error TKN_EOA {
1891    $$ = $1;
1892    handle_error("Error: invalid member\n");
1893    yyerrok;
1894 }
1895 ;
1896 
1897 //**** dictionary *********************************************************
1898 
1899 rpattr_attribute: ATTR_RP_ATTR TKN_WORD methods TKN_EOA {
1900    $$ = changeCurrentAttr(new AttrRPAttr($2, $3));
1901 }
1902 | ATTR_RP_ATTR TKN_RP_ATTR methods TKN_EOA {
1903    $$ = changeCurrentAttr(new AttrRPAttr($2->name, $3));
1904 }
1905 | ATTR_RP_ATTR error TKN_EOA {
1906    $$ = $1;
1907    handle_error("Error: invalid rp-attribute specification\n");
1908    yyerrok;
1909 }
1910 ;
1911 
1912 methods: method {
1913    $$ = new List<AttrMethod>;
1914    if ($1)
1915       $$->append($1);
1916 }
1917 | methods method {
1918    $$ = $1;
1919    if ($2)
1920       $$->append($2);
1921 }
1922 ;
1923 
1924 method: TKN_WORD '(' ')' {
1925    $$ = new AttrMethod($1, new List<RPTypeNode>, false);
1926 }
1927 | TKN_WORD '(' typedef_type_list ')' {
1928    $$ = new AttrMethod($1, $3, false);
1929 }
1930 | TKN_WORD '(' typedef_type_list ',' TKN_3DOTS ')' {
1931    $$ = new AttrMethod($1, $3, true);
1932 }
1933 | KEYW_OPERATOR TKN_OPERATOR '(' typedef_type_list ')' {
1934    char buffer[16];
1935    strcpy(buffer, "operator");
1936    strcat(buffer, $2);
1937    $$ = new AttrMethod(strdup(buffer), $4, false, true);
1938    free($2);
1939 }
1940 | KEYW_OPERATOR TKN_OPERATOR '(' typedef_type_list ',' TKN_3DOTS ')' {
1941    char buffer[16];
1942    strcpy(buffer, "operator");
1943    strcat(buffer, $2);
1944    $$ = new AttrMethod(strdup(buffer), $4, true, true);
1945    free($2);
1946 }
1947 | TKN_WORD error ')' {
1948    free($1);
1949    $$ = NULL;
1950    handle_error("Error: invalid method specification for %s\n", $1);
1951 }
1952 | KEYW_OPERATOR TKN_OPERATOR error ')' {
1953    $$ = NULL;
1954    handle_error("Error: invalid operator specification for %s\n", $2);
1955    free($2);
1956 }
1957 | KEYW_OPERATOR error ')' {
1958    $$ = NULL;
1959    handle_error("Error: invalid operator\n");
1960 }
1961 | error ')' {
1962    $$ = NULL;
1963    handle_error("Error: method specification expected\n");
1964 }
1965 ;
1966 
1967 //// typedef attribute  /////////////////////////////////////////////////
1968 
1969 typedef_attribute: ATTR_TYPEDEF TKN_WORD typedef_type TKN_EOA {
1970    $$ = changeCurrentAttr(new AttrTypedef($2, $3));
1971 }
1972 | ATTR_TYPEDEF error TKN_EOA {
1973    $$ = $1;
1974    handle_error("Error: invalid typedef specification\n");
1975    yyerrok;
1976 }
1977 ;
1978 
1979 typedef_type_list: typedef_type {
1980    $$ = new List<RPTypeNode>;
1981    if ($1)
1982       $$->append(new RPTypeNode($1));
1983 }
1984 | typedef_type_list ',' typedef_type {
1985    $$ = $1;
1986    if ($3)
1987       $$->append(new RPTypeNode($3));
1988 }
1989 ;
1990 
1991 typedef_type: KEYW_UNION typedef_type_list {
1992    $$ = RPType::newRPType("union", $2);
1993    if (!$$) {
1994       handle_error("Error: empty union specification\n");
1995       delete $2;
1996    }
1997 }
1998 | KEYW_RANGE KEYW_OF typedef_type {
1999    if ($3)
2000       $$ = new RPTypeRange($3);
2001    else {
2002       $$ = NULL;
2003    }
2004 }
2005 | TKN_WORD {
2006    $$ = RPType::newRPType($1);
2007    if (!$$) {
2008       handle_error("Error: invalid type %s\n", $1);
2009    }
2010    free($1);
2011 }
2012 | TKN_WORD '[' TKN_INT ',' TKN_INT ']' {
2013    $$ = RPType::newRPType($1, $3, $5);
2014    if (!$$) {
2015       handle_error("Error: invalid type %s[%d,%d]\n", $1, $3, $5);
2016    }
2017    free($1);
2018 }
2019 | TKN_WORD '[' TKN_REAL ',' TKN_REAL ']' {
2020    $$ = RPType::newRPType($1, $3, $5);
2021    if (!$$) {
2022       handle_error("Error: invalid type %s[%f,%f]\n", $1, $3, $5);
2023    }
2024    free($1);
2025 }
2026 | TKN_WORD '[' enum_list ']' {
2027    $$ = RPType::newRPType($1, $3);
2028    if (!$$) {
2029       handle_error("Error: invalid type %s, enum expected\n", $1);
2030       delete $3;
2031    }
2032    free($1);
2033 }
2034 | KEYW_LIST '[' TKN_INT ':' TKN_INT ']' KEYW_OF typedef_type {
2035    if ($8)
2036       if ($3 < $5)
2037          $$ = new RPTypeList($8, $3, $5);
2038       else
2039          $$ = new RPTypeList($8, $5, $3);
2040    else {
2041       $$ = NULL;
2042       delete $8;
2043    }
2044 }
2045 | KEYW_LIST KEYW_OF typedef_type {
2046    if ($3)
2047       $$ = new RPTypeList($3);
2048    else {
2049       $$ = NULL;
2050    }
2051 }
2052 | KEYW_LIST error KEYW_OF typedef_type {
2053    $$ = NULL;
2054    delete $4;
2055    handle_error("Error: invalid list size\n");
2056 }
2057 ;
2058 
2059 enum_list: tkn_word {
2060    $$ = new List<WordNode>;
2061    $$->append(new WordNode($1));
2062 }
2063 | enum_list ',' tkn_word {
2064    $$ = $1;
2065    $$->append(new WordNode($3));
2066 }
2067 ;
2068 
2069 //// protocol attribute /////////////////////////////////////////////////
2070 
2071 protocol_attribute: ATTR_PROTOCOL tkn_word protocol_options TKN_EOA {
2072    $$ = changeCurrentAttr(new AttrProtocol($2, $3));
2073 }
2074 | ATTR_PROTOCOL tkn_word error TKN_EOA {
2075    $$ = $1;
2076    handle_error("Error: invalid protocol option\n");
2077    yyerrok;
2078 }
2079 | ATTR_PROTOCOL error TKN_EOA {
2080    $$ = $1;
2081    handle_error("Error: invalid protocol name\n");
2082    yyerrok;
2083 }
2084 ;
2085 
2086 protocol_options: {
2087    $$ = new List<AttrProtocolOption>;
2088 }
2089 | protocol_options protocol_option {
2090    $$ = $1;
2091    $$->append($2);
2092 }
2093 ;
2094 
2095 protocol_option: KEYW_MANDATORY method {
2096    $$ = new AttrProtocolOption(false, $2);
2097 }
2098 | KEYW_OPTIONAL method  {
2099    $$ = new AttrProtocolOption(true, $2);
2100 }
2101 ;
2102 
2103 //**** schema class *******************************************************
2104 
2105 opt_attr_options: {
2106    $$ = new AttrAttr(ATTR_GENERIC, RPType::newRPType("free_text"));
2107 }
2108 | attr_options {
2109    $$ = new AttrAttr(ATTR_GENERIC, RPType::newRPType("free_text"));
2110    *$$ |= *$1;
2111    delete $1;
2112 }
2113 ;
2114 
2115 attr_options: attr_option {
2116    $$ = $1;
2117 }
2118 | attr_options ',' attr_option {
2119    $$ = $1;
2120    *$$ |= *$3;
2121    delete $3;
2122 }
2123 | error ',' attr_option {
2124    $$ = $3;
2125    handle_error("Error: in attr option specification.\n");
2126 }
2127 ;
2128 
2129 attr_option: KEYW_SYNTAX '(' typedef_type ')' {
2130    $$ = new AttrAttr(ATTR_GENERIC, $3);
2131 }
2132 | KEYW_SYNTAX '(' KEYW_SPECIAL ',' tkn_word ')' {
2133    int syntax = schema.searchAttrSyntax($5);
2134    if (syntax < 0) {
2135       handle_error("Error: no known syntax rule for %s.\n", $5);
2136       $$ = new AttrAttr;
2137    } else
2138       $$ = new AttrAttr(syntax, NULL);
2139    free($5);
2140 }
2141 | KEYW_OPTIONAL {
2142    $$ = new AttrAttr(AttrAttr::OPTIONAL);
2143 }
2144 | KEYW_MANDATORY {
2145    $$ = new AttrAttr;
2146 }
2147 | KEYW_DELETED {
2148    $$ = new AttrAttr(AttrAttr::DELETED)
2149 }
2150 | KEYW_SINGLEVALUED {
2151    $$ = new AttrAttr;
2152 }
2153 | KEYW_MULTIVALUED {
2154    $$ = new AttrAttr(AttrAttr::MULTIVALUED);
2155 }
2156 | KEYW_LOOKUP {
2157    $$ = new AttrAttr(AttrAttr::LOOKUP);
2158 }
2159 | KEYW_KEY {
2160    $$ = new AttrAttr(AttrAttr::KEY);
2161 }
2162 | KEYW_OBSOLETE {
2163    $$ = new AttrAttr(AttrAttr::OBSOLETE);
2164 }
2165 | KEYW_INTERNAL {
2166    $$ = new AttrAttr(AttrAttr::INTERNAL);
2167 }
2168 | KEYW_GENERATED {
2169   $$ = new AttrAttr(AttrAttr::GENERATED);
2170 }
2171 ;
2172 
2173 attr_attribute: ATTR_ATTR tkn_word opt_attr_options TKN_EOA {
2174    $3->setName($2);
2175    $$ = changeCurrentAttr($3);
2176 }
2177 | ATTR_ATTR tkn_word error TKN_EOA {
2178    $$ = $1;
2179    free($2);
2180    handle_error("Error: in attr option specification.\n");
2181    yyerrok;
2182 }
2183 | ATTR_ATTR error TKN_EOA {
2184    $$ = $1;
2185    handle_error("Error: attr name expected.\n");
2186    yyerrok;
2187 }
2188 ;
2189 
2190 //**** rps-auth stuff *****************************************************
2191 
2192 mnt_routes_attribute: ATTR_MNT_ROUTES mnt_routes_list TKN_EOA {
2193    $$ = changeCurrentAttr(new AttrMntRoutes($2));
2194 }
2195 ;
2196 
2197 mnt_routes_list: mnt_routes_list_item {
2198    $$ = new List<AttrMntRoutes::MntPrfxPair>;
2199    $$->append($1);
2200 }
2201 | mnt_routes_list ',' mnt_routes_list_item {
2202    $$ = $1;
2203    $$->append($3);
2204 }
2205 ;
2206 
2207 mnt_routes_list_item: tkn_word {
2208    $$ = new AttrMntRoutes::MntPrfxPair($1, NULL);
2209 }
2210 | tkn_word KEYW_ANY  {
2211    $$ = new AttrMntRoutes::MntPrfxPair($1, NULL);
2212 }
2213 | tkn_word '{' opt_filter_prefix_list '}'  {
2214    $$ = new AttrMntRoutes::MntPrfxPair($1, (FilterPRFXList *) $3);
2215 }
2216 ;
2217 
2218 %%
2219 
2220 void enable_yy_parser_debugging() {
     /* [<][>][^][v][top][bottom][index][help] */
2221 #if YYDEBUG != 0
2222    yydebug = 1;
2223 #endif
2224 }
2225 
2226 void handleArgumentTypeError(char *attr, char *method, int position,
     /* [<][>][^][v][top][bottom][index][help] */
2227                              const RPType *correctType, 
2228                              bool isOperator = false) {
2229    if (isOperator)
2230       if (position)
2231          handle_error("Error: argument %d to %s.operator%s should be %s.\n",
2232                    position, attr, method, ((RPType *) correctType)->name());
2233       else
2234          handle_error("Error: wrong number of arguments to %s.operator%s.\n",
2235                       attr, method);
2236    else
2237       if (position)
2238          handle_error("Error: argument %d to %s.%s should be %s.\n",
2239                    position, attr, method, ((RPType *) correctType)->name());
2240       else
2241          handle_error("Error: wrong number of arguments to %s.%s.\n",
2242                       attr, method);
2243 }
2244 
2245 const AttrMethod *searchMethod(const AttrRPAttr *rp_attr, char *method, ItemList *args) {
     /* [<][>][^][v][top][bottom][index][help] */
2246    const AttrMethod *mtd = rp_attr->searchMethod(method);
2247    int position;
2248    const RPType *correctType;
2249    
2250    if (!mtd) {
2251       handle_error("Error: rp-attribute %s does not have %s defined.\n",
2252                    rp_attr->name, method);
2253       return NULL;
2254    }
2255    
2256    for (; mtd; mtd = rp_attr->searchNextMethod(mtd))
2257       if (mtd->validateArgs(args, position, correctType))
2258          return mtd;
2259 
2260    handleArgumentTypeError(rp_attr->name, method, position, correctType);
2261    
2262    return NULL;
2263 }

/* [<][>][^][v][top][bottom][index][help] */