flex中的Unicode字符?

flex中的Unicode字符?,unicode,bison,flex-lexer,Unicode,Bison,Flex Lexer,我有一个关于两个unicode字符的简单问题,我想在我的编程语言中使用它们。对于赋值,我想使用旧的APL符号← 以及→. 我的flex文件(snazle.l)如下所示: /** phi@gress.ly 2017 **/ /** parser for omni programming language. **/ %{ #include <iostream> using namespace std; #define YY_DECL extern

我有一个关于两个unicode字符的简单问题,我想在我的编程语言中使用它们。对于赋值,我想使用旧的APL符号← 以及→.

我的flex文件(snazle.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();
}
我得到的赋值字符a)错误和b)三(3)次:


我怎样才能补充呢← 及→ 尽可能使用flex字符?

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不会对此抱怨,但这会使字符类难以阅读(至少对这个人来说是可以阅读的)所以
    [\←]的意思与
    [←][\[\]\(\)\{\}]
    ,因为
    [][)(}{]
    (]如果是类中的第一个字符,则不会关闭字符类,因此通常会“面对面”编写括号

  • 也没有必要在备选方案中插入字符序列,因此您可以编写
    ([\←])|([\→])|(:=)|(=:)
    as
    ←|→|:=|=:。或者,如果您愿意,
    ”←"|"→“|”:=“|”=:”
    。当然,您通常不会这样做,因为扫描器通常会向解析器通知每个单独的运算符。如果您打算← 如果是
    :=
    的同义词,那么您可能会得到:

    ←|:=    { return LEFT_ARROW; }
    →|=:    { return RIGHT_ARROW; }
    
  • 与其在扫描仪规范中插入
    printf
    操作,不如让flex将扫描仪置于调试模式。这与在构建扫描仪时将
    -d
    添加到flex命令行一样简单。有关详细信息,请参阅


  • 哇,这真的很有帮助。这么多的rici。我很少在论坛上看到这么好的答案。同意,但是Flex“看到了UTF-8八位字节序列作为8位代码点,Flex从未被设计成正确处理Unicode。只有非常简单的UTF-8模式可以被容忍和处理。对于C或C++,有更好的自由扫描器生成器,可以正确处理Unicode UTF-8、UTF-16和UTF-32编码(标记无效的UTF-8,这构成了风险)。.Quex或RE/flex出现在脑海中。
    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: ;
    
    ←|:=    { return LEFT_ARROW; }
    →|=:    { return RIGHT_ARROW; }