使用带有antlr4的jsp scriptlet解析脚本标记

时间:2017-06-19 05:38:34

标签: java antlr4 jsp-tags

我在解析< script>时遇到了困难使用antlr4标记其中的scriptlet表达式。我从现有的HTMLParser和Lexer语法开始,并尝试根据自己的需要进行修改。 Parser语法是:

parser grammar HTMLParser;

options { tokenVocab=HTMLLexer; }

htmlDocument
    : script*
    ;

script
    : SCRIPT_OPEN scriptAttribute* SCRIPT_TAG_CLOSE? WORD? SCRIPT_TAG_FULL_CLOSE
    | SCRIPT_OPEN scriptAttribute* SCRIPT_TAG_SLASH_CLOSE
    ;

scriptAttribute
    : scriptAttributeName SCRIPT_EQUALS QUOTE SCRIPLET_INSIDE_SCRIPT javaExpression SCRIPTLET_TAG_CLOSE scriptAttributeValue? QUOTE
    | scriptAttributeName SCRIPT_EQUALS QUOTE scriptAttributeValue QUOTE
    | scriptAttributeName
    ;

scriptAttributeName
    : WORD
    ;   

scriptAttributeValue
    : SCRIPT_ATTRIBUTE
    ;


scriptlet    
    : SCRIPTLET_TAG_OPEN javaExpression SCRIPTLET_TAG_CLOSE
    ;

jspElementName
    : TAG_NAME
    ;

jspElementAttribute
    : jspAttributeName TAG_EQUALS jspAttributeValue
    ;

jspAttributeName
    : TAG_NAME
    ;

jspAttributeValue
    : ATTVALUE_VALUE
    ;

javaExpression
    : VALID_JAVA_CHARS | SEA_WS*    
    ;

词法分析器语法:

lexer grammar  HTMLLexer;

SCRIPT_OPEN
    : '<script' ->pushMode(SCRIPT)
    ;


SCRIPTLET_TAG_OPEN
    : ('<%!' | '<%=' | '<%') ->pushMode(SCRIPTVALUE)
    ;


SEA_WS
    :  (' '|'\t'|'\r'? '\n')+
    ;


TAG_NAME
    : TAG_NameStartChar TAG_NameChar*
//  | TAG_NameStartChar* ':' TAG_NameStartChar*
    ;

TAG_WHITESPACE
    : [ \t\r\n] -> channel(HIDDEN)
    ;

fragment
HEXDIGIT
    : [a-fA-F0-9]
    ;

fragment
DIGIT
    : [0-9]
    ;


TAG_NameChar
    : TAG_NameStartChar
//  | ':'
    | '-'
    | '_'
    | '.'
    | DIGIT
    |   '\u00B7'
    |   '\u0300'..'\u036F'
    |   '\u203F'..'\u2040'
    ;


TAG_NameStartChar
    :   [a-zA-Z]
    |   '\u2070'..'\u218F'
    |   '\u2C00'..'\u2FEF'
    |   '\u3001'..'\uD7FF'
    |   '\uF900'..'\uFDCF'
    |   '\uFDF0'..'\uFFFD'
    ;

TAG_EQUALS
    : '=' -> pushMode(ATTVALUE)
    ;

//
// attribute values
//
mode ATTVALUE;

// an attribute value may have spaces b/t the '=' and the value
ATTVALUE_VALUE
    : [ ]* ATTRIBUTE -> popMode
    ;

ATTRIBUTE
    : DOUBLE_QUOTE_STRING
    | SINGLE_QUOTE_STRING
    | ATTCHARS
    | HEXCHARS
    | DECCHARS
    ;

fragment ATTCHAR
    : '-'
    | '_'
    | '.'
    | '/'
    | '+'
    | ','
    | '?'
    | '='
    | ':'
    | ';'
    | '#'
    | [0-9a-zA-Z]
    ;

fragment ATTCHARS
    : ATTCHAR+ ' '?
    ;

fragment HEXCHARS
    : '#' [0-9a-fA-F]+
    ;

fragment DECCHARS
    : [0-9]+ '%'?
    ;

fragment DOUBLE_QUOTE_STRING
    : '"' ~[<"]* '"'
    ;
fragment SINGLE_QUOTE_STRING
    : '\'' ~[<']* '\''
    ;   

//
// <scripts>
//
mode SCRIPT;

SCRIPT_TAG_FULL_CLOSE
    : '</script>' ->popMode
    ;


SCRIPT_TAG_CLOSE
    : '>'
    ;

SCRIPT_TAG_SLASH_CLOSE
    : '/>' -> popMode
    ;

SCRIPT_EQUALS
    : '='
    ;

SCRIPLET_INSIDE_SCRIPT
    : '<%' ->pushMode(SCRIPTVALUE)
    ;

SCRIPT_ATTRIBUTE
    : SCRIPT_ATTCHARS    
    ;

fragment SCRIPT_ATTCHARS
    : SCRIPT_ATTCHAR+
    ;

SCRIPTTAG_WS
    : [ \r\n\t]+ -> channel(HIDDEN)
    ;

WORD
    : [a-zA-Z]+
    ;

QUOTE
    : '"'
    ;

fragment SCRIPT_ATTCHAR
    : '-'
    | '_'
    | '.'
    | '/'
    | ','
    | ';'
    | '\''
//  | '"'
    | [0-9a-zA-Z]
    ;       


mode SCRIPTVALUE;

SCRIPTLET_TAG_CLOSE
    : '%>' ->popMode
    ;

VALID_JAVA_CHARS
    : SCRIPTCHARS+
    ;

SCRIPT_WS
    : [\r\n\t]+ -> channel(HIDDEN)
    ;

fragment SCRIPTCHARS
    : SCRIPTCHAR+ ' '?
    ;   

fragment SCRIPTCHAR
    : '-'
    | '_'
    | '.'
    | '/'
    | '+'
    | ','
    | '?'
    | '='
    | ':'
    | ';'
    | '#'
    | '('
    | ')'
    | '}'
    | '{'
    | '@'
    | '*'
    | '!'
    | '%'[0-9]+
    | '&'
    | '['
    | ']'
    | '~'
    | '+'
    | '^'
    | '\r'
    | '\t'
    | '\n'
    | ' '
    | '"'
    | '\''
    | [0-9a-zA-Z]
    ;   

请注意:目前,我只是在一个非现实简单的两行文件上使用以下文本测试解析器:

<script type="text/javascript" src="<%= request.getContextPath() %>"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/scripts/Main.js"></script>

输出结果为:

line 1:8 no viable alternative at input '<script type'
^<script^ start start index: 0 start stop index: 6
^<script^ start start index: 0 start stop index: 6
^
^ stop start index:  78 stop stop index: 79
^<script^ start start index: 80 start stop index: 86
^

请注意,停止令牌开始索引是从上一行的换行符开始的。我的最终目标是创建一个jsp语法,我可以在其中识别每个脚本,链接,样式,jsp标记库标记,并用其他东西替换它们。其余的语法都已到位,但我在解析脚本标记时遇到了困难。

0 个答案:

没有答案