Detecting multibyte character sequences?

huangapple go评论75阅读模式
英文:

Detecting multibyte character sequences?

问题

I'm writing a parser which parses UTF-8 strings. Characters outside of the ASCII range can only occur inside of string literals, which begin and end with ' or ". The rest of the language may only contain ASCII characters, so I can simply return an error if I find a byte outside the ASCII range.

The problem I can't seem to figure out is, when I encounter a non-ASCII character inside of a string literal, how can I detect how many bytes to skip for that character? My concern is that if a multi-byte character contains a ' or " as one of the bytes, my parser would end the string literal early.

Perhaps a shorter way to ask this is, if I encounter a byte in the 0x80-0xFF range, how can I detect how many bytes are in that character in a UTF-8 encoded string?

I'm writing this parser in C but I suspect that doesn't matter.

英文:

I'm writing a parser which parses UTF-8 strings. Characters outside of the ASCII range can only occur inside of string literals, which begin and end with ' or ". The rest of the language may only contain ASCII characters, so I can simply return an error if I find a byte outside the ASCII range.

The problem I can't seem to figure out is, when I encounter a non-ASCII character inside of a string literal, how can I detect how many bytes to skip for that character? My concern is that if a multi-byte character contains a ' or " as one of the bytes, my parser would end the string literal early.

Perhaps a shorter way to ask this is, if I encounter a byte in the 0x80-0xFF range, how can I detect how many bytes are in that character in a UTF-8 encoded string?

I'm writing this parser in C but I suspect that doesn't matter.

答案1

得分: 6

> 我的担忧是,如果一个多字节字符的其中一个字节包含 ' 或 ",我的解析器将提前结束字符串字面量。

啊,这是你的误解。UTF-8 的精妙之处在于这种情况是不可能发生的。在 UTF-8 中,字节 0x27 只能 表示撇号。它永远不会是多字节序列的一部分。这是因为续字节的最高位始终设置为 1。

UTF-8 的一个主要设计目标是,即使在解析包含非 ASCII 字节的 UTF-8 流时,现有和天真的 ASCII 实现也会表现出相同的行为。你可以安全地解析 " 并继续累积字节,直到达到 "(并使用 \ 来转义内部的 "),而无需担心 UTF-8 中是否涉及多字节字符。ASCII 解析器无需理解 UTF-8 或执行任何 UTF-8 解码,就可以正确工作。

此外,如果你真的想知道你问题的答案,第一个字节的前导 1 位数告诉你长度,唯一的例外是零个 1 位是 "1 字节",一个 1 位是 "续字节"。

0x00 - 0x7F -> 1 字节
0x80 - 0xBF -> (续字节)
0xC0 - 0xDF -> 2 字节
0xE0 - 0xEF -> 3 字节
0xF0 - 0xF7 -> 4 字节

你也可以一直扫描,直到找到范围在 0x00-0x7F 内的内容。

英文:

> My concern is that if a multi-byte character contains a ' or " as one of the bytes, my parser would end the string literal early.

Ah, this is your misunderstanding. The brilliance of UTF-8 is that this cannot happen. In UTF-8, the byte 0x27 can only mean APOSTROPHE. It can never be part of a multi-byte sequence. This is because continuation bytes begin with the high bit set to 1.

A major design goal of UTF-8 is that existing and naïve ASCII implementations will work identically when parsing UTF-8 streams, even if the stream includes non-ASCII bytes. You can safely parse for " and continue to accumulate bytes until you reach " (and use \ to escape internal "), and never have to worry about whether there are multi-byte characters involved with UTF-8. ASCII parsers do not need to understand UTF-8 or perform any UTF-8 decoding in order to work correctly.

Beyond that, if you decide you really do want to know the answer to your question, the first byte's number of leading 1 bits tells you the length, with the exception that zero 1s is "1 byte" and one 1 is "continuation".

0x00 - 0x7F -> 1 byte
0x80 - 0xBF -> (continuation)
0xC0 - 0xDF -> 2 bytes
0xE0 - 0xEF -> 3 bytes
0xF0 - 0xF7 -> 4 bytes

You can also just keep scanning along until you find something in the range 0x00-0x7F.

huangapple
  • 本文由 发表于 2023年5月7日 22:53:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76194653.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定