如何使用antlr4解析3字节utf8字符串

问题描述 投票:0回答:1

下面是我的语法文件。

grammar My;

tokens {
    DELIMITER
}

string:SINGLE_QUOTED_TEXT;

SINGLE_QUOTED_TEXT: (
        '\'' (.)*? '\''
    )+
;

我试图用它来接受所有字符串(它实际上是 mysql g4 的一部分)。 然后我用这段代码来测试它:

#include "MyLexer.h"
#include "MyParser.h"
#include <string>
using namespace My;

int main()
{
    std::string s = "'中'";

    antlr4::ANTLRInputStream input(s);
    MyLexer lexer(&input);

    antlr4::CommonTokenStream tokens(&lexer);
    MyParser parser(&tokens);

    parser.string();

    return 0;
}

结果是 enter image description here

汉字

的utf8编码为3个字节:
\xe4
\xb8
\xad

语法文件和代码文件均采用utf8编码。 我该怎么做才能让它正常工作?

c++ regex utf-8 antlr antlr4
1个回答
0
投票

我已经找到问题所在了。

参考https://stackoverflow.com/a/26865200/9634413

Antlr C++ 运行时使用 std::u32string 来存储输入,\xe4 将被转换为 \xffffffe4,这超出了 unicode 范围 [0,0x10ffff]。

要解决此问题,只需重写 ANTLRInputStream 的构造函数即可:

class MyStream : public antlr4::ANTLRInputStream {
public:
    MyStream(const std::string& input = "")
        : antlr4::ANTLRInputStream(input)
    {
        // Remove the UTF-8 BOM if present
        const char bom[4] = "\xef\xbb\xbf";
        if (input.compare(0, 3, bom, 3) == 0) {
            std::transform(input.begin() + 3, input.end(), _data.begin(),
                [](char c) -> unsigned char { return c; });
        }
        else {
            std::transform(input.begin(), input.end(), _data.begin(),
                [](char c) -> unsigned char { return c; });
        }
        p = 0;
    }
    MyStream(const char data_[], size_t numberOfActualCharsInArray)
        : antlr4::ANTLRInputStream(data_, numberOfActualCharsInArray)
    {
    }
    MyStream(std::istream& stream)
        : antlr4::ANTLRInputStream(stream)
    {
    }
};
© www.soinside.com 2019 - 2024. All rights reserved.