ANTLR4:在标记规则中使用非ASCII字符

10

在ANTRL4书的第74页上,它说任何Unicode字符都可以通过以这种方式指定其代码点来在语法中使用:

'\uxxxx'

其中xxxx是Unicode代码点的十六进制值。

因此,我在ID令牌的标记规则中使用了该技术:

grammar ID;

id : ID EOF ;

ID : ('a' .. 'z' | 'A' .. 'Z' | '\u0100' .. '\u017E')+ ;
WS : [ \t\r\n]+ -> skip ;

当我尝试解析这个输入时:

Gŭnter

ANTLR出现错误,提示无法识别ŭ。(ŭ字符是十六进制016D,因此在指定范围内)

请问我做错了什么?

4个回答

11

ANTLR准备好接受16位字符,但是默认情况下,许多语言环境将以字节(8位)形式读入字符。在使用Java库读取文件时,您需要指定适当的编码方式。如果您正在使用TestRig,可能通过别名/脚本grun进行使用,则使用参数-encoding utf-8或其他编码方式。如果您查看该类的源代码,您将看到以下机制:

InputStream is = new FileInputStream(inputFile);
Reader r = new InputStreamReader(is, encoding); // e.g., euc-jp or utf-8
ANTLRInputStream input = new ANTLRInputStream(r);
XLexer lexer = new XLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
...

2
你不应该在语法中使用TestRig,这就是antlr的作用。 - Terence Parr
3
编码按照我的回答输入到 GruN 上。 - Terence Parr
3
java -Dfile.encoding=UTF-8 org.antlr.v4.runtime.misc.TestRig ID ... - Gunther
2
谢谢Gunther。我尝试了一下,但是它仍然显示相同的错误信息:无法加载-encoding作为词法分析器或语法分析器。 - Roger Costello
虽然已经晚了一年,但它可能会像对我有用一样对其他人有帮助。它说:“无法将-encoding作为词法分析器或解析器加载。”因为你的解析器/词法分析器名称必须紧跟在org.antlr.v4.runtime.misc.TestRig之后。现在它正在尝试查找名为“-encoding”的词法分析器/解析器。正确的命令是“java org.antlr.v4.runtime.misc.TestRig grammarName -encoding UTF-8 startRule input.txt”。 - Emiel Steerneman
显示剩余3条评论

4

语法:

NAME:
   [A-Za-z][0-9A-Za-z\u0080-\uFFFF_]+
;

Java:

import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.TokenStream;

import com.thalesgroup.dms.stimulus.StimulusParser.SystemContext;

final class RequirementParser {

   static SystemContext parse( String requirement ) {
      requirement = requirement.replaceAll( "\t", "   " );
      final CharStream     charStream = CharStreams.fromString( requirement );
      final StimulusLexer  lexer      = new StimulusLexer( charStream );
      final TokenStream    tokens     = new CommonTokenStream( lexer );
      final StimulusParser parser     = new StimulusParser( tokens );
      final SystemContext  system     = parser.system();
      if( parser.getNumberOfSyntaxErrors() > 0 ) {
         Debug.format( requirement );
      }
      return system;
   }

   private RequirementParser() {/**/}
}

来源:

词法分析器和Unicode文本


4

如果您在Java代码中使用antlr4时遇到相同的问题,ANTLRInputStream已经被弃用了。这里有一种可行的方法可以将多字符Unicode数据从一个String传递给MyLexer词法分析器:

String myString = "\u2013";

CharBuffer charBuffer = CharBuffer.wrap(myString.toCharArray());
CodePointBuffer codePointBuffer = CodePointBuffer.withChars(charBuffer);
CodePointCharStream cpcs = CodePointCharStream.fromBuffer(codePointBuffer);

OneLexer lexer = new MyLexer(cpcs);       
CommonTokenStream tokens = new CommonTokenStream(lexer);

1

在实际读取文件时,您可以指定文件的编码方式。 对于Kotlin/Java,可以像这样进行设置,语法中不需要指定编码方式!

val inputStream: CharStream = CharStreams.fromFileName(fileName, Charset.forName("UTF-16LE"))
val lexer = BlastFeatureGrammarLexer(inputStream)

Java/Kotlin支持的字符集


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接