flex 中的 Unicode 字符?
Unicode Character in flex?
我有一个关于两个 unicode 字符的简单问题,我想在我的编程语言中使用它们。对于作业,我想使用旧的 APL 符号 ← 以及 →。
我的弹性文件 (snazzle.l) 如下所示:
/** phi@gress.ly 2017 **/
/** parser for omni programming language. **/
%{
#include <iostream>
using namespace std;
#define YY_DECL extern "C" int yylex()
int linenum = 0;
%}
%%
[\n] {++linenum;}
[ \t] ;
[0-9]+\.[0-9]+([eE][+-]?[0-9]+)? { cout << linenum << ". Found a floating-point number: " << yytext << endl; }
\"[^\"]*\" { cout << linenum << ". Found string: " << yytext << endl; }
[0-9]+ { cout << linenum << ". Found an integer: " << yytext << endl; }
[a-zA-Z0-9]+ { cout << linenum << ". Found an identifier: " << yytext << endl; }
([\←])|([\→])|(:=)|(=:) { cout << linenum << ". Found assignment operator: " << yytext <<endl; }
[\;] { cout << linenum << ". Found statement delimiter: " << yytext <<endl; }
[\[\]\(\)\{\}] { cout << linenum << ". Found parantheses: " << yytext << endl; }
%%
main() {
// lex through the input:
yylex();
}
当我"snazzle"输入以下内容时:
x → y;
我得到赋值字符 a) 错误和 b) 三 (3) 次:
0. Found an identifier: x
0. Found assignment operator: �
0. Found assignment operator: �
0. Found assignment operator: �
0. Found an identifier: y
0. Found statement delimiter: ;
如何添加 ← 和 → 尽可能灵活的字符?
Flex 生产八位清洁扫描仪;也就是说,它可以处理由任意八位字节组成的任何输入。它对 UTF-8 或 Unicode 代码点一无所知,但这并不能阻止它将 Unicode 输入字符识别为八位字节的 序列 (not 单个字符)。哪个序列取决于您使用的 Unicode 编码,但假设您的文件是 UTF-8,→ 将是三个字节 e2 86 92
和 ← 将是 e2 86 90
.
然而,您实际上不必知道这一点;您可以将 UTF-8 序列放入您的 flex 模式中。您甚至不需要引用它,尽管这可能是个好主意,因为如果您最终使用正则表达式运算符,它会证明不那么混乱。这里我的意思是引用它,如"←"
。 \←
不会做你期望的,因为 \ 只适用于下一个 octet (正如我所说,flex 对Unicode 编码),它只是该符号中三个字节中的第一个。换句话说,"←"?
真正意味着 "an optional left-arrow",而 \←?
意味着 "the two octets \xE2 \x86
optionally followed by \x90
"。我希望这很清楚。
Flex 字符 classes 对 Unicode 序列(或任何其他多字符序列)没有用,因为字符 class 是一组八位字节。因此,如果您写 [←]
,flex 会将其解释为 "one of the octets \xE2
, \x86
or \x90
"。 [注1]
备注
很少需要在 flex 字符 classes 中对字符进行反斜杠转义;唯一必须反斜杠转义的字符是反斜杠本身。转义不需要转义的字符不是错误,因此 flex 不会抱怨它,但它会使字符 classes 难以让人阅读(至少,对于这个人来说是这样) .所以 [\←]
和 [←]
的意思完全一样,你可以把 [\[\]\(\)\{\}]
写成 [][)(}{]
。 (如果字符 class 是 class 中的第一个字符,] 不会关闭字符 class,因此通常写括号 "face-to-face")。
也没有必要在备选项中用括号括起字符序列,因此您可以将 ([\←])|([\→])|(:=)|(=:)
写成 ←|→|:=|=:
。或者,如果您愿意,"←"|"→"|":="|"=:"
。当然,您通常不会那样做,因为扫描器通常会通知解析器有关每个单独运算符的信息。如果您的目的是使 ← 成为 :=
的同义词,那么您可能会得到:
←|:= { return LEFT_ARROW; }
→|=: { return RIGHT_ARROW; }
与其在扫描仪规范中插入 printf
操作,不如让 flex 将扫描仪置于调试模式会更好。这就像在构建扫描仪时将 -d
添加到 flex 命令行一样简单。有关详细信息,请参阅 flex manual section on debugging。
我有一个关于两个 unicode 字符的简单问题,我想在我的编程语言中使用它们。对于作业,我想使用旧的 APL 符号 ← 以及 →。
我的弹性文件 (snazzle.l) 如下所示:
/** phi@gress.ly 2017 **/
/** parser for omni programming language. **/
%{
#include <iostream>
using namespace std;
#define YY_DECL extern "C" int yylex()
int linenum = 0;
%}
%%
[\n] {++linenum;}
[ \t] ;
[0-9]+\.[0-9]+([eE][+-]?[0-9]+)? { cout << linenum << ". Found a floating-point number: " << yytext << endl; }
\"[^\"]*\" { cout << linenum << ". Found string: " << yytext << endl; }
[0-9]+ { cout << linenum << ". Found an integer: " << yytext << endl; }
[a-zA-Z0-9]+ { cout << linenum << ". Found an identifier: " << yytext << endl; }
([\←])|([\→])|(:=)|(=:) { cout << linenum << ". Found assignment operator: " << yytext <<endl; }
[\;] { cout << linenum << ". Found statement delimiter: " << yytext <<endl; }
[\[\]\(\)\{\}] { cout << linenum << ". Found parantheses: " << yytext << endl; }
%%
main() {
// lex through the input:
yylex();
}
当我"snazzle"输入以下内容时:
x → y;
我得到赋值字符 a) 错误和 b) 三 (3) 次:
0. Found an identifier: x
0. Found assignment operator: �
0. Found assignment operator: �
0. Found assignment operator: �
0. Found an identifier: y
0. Found statement delimiter: ;
如何添加 ← 和 → 尽可能灵活的字符?
Flex 生产八位清洁扫描仪;也就是说,它可以处理由任意八位字节组成的任何输入。它对 UTF-8 或 Unicode 代码点一无所知,但这并不能阻止它将 Unicode 输入字符识别为八位字节的 序列 (not 单个字符)。哪个序列取决于您使用的 Unicode 编码,但假设您的文件是 UTF-8,→ 将是三个字节 e2 86 92
和 ← 将是 e2 86 90
.
然而,您实际上不必知道这一点;您可以将 UTF-8 序列放入您的 flex 模式中。您甚至不需要引用它,尽管这可能是个好主意,因为如果您最终使用正则表达式运算符,它会证明不那么混乱。这里我的意思是引用它,如"←"
。 \←
不会做你期望的,因为 \ 只适用于下一个 octet (正如我所说,flex 对Unicode 编码),它只是该符号中三个字节中的第一个。换句话说,"←"?
真正意味着 "an optional left-arrow",而 \←?
意味着 "the two octets \xE2 \x86
optionally followed by \x90
"。我希望这很清楚。
Flex 字符 classes 对 Unicode 序列(或任何其他多字符序列)没有用,因为字符 class 是一组八位字节。因此,如果您写 [←]
,flex 会将其解释为 "one of the octets \xE2
, \x86
or \x90
"。 [注1]
备注
很少需要在 flex 字符 classes 中对字符进行反斜杠转义;唯一必须反斜杠转义的字符是反斜杠本身。转义不需要转义的字符不是错误,因此 flex 不会抱怨它,但它会使字符 classes 难以让人阅读(至少,对于这个人来说是这样) .所以
[\←]
和[←]
的意思完全一样,你可以把[\[\]\(\)\{\}]
写成[][)(}{]
。 (如果字符 class 是 class 中的第一个字符,] 不会关闭字符 class,因此通常写括号 "face-to-face")。也没有必要在备选项中用括号括起字符序列,因此您可以将
([\←])|([\→])|(:=)|(=:)
写成←|→|:=|=:
。或者,如果您愿意,"←"|"→"|":="|"=:"
。当然,您通常不会那样做,因为扫描器通常会通知解析器有关每个单独运算符的信息。如果您的目的是使 ← 成为:=
的同义词,那么您可能会得到:←|:= { return LEFT_ARROW; } →|=: { return RIGHT_ARROW; }
与其在扫描仪规范中插入
printf
操作,不如让 flex 将扫描仪置于调试模式会更好。这就像在构建扫描仪时将-d
添加到 flex 命令行一样简单。有关详细信息,请参阅 flex manual section on debugging。