iGe*_*eks 3 unicode bison flex-lexer
我有一个关于两个 unicode 字符的简单问题,我想在我的编程语言中使用它。对于作业,我想使用旧的 APL 符号?也 ?。
我的 flex 文件 (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();
}
Run Code Online (Sandbox Code Playgroud)
当我“snazzle”以下输入时:
x ? y;
Run Code Online (Sandbox Code Playgroud)
我得到分配字符 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: ;
Run Code Online (Sandbox Code Playgroud)
我该如何添加?和 ?尽可能使用弹性字符?
Flex 生产八位清洁扫描仪;也就是说,它可以处理由任意八位字节组成的任何输入。它对 UTF-8 或 Unicode 代码点一无所知,但这并不能阻止它将 Unicode 输入字符识别为八位字节序列(不是单个字符)。哪个序列取决于您使用的 Unicode 编码,但假设您的文件是 UTF-8,→ 将是三个字节e2 86 92,← 将是e2 86 90.
然而,您实际上不必知道这一点。您可以将 UTF-8 序列放入您的 flex 模式中。您甚至不需要引用它,尽管它可能是一个好主意,因为如果您最终使用正则表达式运算符,它会证明不那么令人困惑。这里我的意思是引用它,如"←". \←不会做你所期望的,因为\只适用于下一个八位字节(正如我所说,flex 对 Unicode 编码一无所知),它只是该符号中三个字节中的第一个。换句话说,"←"?真正的意思是“一个可选的左箭头”,而\←?意思是“两个八位字节\xE2 \x86 可选地后跟 \x90”。我希望这很清楚。
Flex 字符类对 Unicode 序列(或任何其他多字符序列)没有用,因为字符类是一组八位字节。因此,如果您编写[←],flex 会将其解释为“八位字节之一\xE2,\x86或\x90”。[注1]
在 flex 字符类中很少需要反斜杠转义字符;必须被反斜杠转义的唯一字符是反斜杠本身。转义不需要转义的字符并不是错误,所以 flex 不会抱怨它,但它使人类难以阅读字符类(至少,对于这个人来说)。So 的[\←]意思完全相同[←],你可以写[\[\]\(\)\{\}]为[][)(}{]. (]如果它是类中的第一个字符,则不会关闭字符类,因此通常“面对面”编写括号)。
也没有必要在替代项([\?])|([\?])|(:=)|(=:)中将字符序列括起来,因此您可以编写为?|?|:=|=:. 或者,如果您愿意,"?"|"?"|":="|"=:". 当然,您通常不会这样做,因为扫描器通常会通知解析器每个单独的操作符。如果您的意图是使 ← 成为 的同义词:=,那么您最终可能会得到:
?|:= { return LEFT_ARROW; }
?|=: { return RIGHT_ARROW; }
Run Code Online (Sandbox Code Playgroud)与其printf在您的扫描仪规范中插入操作,不如让 flex 将您的扫描仪置于调试模式。这就像-d在构建扫描仪时添加到 flex 命令行一样简单。有关更多详细信息,请参阅有关调试的flex 手册部分。
| 归档时间: |
|
| 查看次数: |
1225 次 |
| 最近记录: |