无法在 Antlr4 中实现带有自定义分隔符的 q 引号字符串
No way to implement a q quoted string with custom delimiters in Antlr4
我正在尝试为 oracle Q 引用字符串机制实现词法分析器规则,其中我们有类似 q'$some string$'
在这里,您可以用任何字符代替 $,但空格、(、{、[、< 除外,但字符串必须以相同的字符开头和结尾。可接受的标记示例包括:
q'!some string!'
q'ssome strings'
请注意 s 是自定义分隔符,但在字符串中也可以使用它,因为我们只会在 s'
处结束
以下是我尝试实施规则的方式:
Q_QUOTED_LITERAL: Q_QUOTED_LITERAL_NON_TERMINATED . QUOTE-> type(QUOTED_LITERAL);
Q_QUOTED_LITERAL_NON_TERMINATED:
Q QUOTE ~[ ({[<'"\t\n\r] { setDelimChar( (char)_input.LA(-1) ); }
( . { !isValidEndDelimChar() }? )*
;
我已经检查了我从 !isValidEndDelimChar() 获得的值,我在正确的地方得到了一个错误的谓词,所以一切都应该有效,但 antlr 只是忽略了这个谓词。我也试过移动谓词,把那部分放在一个单独的规则中,还有一堆其他的东西,经过一天半的研究,我终于提出了这个问题。
我也尝试过以其他方式实现它,但似乎没有办法在 antlr4(antlr3 版本曾经工作)中实现自定义字符分隔字符串。
不确定为什么不调用 { ... }
操作,但不需要。以下语法对我有用(将谓词放在 .
前面!):
grammar Test;
@lexer::members {
boolean isValidEndDelimChar() {
return (_input.LA(1) == getText().charAt(2)) && (_input.LA(2) == '\'');
}
}
parse
: .*? EOF
;
Q_QUOTED_LITERAL
: 'q\'' ~[ ({[<'"\t\n\r] ( {!isValidEndDelimChar()}? . )* . '\''
;
SPACE
: [ \t\f\r\n] -> skip
;
如果你 运行 class:
import org.antlr.v4.runtime.*;
public class Main {
public static void main(String[] args) {
Lexer lexer = new TestLexer(CharStreams.fromString("q'ssome strings' q'!foo!'"));
CommonTokenStream tokens = new CommonTokenStream(lexer);
tokens.fill();
for (Token t : tokens.getTokens()) {
System.out.printf("%-20s %s\n", TestLexer.VOCABULARY.getSymbolicName(t.getType()), t.getText());
}
}
}
将打印以下输出:
Q_QUOTED_LITERAL q'ssome strings'
Q_QUOTED_LITERAL q'!foo!'
EOF <EOF>
我正在尝试为 oracle Q 引用字符串机制实现词法分析器规则,其中我们有类似 q'$some string$'
在这里,您可以用任何字符代替 $,但空格、(、{、[、< 除外,但字符串必须以相同的字符开头和结尾。可接受的标记示例包括: q'!some string!' q'ssome strings' 请注意 s 是自定义分隔符,但在字符串中也可以使用它,因为我们只会在 s'
处结束以下是我尝试实施规则的方式:
Q_QUOTED_LITERAL: Q_QUOTED_LITERAL_NON_TERMINATED . QUOTE-> type(QUOTED_LITERAL);
Q_QUOTED_LITERAL_NON_TERMINATED:
Q QUOTE ~[ ({[<'"\t\n\r] { setDelimChar( (char)_input.LA(-1) ); }
( . { !isValidEndDelimChar() }? )*
;
我已经检查了我从 !isValidEndDelimChar() 获得的值,我在正确的地方得到了一个错误的谓词,所以一切都应该有效,但 antlr 只是忽略了这个谓词。我也试过移动谓词,把那部分放在一个单独的规则中,还有一堆其他的东西,经过一天半的研究,我终于提出了这个问题。
我也尝试过以其他方式实现它,但似乎没有办法在 antlr4(antlr3 版本曾经工作)中实现自定义字符分隔字符串。
不确定为什么不调用 { ... }
操作,但不需要。以下语法对我有用(将谓词放在 .
前面!):
grammar Test;
@lexer::members {
boolean isValidEndDelimChar() {
return (_input.LA(1) == getText().charAt(2)) && (_input.LA(2) == '\'');
}
}
parse
: .*? EOF
;
Q_QUOTED_LITERAL
: 'q\'' ~[ ({[<'"\t\n\r] ( {!isValidEndDelimChar()}? . )* . '\''
;
SPACE
: [ \t\f\r\n] -> skip
;
如果你 运行 class:
import org.antlr.v4.runtime.*;
public class Main {
public static void main(String[] args) {
Lexer lexer = new TestLexer(CharStreams.fromString("q'ssome strings' q'!foo!'"));
CommonTokenStream tokens = new CommonTokenStream(lexer);
tokens.fill();
for (Token t : tokens.getTokens()) {
System.out.printf("%-20s %s\n", TestLexer.VOCABULARY.getSymbolicName(t.getType()), t.getText());
}
}
}
将打印以下输出:
Q_QUOTED_LITERAL q'ssome strings'
Q_QUOTED_LITERAL q'!foo!'
EOF <EOF>