/*
 * <license>
 * Copyright (c) 2003-2004, Sun Microsystems, Inc.
 * 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 Sun Microsystems, Inc. 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, 
 * ROCUREMENT 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.
 * </license>
 */

PARSER_BEGIN(TagFile)

package com.sun.tlddoc.tagfileparser;

import java.io.InputStream;
import java.util.ArrayList;

/**
 * Simple parser for tag files that only actually parses the directives.
 * All other content is left unparsed.
 *
 * @author Mark Roth
 */
public class TagFile {

    /** The set of directives in this tag file */
    public ArrayList directives = new ArrayList();

    public static TagFile parse( InputStream in ) throws ParseException {
        TagFile parser = new TagFile( in );
        parser.Input();
        return parser;
    }

    public static void main(String args[]) throws ParseException {
        TagFile parser = new TagFile(System.in);
        parser.Input();
        ((SimpleNode)parser.jjtree.rootNode()).dump(">");
    }

    /**
     * Returns the list of directives in this tag file.
     */
    public ArrayList getDirectives() {  
        return this.directives;
    }

}

PARSER_END(TagFile)

TOKEN :
{
    < JSP_COMMENT   : "<%--"            > : WithinComment
  | < JSP_DIRECTIVE : "<%@"             > : JSPDirectiveName
  | < XML_DIRECTIVE : "<jsp:directive." > : XMLDirectiveName
  | < OTHER_CONTENT : ~[]               > : WithinOtherContent
}

// Support for JSP comments <%-- * --%>
<WithinComment> SKIP :
{
    "--%>" : DEFAULT
}

<WithinComment> MORE :
{
    <~[]>
}


// Support for <%@ * %>
<JSPDirectiveName> SKIP :
{
    < [" ","\t","\r","\n"] >
}

<JSPDirectiveName> TOKEN :
{
    < JSP_DIRECTIVE_NAME  : (["A"-"Z","a"-"z","0"-"9","_",":","-"])+ > : 
						JSPDirectiveAttributeName
}

<JSPDirectiveAttributeName> SKIP :
{
    < [" ","\t","\r","\n"] >
}

<JSPDirectiveAttributeName> TOKEN :
{
    < EQ                  : "="  > 
  | < BEGIN_QUOTE_SINGLE  : ("'") >  : JSPDirectiveAttributeValueSingle
  | < BEGIN_QUOTE_DOUBLE  : ("\"") > : JSPDirectiveAttributeValueDouble
  | < END_DIRECTIVE       : "%>" >  : DEFAULT
  | < JSP_ATTRIBUTE_NAME  : (["A"-"Z","a"-"z","0"-"9","_",":","-"])+ >
}

<JSPDirectiveAttributeValueSingle> SKIP :
{
    < [" ","\t","\r","\n"] >
}

<JSPDirectiveAttributeValueSingle> TOKEN :
{
    < END_QUOTE_SINGLE    : ("'") > : JSPDirectiveAttributeName
  | < JSP_ATTRIBUTE_VALUE1 : (   ~["'","\\"]
                               | ( "\\'" )
                               | ( "\\\"" )
                               | ( "\\\\" ) )+ >
}

<JSPDirectiveAttributeValueDouble> SKIP :
{
    < [" ","\t","\r","\n"] >
}

<JSPDirectiveAttributeValueDouble> TOKEN :
{
    < END_QUOTE_DOUBLE    : ("\"") > : JSPDirectiveAttributeName
  | < JSP_ATTRIBUTE_VALUE2 : (   ~["\"","\\"]
			       | ( "\\'" )
			       | ( "\\\"" )
			       | ( "\\\\" ) )+ >
}



// Support for <jsp:directive.*>
<XMLDirectiveName> SKIP :
{
    < [" ","\t","\r","\n"] >
}

<XMLDirectiveName> TOKEN :
{
    < XML_DIRECTIVE_NAME  : (["A"-"Z","a"-"z","0"-"9","_",":","-"])+ > : 
						XMLDirectiveAttributeName
}

<XMLDirectiveAttributeName> SKIP :
{
    < [" ","\t","\r","\n"] >
}

<XMLDirectiveAttributeName> TOKEN :
{
    < X_EQ                  : "="  > 
  | < X_BEGIN_QUOTE_SINGLE  : ("'") >  : XMLDirectiveAttributeValueSingle
  | < X_BEGIN_QUOTE_DOUBLE  : ("\"") > : XMLDirectiveAttributeValueDouble
  | < X_END_DIRECTIVE       : "/>" >  : DEFAULT
  | < XML_ATTRIBUTE_NAME  : (["A"-"Z","a"-"z","0"-"9","_",":","-"])+ >
}

<XMLDirectiveAttributeValueSingle> SKIP :
{
    < [" ","\t","\r","\n"] >
}

<XMLDirectiveAttributeValueSingle> TOKEN :
{
    < X_END_QUOTE_SINGLE   : ("'") > : XMLDirectiveAttributeName
  | < XML_ATTRIBUTE_VALUE1 : (   ~["'","\\"]
                               | ( "\\'" )
                               | ( "\\\"" )
                               | ( "\\\\" ) )+ >
}

<XMLDirectiveAttributeValueDouble> SKIP :
{
    < [" ","\t","\r","\n"] >
}

<XMLDirectiveAttributeValueDouble> TOKEN :
{
    < X_END_QUOTE_DOUBLE   : ("\"") > : XMLDirectiveAttributeName
  | < XML_ATTRIBUTE_VALUE2 : (   ~["\"","\\"]
			       | ( "\\'" )
			       | ( "\\\"" )
			       | ( "\\\\" ) )+ >
}


// Content that's not a directive or a comment.

<WithinOtherContent> SKIP :
{
    <"<"> { input_stream.backup(1); } : DEFAULT
  | <~[]>
}

<WithinOtherContent> MORE :
{
    <~[]>
}


void Input() :
{}
{
  JSPTagDef() <EOF>
}

void JSPTagDef() :
{}
{
  (
      Comment()
    | JSPDirective()
    | XMLDirective()
    | OtherContent()
  )*
}

void Comment() :
{}
{
  <JSP_COMMENT>
}

void JSPDirective() :
{
  Directive result = new Directive();
  String directiveName;
  String attributeName;
  String attributeValue;
}
{
  <JSP_DIRECTIVE> 
  directiveName = JSPDirectiveName() 
  {
    result.setDirectiveName( directiveName );
  }
  ( 
    attributeName = JSPAttributeName() 
    <EQ>
    (   ( <BEGIN_QUOTE_SINGLE> 
          (attributeValue = JSPAttributeValue()) 
          <END_QUOTE_SINGLE> 
        )
      | ( <BEGIN_QUOTE_DOUBLE> 
          (attributeValue = JSPAttributeValue())
          <END_QUOTE_DOUBLE> 
        )
    )
    {
      result.addAttribute( new Attribute( attributeName, attributeValue ) );
    }
  )*
  <END_DIRECTIVE>
  {
    directives.add( result );
  }
}

String JSPDirectiveName() :
{
  Token result;
}
{
  result = <JSP_DIRECTIVE_NAME>
  {
    return result.toString();
  }
}

String JSPAttributeName() :
{
  Token result;
}
{
  result = <JSP_ATTRIBUTE_NAME>
  {
    return result.toString();
  }
}

String JSPAttributeValue() :
{
  Token result;
}
{
  (
      (result = <JSP_ATTRIBUTE_VALUE1>) 
    | (result = <JSP_ATTRIBUTE_VALUE2>)
  )
  {
    return result.toString();
  }
}


void XMLDirective() :
{
  Directive result = new Directive();
  String directiveName;
  String attributeName;
  String attributeValue;
}
{
  <XML_DIRECTIVE> 
  directiveName = XMLDirectiveName() 
  {
    result.setDirectiveName( directiveName );
  }
  ( 
    attributeName = XMLAttributeName() 
    <X_EQ>
    (   ( <X_BEGIN_QUOTE_SINGLE> 
          attributeValue = XMLAttributeValue() 
          <X_END_QUOTE_SINGLE> 
        )
      | ( <X_BEGIN_QUOTE_DOUBLE> 
          attributeValue = XMLAttributeValue() 
          <X_END_QUOTE_DOUBLE> 
        )
    )
    {
      result.addAttribute( new Attribute( attributeName, attributeValue ) );
    }
  )*
  <X_END_DIRECTIVE>
  {
    directives.add( result );
  }
}

String XMLDirectiveName() :
{
  Token result;
}
{
  result = <XML_DIRECTIVE_NAME>
  {
    return result.toString();
  }
}

String XMLAttributeName() :
{
  Token result;
}
{
  result = <XML_ATTRIBUTE_NAME>
  {
    return result.toString();
  }
}

String XMLAttributeValue() :
{
  Token result;
}
{
  (
      (result = <XML_ATTRIBUTE_VALUE1>) 
    | (result = <XML_ATTRIBUTE_VALUE2>)
  )
  {
    return result.toString();
  }
}



void OtherContent() :
{}
{
  <OTHER_CONTENT>
}

