我正嘗試使用Antlr4構建MVS JCL識別器。一般的努力進行得相當順利,但是我在處理與* nix「here docs」(內聯文件)相當的MVS時遇到了麻煩。我無法使用詞法分析器模式在JCL和here-doc內容之間進行觸發器翻譯,因此我正在尋找可能使用解析器級別的替代方法。Antlr 4:在解析器中切換模式的方法
IBM MVS允許使用「instream數據集」,類似於* nix here-docs。
實施例:
這定義使用標籤「ANYNAME」三線聯文件,用字符「ZZ」和訪問一個引用程序終止:
//ANYNAME DD *,SYMBOLS=(JCLONLY,FILEREF),DLM=ZZ
HEREDOC TEXT 1
HEREDOC TEXT 2
HEREDOC TEXT 3
ZZ
//NEXTFILE DD ...stuff...
ANYNAME
是手柄程序可以通過它訪問here-doc內容。
DD *
是強制性的,並通知MVS一個here-doc如下。
SYMBOLS=(JCLONLY,FILEREF)
是關於如何處理here-doc的可選細節。
DLM=ZZ
也是可選的並且定義了here-doc終止符(默認終止符= /*
)。
我需要能夠在解析器水平,處理//ANYNAME...
線(我有位),然後直到我找到了(可能非默認)來讀取這裏-doc的內容在這裏-doc的終止 。從某種意義上說,這看起來像一個詞法分析模式的機會 - 但在這一點上我正在解析器中工作,而且我沒有固定的終結器來處理。
我需要指導如何切換模式來處理我的here-doc,然後再切換回來繼續處理我的JCL。
下面是我的語法的一個非常簡潔的版本(實際語法到目前爲止大約是2,200行,並且是不完整的)。
感謝您的任何見解。感謝您的幫助,意見和建議。
/* the ddstmt parser rule should be considered the main entry point. It handles (at least):
//ANYNAME DD *,SYMBOLS=(JCLONLY,FILEREF),DLM=ZZ
and // DD *,DLM=ZZ
and //ANYNAME DD *,SYMBOLS=EXECSYS
and //ANYNAME DD *
I need to be able process the above line as JCL then read the here-doc content...
"HEREDOC TEXT 1"
"HEREDOC TEXT 2"
"HEREDOC TEXT 3"
as either a single token or a series of tokens, then, after reading the here-doc
delimiter...
"ZZ"
, go back to processing regular JCL again.
*/
/* lexer rules: */
LINECOMMENT3 : SLASH SLASH STAR ;
DSLASH : SLASH SLASH ;
INSTREAMTERMINATE : SLASH STAR ;
SLASH : '/' ;
STAR : '*' ;
OPAREN : '(' ;
CPAREN : ')' ;
COMMA : ',' ;
KWDD : 'DD' ;
KWDLM : 'DLM' ;
KWSYMBOLS : 'SYMBOLS' ;
KWDATA : 'DATA' ;
SYMBOLSTARGET : 'JCLONLY'|'EXECSYS'|'CNVTSYS' ;
EQ : '=' ;
APOST : '\'' ;
fragment
SPC : ' ' ;
SPCS : SPC+ ;
NL : ('\r'? '\n') ;
UNQUOTEDTEXT : (APOST APOST|~[=\'\"\r\n\t,/() ])+ ;
/* parser rules: */
label : unquotedtext
;
separator : SPCS
;
/* handle crazy JCL comment rules - start */
partcomment : SPCS partcommenttext NL
;
partcommenttext : ((~NL+?)?)
;
linecomment : LINECOMMENT3 linecommenttext NL
;
linecommenttext : ((~NL+?)?)
;
postcommaeol : ((partcomment|NL) linecomment* DSLASH SPCS)?
;
poststmteol : ((partcomment|NL) linecomment*)?
;
/* handle crazy JCL comment rules - end */
ddstmt : DSLASH (label|) separator KWDD separator dddecl
;
dddecl : ...
| ddinstreamdecl
| ...
;
ddinstreamdecl : (STAR|KWDATA) poststmteol ddinstreamopts
;
ddinstreamopts : (COMMA postcommaeol ddinstreamopt poststmteol)*
;
ddinstreamopt : ( ddinstreamdelim
| symbolsdecl
)
;
ddinstreamdelim : KWDLM EQ unquotedtext
;
symbolsdecl : KWSYMBOLS EQ symbolsdef
;
symbolsdef : OPAREN symbolstarget (COMMA symbolsloggingdd)? CPAREN
| symbolstarget
;
symbolstarget : SYMBOLSTARGET
;
symbolsloggingdd : unquotedtext
;
unquotedtext : UNQUOTEDTEXT
;
感謝您抽出寶貴的時間爲我提供你的洞察力。我會審查它,並試圖讓我的頭腦圍繞你所建議的技術。我可能會回來更多的問題。 TIA。 – v0rl0n 2014-12-05 19:08:42