在RFC2616(HTTP / 1.1)中,“2.2基本规则”一节中“令牌”的定义如下:
token = 1*<any CHAR except CTLs or separators>
从那一节开始,我有以下片段,现在我想定义'TOKEN':
lexer grammar AcceptEncoding;
TOKEN: /* (CHAR excluding (CTRL | SEPARATORS)) */
fragment CHAR: [\u0000-\u007f];
fragment CTRL: [\u0000-\u001f] | \u007f;
fragment SEPARATORS: [()<>@,;:\\;"/\[\]?={|}] | SP | HT;
fragment SP: ' ';
fragment HT: '\t';
对于TOKEN
的定义,我如何估计我的假设“排除”运算符?
答案 0 :(得分:1)
ANTLR中没有设置/范围数学。您只能通过OR运算符组合多个集/范围。许多不相交范围的典型规则如下:
fragment LETTER_WHEN_UNQUOTED:
'0'..'9'
| 'A'..'Z'
| '$'
| '_'
| '\u0080'..'\uffff'
;
答案 1 :(得分:0)
一种方法是对字符集进行“数学运算”,以便我们可以定义只能组合字符的词法规则:
lexer grammar RFC2616;
TOKEN: (DIGIT | UPALPHA | LOALPHA | NON_SEPARATORS)+
/*
* split up ASCII 0-127 into 'atoms' of
* relevance per '2.2 Basic Rules'. Regions
* not requiring to be referenced are not
* given a name.
*/
// [\u0000-\u0008]; /* (control chars) */
fragment HT: '\u0009'; /* (tab) */
fragment LF: '\u0010'; /* (LF) */
// [\u0011-\u0012]; /* (control chars) */
fragment CR: '\u0013'; /* (CR)
// [\u0014-\u001f]; /* (control chars) */
fragment SP: '\u0020'; /* (space) */
// [\u0021-\u02f]; /* !"#$%'()*+,-./ */
fragment DIGIT: [u0030-\u0039]; /* 01234556789 */
// [\u003a-\u0040]; /* :;<=>@ */
fragment UPALPHA: [\u0041-\u005a]; /* ABCDEFGHIGJLMNOPQRSTUVWXYZ */
// [\u005b-\u0060]; /* [\]^_` */
fragment LOALPHA: [\u0061-\u0071]; /* abcdefghijklmnopqrstuvwxyz */
// [\u007b-\u007e]; /* {|}~ */
// '\u007f'; /* (del) */
/*
* Considering 'all relevant gaps' and the characters we
* cannot use per RFC 2616 Section 2.2 Basic Rules definition
* of 'separators', what does that leave us with?
* (manually determined)
*/
fragment SEPARATORS: [()<>@,;:\\;"/\[\]?={|}];
fragment NON_SEPARATORS: [!#$%&'*+-.^_`~*];
我发现这种方法并不特别令人满意。 RFC 2616中的另一条规则希望定义为:
TEXT: <any OCTET except CTLs, but including LWS>
qdtext = <any TEXT except <">>
这会迫使我进一步重构上面的权宜之计'SEPARATORS'令牌,如:
fragment QUOT: '"';
fragment SEPARATORS_OTHER_THAN_QUOT: [()<>@,;:\\;/\[\]?={|}];
fragment SEPARATORS: SEPARATORS_OTHER_THAN_QUOT | QUOT;
fragment LWS: SP | HT;
TEXT: DIGIT | UPALPHA | LOALPHA | LWS | SEPARATORS | NON_SEPARATORS;
QDTEXT: DIGIT | UPALPHA | LOALPHA | LWS | SEPARATORS_OTHER_THAN_QUOT | NON_SEPARATORS;
也许这是编写词法分析器的一部分,并且无法避免,但感觉更像是以错误的方式解决问题!
(注意:我不会将此答案标记为'正确'。)
答案 2 :(得分:0)
受到来自@ mike-lischke的答案的刺激(因为LETTER_WHEN_UNQUOTED
真的感觉还是错的),我在其他语法中寻找对引用的字符串文字进行肯定常见的处理。在Terrence Parr自己的Java 1.6 ANTLR3 grammar(呃,没有正确地作为text/plain
)(通过ANTLR3 Grammar List),他可以获得除#39以外的任何角色的比赛;词法分析器规则中的波浪号运算符~
:
STRINGLITERAL
: '"'
( EscapeSequence
| ~( '\\' | '"' | '\r' | '\n' )
)*
'"'
;
// Copyright (c) 2007-2008 Terence Parr and possibly Yang Jiang.
注意:上述代码是根据BSD许可证授权的,但我不在BSD许可下重新分发此片段(因为此帖子本身在CC-BY-SA下)。相反,我我在“合理使用”的条款中使用它。据我所知。
因此~
为我提供了一个选项来表达:&#39; Unicode中的所有字符,但设置B&#39;中的字符除外。 &#34;恼人的我不会选择被排除在&#34;之外的那套,我想。但后来我意识到了
TOOHIGH: [\u007f-\uffff];
TOKEN: (~( TOOHIGH | SP | HT | CTRL | SEPARATORS ))+
......应该没事。虽然在实践中,ANTLR4并不喜欢&#39; lexer子规则出现在&#39; sets&#39;中,并且只处理文字集,因此最终变为:
TOKEN:
/* this is given in '2.2 Basic Rules' as:
*
* token = 1*<any CHAR except CTLs or separators>
*
* which I am reducing down to:
* any character in ASCII 0-127 but _excluding_
* CTRL (0-31,127)
* SEPARATORS
* space (32)
* and tab (9) (which is a CTRL character anyhow)
*/
( ~( [\u0000-\u001f] | '\u007f' /*CTRL,HT*/ | [()<>@,;:\\;"/\[\]?={|}] /*SEPARATORS*/ | '\u0020' /*SP*/ | [\u0080-\uffff] /*NON_ASCII*/))*
;
诀窍是用including the set I do want
(Unicode 128 +)来表达excluding the set I don't want
(Unicode 0-127)。
这比我的其他答案简洁得多。如果确实有效,我会将其标记为正确。