2017-06-06 107 views
0

我想解析jsp文件來識別指令標籤,jsp動作元素,scriptlet表達式等。爲此,我試圖擴展現有的html grammar。 我在正常的html標籤打開和jsp標籤打開方面存在問題。現有的語法有以下詞法規則:Antlr4解析jsp scriptlets表達式指令

TAG_OPEN 
    : '<' -> pushMode(TAG) 
    ; 
// 
// tag declarations 
// 
mode TAG; 

TAG_CLOSE 
    : '>' -> popMode 
    ; 

TAG_SLASH_CLOSE 
    : '/>' -> popMode 
    ; 

TAG_SLASH 
    : '/' 
    ; 

// 
// lexing mode for attribute values 
// 
TAG_EQUALS 
    : '=' -> pushMode(ATTVALUE) 
    ; 

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

TAG_WHITESPACE 
    : [ \t\r\n] -> skip 
    ; 

而且把對應的解析器規則爲:

htmlElement 
    : TAG_OPEN htmlTagName htmlAttribute* TAG_CLOSE htmlContent TAG_OPEN TAG_SLASH htmlTagName TAG_CLOSE 
    | TAG_OPEN htmlTagName htmlAttribute* TAG_SLASH_CLOSE 
    | TAG_OPEN htmlTagName htmlAttribute* TAG_CLOSE 
    | TAG_OPEN TAG_SLASH htmlTagName TAG_CLOSE 
// | jspDirective 
// | jspDeclaration 
    | scriptlet 
    | script 
    | style 
    ; 

我想用下面的延長上述規則:

scriptlet 
    : JSP_TAG_OPEN jspElement jspElementName jspElementAttribute* JSP_TAG_CLOSE 
    //|SCRIPTLET 
    ; 

jspElementName 
    : TAG_NAME 
    ; 

jspElementAttribute 
    : jspAttributeName TAG_EQUALS jspAttributeValue 
    ; 

jspAttributeName 
    : TAG_NAME 
    ; 

jspAttributeValue 
    : ATTVALUE_VALUE 
    ; 

jspElement 
    : jspDirective 
    | jspExpression 
    | jspDeclaration 
    | jspFragment 
    ; 

jspDirective  
    : JSP_DIRECTIVE_SIGN 
    ; 

jspExpression 
    : JSP_EXPRESSION_SIGN 
    ; 

jspDeclaration 
    : JSP_DECLARATION_SIGN 
    ; 

jspFragment 
    : JSP_FRAGMENT_SIGN 
    ; 

詞法分析規則爲:

JSP_TAG_OPEN 
    : '<%' ' '* 
    ; 

JSP_DIRECTIVE_SIGN 
    : '@' 
    ; 

JSP_EXPRESSION_SIGN 
    : '=' 
    ; 

JSP_DECLARATION_SIGN 
    : '!' 
    ; 

JSP_FRAGMENT_SIGN 
    : [ ]+ 
    ; 

JSP_TAG_CLOSE 
    : '%>' 
    ; 

但我想這個問題是,只要遇到<字符,TAG_OPEN的詞法分析規則開始運行,而不是等着看是否是jsp標記<%

所以,當我試圖解析一個小的HTML具有以下內容:

<html> 
<title>Statement Load page</title> 
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" 
    prefix="html"%> 

我收到此錯誤:

line 3:2 no viable alternative at input '@ taglib uri="http://jakarta.apache.org/struts/tags-html"\r\n\tprefix="html"%>\r\n' 

回答

0

好吧,我來爲JSP語法現在。如果這有助於其他人,我在這裏分享。另外,如果有人提出任何更新,指出問題或有助於使語法更好,我會很高興。

詞法語法:

lexer grammar HTMLLexer; 


HTML_COMMENT 
    : '<!--' .*? '-->' 
    ; 

HTML_CONDITIONAL_COMMENT 
    : '<![' .*? ']>' 
    ; 

JSP_COMMENT 
    : '<%--' .*? '--%>' 
    ; 

XML_DECLARATION 
    : '<?xml' .*? '>' 
    ; 

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

DIRECTIVE_TAG_OPEN 
    : '<%@' -> pushMode(TAG) 
    ; 

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

// 
// 
CDATA 
    : '<![CDATA[' .*? ']]>' 
    ; 

DTD 
    : '<!' .*? '>' 
    ; 

//SCRIPTLET 
// : '<?' .*? '?>' 
// | '<%' .*? '%>' 
// ; 

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


LINK_OPEN 
    : '<link' ->pushMode(LINK) 
    ; 

STYLE_OPEN 
    : '<style' ->pushMode(STYLE) 
    ; 

TAG_OPEN 
    : '<' ->pushMode(TAG) 
    ; 

HTML_TEXT 
    : ~'<'+ 
    ; 

// 
// tag declarations 
// 
mode TAG; 

JSP_TAG_CLOSE 
    : '%>' -> popMode 
    ; 

TAG_CLOSE 
    : '>' -> popMode 
    ; 

TAG_SLASH_CLOSE 
    : '/>' -> popMode 
    ; 

TAG_SLASH 
    : '/' 
    ; 

// 
// lexing mode for attribute values 
// 
TAG_EQUALS 
    : '=' -> pushMode(ATTVALUE) 
    ; 

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

TAG_COLON 
    : ':' 
    ; 

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' 
    ; 

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

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


SCRIPT_TAG_CLOSE 
    : '>' -> popMode 
    ; 

SCRIPT_TAG_SLASH_CLOSE 
    : '/>' -> popMode 
    ; 

SCRIPT_EQUALS 
    : ' '* '=' ' '* 
    ; 

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

SCRIPT_ATTRIBUTE 
    : SCRIPT_ATTCHARS  
    ; 

fragment SCRIPT_ATTCHARS 
    : SCRIPT_ATTCHAR+ ' '? 
    ; 

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

WORD 
    : [ a-zA-Z]+ 
    ; 

QUOTE 
    : '"' ' '* 
    ; 

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

// 
// <link> 
// 
mode LINK; 

LINK_BODY 
    : .*? '</link>' ->popMode 
    ; 

LINK_SHORT_BODY 
    : '/>' ->popMode 
    ; 

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

LINK_NONSLASH_BODY 
    : .*? '>' ->popMode 
    ; 


// 
// <styles> 
// 
mode STYLE; 

STYLE_BODY 
    : .*? '</style>' -> popMode 
    ; 

STYLE_SHORT_BODY 
    : .*? '</>' -> popMode 
    ; 

// 
// 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 
    : '\'' ~[<']* '\'' 
    ; 

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] 
    ; 

分析器語法:

parser grammar HTMLParser; 

options { tokenVocab=HTMLLexer; } 

htmlDocument 
    : (scriptlet | SEA_WS)* xml? (scriptlet | SEA_WS)* dtd? (scriptlet | SEA_WS)* htmlElements* 
    ; 

htmlElements 
    : htmlMisc* htmlElement htmlMisc* 
    ; 

htmlElement 
    : script 
    | link 
    | style 
    | scriptlet 
    | TAG_OPEN htmlTagName htmlAttribute* TAG_CLOSE htmlContent TAG_OPEN TAG_SLASH htmlTagName TAG_CLOSE 
    | TAG_OPEN htmlTagName htmlAttribute* TAG_SLASH_CLOSE 
    | TAG_OPEN htmlTagName htmlAttribute* TAG_CLOSE 
    | TAG_OPEN TAG_SLASH htmlTagName TAG_CLOSE 
    ; 

htmlContent 
    : htmlChardata? ((htmlElement | xhtmlCDATA | htmlComment) htmlChardata?)* 
    ; 

htmlAttribute 
    : htmlAttributeName TAG_EQUALS htmlAttributeValue 
    | htmlAttributeName 
    ; 

htmlAttributeName 
    : TAG_NAME 
    ; 

htmlAttributeValue 
    : ATTVALUE_VALUE 
    ; 

htmlTagName 
    : TAG_NAME 
    | tagKey TAG_COLON tagVal 
    ; 

tagKey 
    : TAG_NAME 
    ; 

tagVal 
    : TAG_NAME 
    ; 

htmlChardata 
    : HTML_TEXT 
    | SEA_WS 
    ; 

htmlMisc 
    : htmlComment 
    | jspComment 
    | SEA_WS 
    ; 

htmlComment 
    : HTML_COMMENT 
    | HTML_CONDITIONAL_COMMENT 
    ; 

jspComment 
    : JSP_COMMENT 
    ; 

xhtmlCDATA 
    : CDATA 
    ; 

dtd 
    : DTD 
    ; 

xml 
    : XML_DECLARATION 
    ; 

scriptlet 
    : DIRECTIVE_TAG_OPEN jspElementName jspElementAttribute* JSP_TAG_CLOSE 
    | 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*  
    ; 

script 
    : SCRIPT_OPEN scriptAttribute* SCRIPT_TAG_CLOSE htmlContent* SCRIPT_TAG_FULL_CLOSE 
    | SCRIPT_OPEN scriptAttribute* SCRIPT_TAG_SLASH_CLOSE 
    ; 

scriptAttribute 
    : scriptAttributeName SCRIPT_EQUALS QUOTE scriptlet scriptAttributeValue* QUOTE 
    | scriptAttributeName SCRIPT_EQUALS scriptAttributeValue 
    | scriptAttributeName 
    ; 

scriptAttributeName 
    : WORD 
    ; 

scriptAttributeValue 
    : SCRIPT_ATTRIBUTE 
    ; 

link 
    : LINK_OPEN (LINK_BODY | LINK_SHORT_BODY | LINK_NONSLASH_BODY) 
    | LINK_OPEN scriptlet* (LINK_BODY | LINK_SHORT_BODY | LINK_NONSLASH_BODY) 
    ; 

style 
    : STYLE_OPEN (STYLE_BODY | STYLE_SHORT_BODY) 
    ; 

編輯:我已經修改了,因爲我的最後一個條目解析器和詞法語法。我現在正在解析jsp文件時遇到問題。樣本JSP是:

<html> 
<title>Statement Load page</title> 

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

<body> 
</body> 
</html> 

在解析這個文件,我得到:

line 4:0 mismatched input '<script' expecting '<' 
line 5:31 no viable alternative at input '<script type="text/javascript" src' 

也就是說,儘管遭遇「<腳本」標籤解析器沒有進入「腳本」的規則,但可能將其視爲其他'htmlElement'。但我不確定。

解析器語法的相關部分是:

script 
    : SCRIPT_OPEN scriptAttribute* SCRIPT_TAG_CLOSE htmlContent* SCRIPT_TAG_FULL_CLOSE 
    | SCRIPT_OPEN scriptAttribute* SCRIPT_TAG_SLASH_CLOSE 
    ; 

scriptAttribute 
    : scriptAttributeName SCRIPT_EQUALS QUOTE scriptlet scriptAttributeValue* QUOTE 
    | scriptAttributeName SCRIPT_EQUALS scriptAttributeValue 
    | scriptAttributeName 
    ; 

scriptAttributeName 
    : WORD 
    ; 

scriptAttributeValue 
    : SCRIPT_ATTRIBUTE 
    ; 
+0

我一直在修改我的語法解析腳本標籤的更多細節。但是我在解析時遇到問題。 @Bart Kiers可以請你看看這個。 –