/*
 * @(#)file      Parser.jjt
 * @(#)author    Sun Microsystems, Inc.
 *
 * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

options {
  MULTI=true;
  STATIC=false;
  NODE_PREFIX= "JDM";
  NODE_PACKAGE="com.sun.jmx.snmp.IPAcl";
}


PARSER_BEGIN(Parser)

package com.sun.jmx.snmp.IPAcl;

import java.io.*;

public class Parser {
}

PARSER_END(Parser)


SKIP :
{
  " "
| "\t"
| "\n"
| "\r"
| <"--" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>
| <"#" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>

}



/* RESERVED WORDS AND LITERALS */

TOKEN : 
{
  <ACCESS: "access">
| <ACL: "acl">
| <ASSIGN: "=">
| <COMMUNITIES: "communities">
| <ENTERPRISE: "enterprise">
| <HOSTS: "hosts">
| <LBRACE: "{">
| <MANAGERS: "managers">
| <RANGE: "-">
| <RBRACE: "}">
| <RO: "read-only">
| <RW: "read-write">
| <TRAP: "trap">
| <INFORM: "inform">
| <TRAPCOMMUNITY: "trap-community">
| <INFORMCOMMUNITY: "inform-community">
| <TRAPNUM: "trap-num">
}



TOKEN : /* LITERALS */
{
  < INTEGER_LITERAL:
        <DECIMAL_LITERAL> (["l","L"])?
      | <HEX_LITERAL> (["l","L"])?
      | <OCTAL_LITERAL> (["l","L"])?
  >
|
  < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
|
  < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
|      
  < #OCTAL_LITERAL: "0" (["0"-"7"])* >
}

TOKEN : /* V6 LITERALS */
{ 
  < V6_ADDRESS: ((( ( (<H> ":")+ (":")?) | "::" ) (<H> ":")* (<H> | (<D> "." <D> "." <D> "." <D>))) | ("::")) | ( (<H> ":")+ ":") >
|
  <#H: (["0"-"9","a"-"f","A"-"F"])+ >
| 
  <#D: (["0"-"9"])+ >
}
 
TOKEN : /* IDENTIFIERS */
{
  < IDENTIFIER: ( (<DIGIT>|<LETTER>)+ (<SEPARATOR>|<LETTER>|<DIGIT>)* (<DIGIT>|<LETTER>)+ ) | (<DIGIT>|<LETTER>)+ >
|
  < #LETTER: ["a"-"z","A"-"Z"] >
|
  < #SEPARATOR: ["-", "_"] >
|
  < #DIGIT: ["0"-"9"] >
|
 <CSTRING: "\"" (~["\""])* "\"">
}

 

TOKEN: /* SEPARATOR */
{
  < COMMA: "," >
| < DOT: "." >
| < MARK: "!" >
| < MASK: "/">
}

// A file can contain several acl definitions
//
JDMSecurityDefs SecurityDefs()  : {}
{
  [AclBlock()]
  [TrapBlock()]
  [InformBlock()]
  <EOF>
  { return jjtThis;}
}

void AclBlock(): {}
{
"acl" "=" "{" (AclItem())+ "}"
}

void AclItem(): {}
{
"{" jjtThis.com= Communities() jjtThis.access= Access() Managers() "}"
}

JDMCommunities Communities(): {}
{
"communities" "=" Community() ( "," Community())*

{return jjtThis;}

}

void Community(): 
{
  Token t;
}
{
t=<IDENTIFIER> {jjtThis.communityString= t.image;}
}

JDMAccess Access(): {}
{
"access" "=" ( <RO> {jjtThis.access= RO;}
              |
               <RW> {jjtThis.access= RW;}
             )
{return jjtThis;}
}


void Managers() : { }
{
"managers" "=" Host() ( "," Host())*
}

void Host() : 
{
  Token t;
}
{
HostName()
|
LOOKAHEAD(<INTEGER_LITERAL> ( "." <INTEGER_LITERAL> )* "/" <INTEGER_LITERAL>)
NetMask()
|
LOOKAHEAD(<V6_ADDRESS> "/" <INTEGER_LITERAL>)
NetMaskV6()
|
LOOKAHEAD(<INTEGER_LITERAL> ".")
IpAddress()
|
IpV6Address()
|
IpMask()
}

void HostName():
{
  Token t;
}
{
  t=<IDENTIFIER> { jjtThis.name.append(t.image); }
(
"." t=<IDENTIFIER> 
  {jjtThis.name.append( "." + t.image); }
)*

}

void IpAddress():
{
Token t;
}
{

t= <INTEGER_LITERAL> 
  {jjtThis.address.append(t.image); }
(
"." t= <INTEGER_LITERAL> 
  {jjtThis.address.append( "." + t.image); }
)*

}

void IpV6Address():
{
Token t;
}
{

t= <V6_ADDRESS> 
  {jjtThis.address.append(t.image); }
}

void IpMask():
{
Token t;
}
{

t= <INTEGER_LITERAL> 
  {jjtThis.address.append(t.image); }
(
"!" t= <INTEGER_LITERAL> 
  {jjtThis.address.append( "." + t.image); }
)*
}

void NetMask():
{
Token t;
}
{

t= <INTEGER_LITERAL> 
  {jjtThis.address.append(t.image); }
(
"." t= <INTEGER_LITERAL> 
  {jjtThis.address.append( "." + t.image); }
)* "/" t= <INTEGER_LITERAL> {jjtThis.mask = t.image; }
}

void NetMaskV6():
{
Token t;
}
{

t= <V6_ADDRESS> 
  {jjtThis.address.append(t.image); }

"/" t= <INTEGER_LITERAL> {jjtThis.mask = t.image; }
}

void TrapBlock(): { }
{
"trap" "=" "{" (TrapItem())* "}"
}

void TrapItem(): { }
{
"{" jjtThis.comm= TrapCommunity() TrapInterestedHost() (Enterprise())* "}"
}

JDMTrapCommunity TrapCommunity(): 
{
  Token t;
}
{
"trap-community" "=" t=<IDENTIFIER> { jjtThis.community= t.image; return jjtThis; }
}

void TrapInterestedHost(): { }
{
"hosts" "=" HostTrap() ("," HostTrap())*
}

void HostTrap() : 
{
  Token t;
}
{
HostName()
|
IpAddress()
|
IpV6Address()
}

void Enterprise(): 
{
  Token t;
}
{
"{"
"enterprise" "="  t=<CSTRING> {jjtThis.enterprise= t.image;}

"trap-num" "=" TrapNum() ("," TrapNum())*

"}"
}

void TrapNum():
{
  Token t;
}
{
  t=<INTEGER_LITERAL> {jjtThis.low= Integer.parseInt(t.image);}
[
  "-" t=<INTEGER_LITERAL> {jjtThis.high= Integer.parseInt(t.image);}
]
}


void InformBlock(): { }
{
"inform" "=" "{" (InformItem())* "}"
}

void InformItem(): { }
{
"{" jjtThis.comm= InformCommunity() InformInterestedHost() "}"
}

JDMInformCommunity InformCommunity(): 
{
  Token t;
}
{
"inform-community" "=" t=<IDENTIFIER> { jjtThis.community= t.image; return jjtThis; }
}

void InformInterestedHost(): { }
{
"hosts" "=" HostInform() ("," HostInform())*
}

void HostInform() : 
{
  Token t;
}
{
HostName()
|
IpAddress()
|
IpV6Address()
}

