我正在为实时编程语言PEARL编写编译器。 PEARL支持具有嵌入式控制字符序列的字符串,例如
'some text'\1B 1B 1B\'some more text'.
控制字符序列以'\为前缀,以\'结尾。 控制序列内部有两位数字,用于指定控制字符。
在上面的示例中,结果字符串为
'some textESCESCESCsome more text'
ESC代表不可打印的ASCII转义字符。
此外,控制字符序列内部还允许换行符来构建多行字符串,例如
'some text'\1B
1B
1B\'some more text'.
与上面的字符串相同。
grammar stringliteral;
tokens {
CHAR,CHARS,CTRLCHARS,ESC,WHITESPACE,NEWLINE
}
stringLiteral: '\'' CHARS? '\'' ;
fragment
CHARS: CHAR+ ;
fragment
CHAR: CTRLCHARS | ~['\n\r] ;
fragment
ESC: '\'\\' ;
fragment
CTRLCHARS: ESC ~['] ESC;
WHITESPACE: (' ' | '\t')+ -> channel(HIDDEN);
NEWLINE: ( '\r' '\n'? | '\n' ) -> channel(HIDDEN);
上面的词法分析器/解析器的行为非常奇怪,因为它仅接受 字符串,格式为“ x”,并忽略多个字符和控制字符序列。
我可能正在监督一些显而易见的事情。欢迎任何提示或想法解决此问题!
我现在已经根据迈克的提示纠正了语法:
grammar stringliteral;
tokens {
STRING
}
stringLiteral: STRING;
STRING: '\'' ( '\'' '\\' | '\\' '\'' | . )*? '\'';
识别控制字符序列的末尾仍然存在问题:
输入'A STRING'\ CTRL \''会产生错误
Line 1:10 token recognition error at: '\'
line 1:11 token recognition error at: 'C'
line 1:12 token recognition error at: 'T'
line 1:13 token recognition error at: 'R'
line 1:14 token recognition error at: 'L'
line 1:15 token recognition error at: '\'
有什么主意吗?顺便说一句:我们正在使用antlr v 4.5。
答案 0 :(得分:0)
此语法有多个问题:
WHITESPACE
和NEWLINE
规则定义的自动空格删除的约束。\1B 1B 1B
之类的控制字符序列。尤其是第三点是一个实际的问题,因为您不知道控制序列在哪里结束(除非这只是一个错字,而您实际上的意思是:\1B \1B \1B
。
无论如何,不要在词法分析器中处理转义序列(除非使规则起作用所需的最低限度处理,即\'
序列的处理。您的规则只需要解析整个文本并您可以在语义阶段找出转义序列:
STRING: '\' ('\\' '\'' | . )*? '\'';
注意*?
是非贪心运算符,用于在第一个结束引号char处停止。否则,词法分析器将继续匹配同一字符串规则(贪婪行为)中的所有以下(转义和非转义)引号字符。此外,字符串规则现在是词法分析器规则,不受空白跳的影响。
答案 1 :(得分:0)
我通过修改最新的Java语法示例中的适当规则,解决了该语法片段的问题:
StringLiteral
: '\'' StringCharacters? '\''
;
fragment
StringCharacters
: StringCharacter+
;
fragment
StringCharacter
: ~['\\\r\n]
| EscapeSequence
;
fragment
EscapeSequence
: '\'\\' (HexEscape| ' ' | [\r\n])* '\\\''
;
fragment
HexEscape
: B4Digit B4Digit
;
fragment
B4Digit
: '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
;