English  
     
 

 

主页   新闻   白皮书   文档   出版物   下载   源码   方案   资质
 
 
     
     
  主页| 文档| 目录| 前章| 后章    
       
     
     
 

第二章 词法结构


    本章定义Fuxi程序设计语言的词法结构(Lexical Structure)。Fuxi程序采用Unicode字符来编写,但是系统提供一种Unicode转义系列来进行字符转换,使得任何Unicode字符都可以采用ASCII码来表示。Fuxi的词法包括以下内容的定义:

行结束符号(Line Terminator):Fuxi使用一种和其它现有的宿主系统兼容的行结束符号,并且保持程序文本的行号的一致性;

空白(White space);

注释(Comment);

句法符号(Token):这些句法符号包括:标识符(Identifier)、关键字(Keyword)、文字量(Literal)、分隔符(Separator)及运算符(Operator)等。

§2.1 源程序输入流
本规范并不试图对源程序文件的编码形式或采用的源程序编辑器进行规定,而是假定Fuxi的实现(Implementation)能够把采用不同编码形式的Fuxi源程序文件转换成由Unicode字符组成的源程序输入流(Source Code Input Stream),也称为原始Unicode字符流(Raw Unicode Character Stream),并以此作为词法分析的输入,开始编译过程。

§2.1.1 Unicode
Unicode是一种国际字符的编码标准,Fuxi源程序输入流就是由Unicode字符编码组成的数据流。编译器将依据Fuxi的词法定义,对这个输入流进行分析,将其转换成一个个的词法符号。关于Unicode的材料可以在以下网站获取:

http://www.unicode.org

Fuxi语言采用Unicode的4.0版本,并且Fuxi平台将跟踪Unicode规范的演变而不断升级。

除了注释、标识符、字符常量及字符串外,所有程序的其它输入成分均由ASCII(the American Standard Code for Information Interchange)字符构成(下面所述的Unicode转义系列也是由ASCII字符构成的)。Unicode的前128个编码为ASCII字符。需要指出的是,由于Fuxi的标识符采用Unicode字符,因此类型名、变量名、方法名等都可以直接使用汉字(简体或繁軆)。

在不支持Unicode字符的编辑器中,用户可以使用Unicode转义系列(Unicode Escape Sequence)来输入任何Unicode字符,Unicode转义系列和其所对应的Unicode字符是完全等价的。

§2.1.2 词法转换
编译器通过以下的词法转换(Lexical Translation)步骤,将上述的原始Unicode字符流转换成各种词法符号(Tokens)。

转义处理(Escape Processing):将原始Unicode字符流中的Unicode转义系列转换成对应的Unicode字符。Unicode转义系列的形式为\uxxxx,其中xxxx为4个16进制数字,表示编码为xxxx的Unicode字符。该转换步骤允许所有的Fuxi程序都可以仅用ASCII字符来编写。

行识别(Line Recognition):将经过步骤1)转换得来的Unicode字符流转换成由输入字符和行结束符组成的流;

符号化过程(Tokenization):将经过步骤2)转换得来的由输入字符和行结束符组成的输入流转换成输入成分(Input Element),在剔除空白、注释后,形成词法符号(Tokens)组成的系列。这些词法符号(Token)是构成句法(Syntactic Grammar)的结点符号(Terminal Symbol)。

§2.1.3 Unicode转义系列
编译器对原始Unicode输入流进行转换,将原始Unicode输入字符转换为词法输入元素。原始的Unicode输入字符定义为:

<Unicode输入字符>:
<Unicode字符> 或
<Unicode转义系列>


<Unicode转义系列>定义为:

\<Unicode标记><16进制数字><16进制数字><16进制数字><16进制数字>

<Unicode标记>定义为:

u 或
u<Unicode标记>

<16进制数字>定义为下列字符之一:

0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f

其中\、u和<16进制数字>均为ASCII码。

当程序文本出现反斜杠‘\’时,词法分析器还需要统计该符号前面所遇到的连续‘\’的个数,如果前面的‘\’个数为偶数,则此‘\’可以和后面符号串依据上述<Unicode转义系列>的词法定义,进行<Unicode转义系列>分析;如果当前‘\’前面连续的‘\’个数为奇数,则当前的‘\’不能和后面的字符构成<Unicode转义系列>。例如,程序文本中的原始输入串"\\u2297=\u2297",将得出7个字符" \ \ u 2 2 9 7 = " (其中\u2297是字符""的Unicode编码)。

如果当前‘\’后面紧跟的字符不是u,则‘\’就是一个Unicode输入字符,词法分析继续后面的分析。

如果当前‘\’后面紧跟一个或几个u,如果最后一个u后面不是紧跟着4个16进制数字,则出现编译错误。一个已经分析出的Unicode转义字符不可继续参与后面Unicode转义分析。例如\u005cu005a,将得出6个字符\u005a,\u005c表示ASCII字符\,但它不能继续参与后面的Unicode转义分析,因此没有同后面的u005a构成新的Unicode转义字符。

§2.1.4 行结束符
编译器通过识别行结束符(Line Terminator)来对程序文本进行分行。行结束符是编译器确定字符的在文本中的行号的依据;同时行结束符也是//形式的注释结束的标记。行结束符号定义如下:

<行结束符号>:

一个ASCII码的LF字符,也称“换行”(\u000A) 或
一个ASCII码的CR字符,也称“回车”(\u000D) 或
一个ASCII码的CR字符紧跟一个ASCII码的LF字符 或
下一行符号(\u0085) 或
行分隔符(\u2028) 或
段分隔符(\u2029)

§2.2 符号化过程
原始Unicode字符流经过转义处理和行识别后,形成由输入字符和行结束符组成的字符流。这种字符流在剔除空白和注释后,被分析成词法符号(Token),这一过程称为符号化(Tokenization)。这些词法符号将进一步作为句法分析的输入。

我们通过以下词法规则来定义符号化过程。

<输入符号>定义为:

{<词法元素>}[<中断符>]

<词法元素>定义为:

<空白>
<注释>
<词法符号>

<中断符>定义为:

ASCII SUB字符,即“control-z”

空白和注释是程序中词法符号之间的分隔符号。符号化过程正是利用这些空白和注释来断取不同的词法符号来的。而control-Z中断符(\u001a)是一种可选的结束符号,主要是为维持和一些操作系统的兼容性。
对于输入流中的两个字符x和y,如果x出现在y的前面,我们则称x在y的左边,或者y在x的右边。例如,

class 空类 {
}

我们称‘{’在‘}’的左边,或者‘}’在‘{’的右边。这一约定,可以让我们定义一个二元操作符的左参量和右参量。

§2.2.1 空白
空白(White space)是有ASCII空格符(Space,\u0020)、水平制表符(Horizontal Tab,\u0029)、进表符(Form Feed,\u002c)以及行结束符组成。

<空白>定义为:

ASCII SP字符,即空格符 或
ASCII HT字符,即水平制表符 或
ASCII FF字符,即进表符 或
<行结束符>

§2.2.2 注释
注释有以下两种形式:

/* 注释 */
// 注释

第一种为传统注释形式,在ASCII字符/*和*/之间的所有内容将被忽略掉(和C、C++相同);第二种为行末注释形式,在ASCII字符//和行结束符之间的所有内容将被忽略掉(和C++相同)。
注释可以通过以下规则来加于形式化描述:

<注释>定义为:

<传统注释> 或
<行末注释>

<传统注释>定义为:

/*<非星号字符><注释尾部>

<行末注释>定义为:

//{<输入字符>}<行结束符>

<注释尾部>定义为:

*<注释尾杠>
<非星字符><注释尾部>

<注释尾杠>定义为:

/ 或
*<注释尾杠> 或
<非星非杠><注释尾部>

<非星字符>定义为:

不是星号*的输入字符

<非星非杠>定义为:

不是星号*和斜杠/的输入字符

上述词法规则隐含以下注释的特点:

注释不能嵌套;

在以//开头的注释中,/*和*/仅作为注释的内容而无其它含义;

在以/*开头的注释中,//仅作为注释的内容而无其它含义。

因此,下列文字:

/* 本注释 /* // /* 到此结束 */

仅表示一个完整的注释。

同时,词法规则也隐含注释不可出现在字符量和字符串中。

§2.3 词法符号
词法符号(Tokens)是词法分析的输出,同时也是句法分析的输入。词法符号是构成句法规则的结点符号(Terminal Symbols)。词法符号可以通过以下词法规则来定义:

<词法符号>定义为:

<标识符> 或
<关键字> 或
<文字量> 或
<分隔符> 或
<运算符>

§2.3.1 关键字
以下由ASCII字符组成的字符系列,被系统保留作关键字用,它们不能作为标识符来使用。

<关键字>是下列之一:

abstract active base bool byte
case char class const default
delete double else enum false
final float if import in
include insert int interface internal
let lock long macro mobile
native null operator override package
partial persistent private protected public
remote scan short static switch
take template test this true
ubyte uint ulong ushort volatile

§2.3.2 标识符
标识符(Identifier)是以字母开头,由任意多个字母、数字组成的、而非关键字的字符系列。标识符可以形式地定义如下:

<标识符>定义为:

不是<关键字>的<标识系列>

<标识系列>定义为:

<字母>{<字母或数字>}

<字母>定义为:

是Fuxi字母的Unicode字符

<字母或数字>定义为:

是Fuxi字母或者是Fuxi数字的Unicode字符

所谓的“Fuxi字母”是从整个Unicode字符集中抽取出来的,它能支持当今世界上大多数文字,包括汉字、日文、韩文等大字符集;其中包括ASCII大小写的拉丁字母A ~ Z (\u0041 ~ \u005a)、a ~ z (\u0061 ~ \u007a),并且出于历史的原因,还包括ASCII下划线(_,\u005f)和美圆符号($, \u0024),但$仅作系统内部使用,用户程序中不可使用;包括CJK大汉字字符集中非标点字符;还包括其它拼写文字的字母,如希腊字母、俄文字母、阿拉伯文等。

所谓“Fuxi数字”指ASCII数字0~9 (\u0030 ~ \u0039)。

两个标识符相等,当且仅当它们编码长度相等,并且每个位置上的字母或数字均为相同的Unicode字符。

Unicode的合成字符同其分解形式是不等的,例如在Unicode文本中带锐音符号(acute)的拉丁字母A(á,\u00c1)可以等同于拉丁字母A(\u004)后紧跟一个不占空间的(non-spacing)锐音符号(\u0301),但在标识符中这两种形式是不相等的。

以下是几个标识符的例子:

MAX_VALUE 海创达 i3 String


§2.3.3 文字量
文字量(Literals)是基本类型、字符串以及空引用类型的值的文字表示。

<文字量>定义如下:

<整数量> 或
<浮点量> 或
<布尔量> 或
<字符量> 或
<字符串量> 或
<空类型量>

§2.3.3.1 整数量
整数量可以表示为十进制(Decimal)、16进制(Hexadecimal)和8进制(Octal)数。

<整数量>定义为:

<十进制量> 或
<十六进制量> 或
<八进制量>

<十进制量>定义为:

<十进制数值>[<整型后缀>]

<十六进制量>定义为:

<十六进制数值>[<整型后缀>]

<八进制量>定义为:

<八进制数值>[<整型后缀>]

<整型后缀>定义为以下之一:

SB sb S s I i L l UB ub US us U u UI ui UL ul

在整型数值的后面可以带一个整型后缀,用于限制该数值的类型;无后缀的整型数值缺省为int型,即32位带符号整数。整型后缀同数值类型的关系在以下表格中列出:

后 缀
类型

SB或sb
byte

S或s
short

I或i
int

L或l
long

UB或ub
ubyte

US或us
ushort

UI、U、ui或u
uint

UL或ul
ulong


十进制整数值要么是ASCII字符0,表示整数0,要么是一个非0的ASCII数字,后面可选择地跟一些ASCII数字0 ~ 9。十进制整数的形式化定义如下:

<十进制数值>定义为:

0 或
<非零十进制数字>{<十进制数字>}

<非零十进制数字>定义为:

1 2 3 4 5 6 7 8 9

<十进制数字>定义为:

0 或
<非零十进制数字>

十六进制数值是以ASCII字符0x或0X开头,后面紧跟1个或几个十六进制数字,可以表示正整数、0或负整数。十六进制数字中大于9的数字分别采用ASCII字母a ~ f 或者A ~ F来表示,字母的大小写与值无关。十六进制整数的形式化定义如下:

<十六进制数值>定义为:

0x<十六进制数字>{<十六进制数字>}
0X<十六进制数字>{<十六进制数字>}

<十六进制数字>定义为以下之一:

0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F

八进制数值是由ASCII数字0后跟1个或几个ASCII数字0 ~ 7构成,表示正整数、0或负整数。八进制数的定义如下:

<八进制数值>定义为:

0<八进制数字>{<八进制数字>}

<八进制数字>定义为以下之一:

0 1 2 3 4 5 6 7

八进制数值至少包含2个数字;0总是被认为是十进制数,0、00和0x0表示相同的数值0。

在进行词法分析的过程中,还应验证数值的合法性。例如,320sb就不是一个合法的整数量,因为byte型的数值范围是-128~127,而320不在之内。下表列出了各整数类型的取值范围:

类型
十进制数值范围
十六进制数值范围
八进制数值范围

byte
-128 ~ 127
0x80SB ~ 0x7FSB
0200SB ~ 0177SB

ubyte
0 ~ 255
0x00 ~ 0xffUB
0 ~ 0377UB

short
-32 768 ~ 32 767
0x8000S ~ 0x7FFFS
0100000S ~ 077777S

ushort
0 ~ 65 535
0x0000 ~ 0xFFFFUS
0 ~ 0177777US

int
-2147483648 ~ 2147483647
0x80000000 ~ 0x7fffffff
020000000000~017777777777

uint
0 ~ 4294967295
0x00000000ui~ 0xffffffffui
0 ~ 037777777ui

long
223372036854775808~ 9223372036854775807
0x8000000000000000L ~ 0x7fffffffffffffffL
01000000000000000000000L~
0777777777777777777777L

ulong
0 ~
18446744073709551615
0 ~
0xffffffffffffffffUL
0 ~
01777777777777777777777ul


§2.3.3.2 浮点量
浮点量是由以下部分组成的:整数部分、小数点、分数部分、指数部分和浮点后缀。指数部分(如果有的话),是由ASCII字母E或e后面跟一个带符号的整数构成。

一个最简单的浮点量是由一个数字(在整数部分或分数部分)和以下之一构成:小数点、指数或者浮点后缀;所有其它部分均为可选项。

如果浮点量的后缀是ASCII字符F或f,其类型float;否则为double型(其后可选带后缀D或d)。

<浮点量>定义为:

<数字串>.[<数字串>][<指数部分>][<浮点后缀>] 或
.[<数字串>][<指数部分>][<浮点后缀>] 或
<数字串><指数部分>[<浮点后缀>] 或
<数字串>[<指数部分>]<浮点后缀>

<数字串>定义为:

<数字>{<数字>}

<指数部分>定义为:

<指数指示符><带符号整数>

<指数指示符>定义为:

E 或
e

<带符号整数>定义为:

[<正负号>]<数字串>

<正负号>定义为:

+ 或
-

<数字>定义为以下之一:

0 1 2 3 4 5 6 7 8 9

<浮点后缀>定义为以下之一:

D d F f

最小的非0正float量为1.40239846e-45f;最大的正float量为3.40282347e+38f。最小的非0正double量为4.94065645841246544e-324;最大的正double量为1.79769313486231570e+308。

以下情况会导致编译错误:

浮点量太长,使得内部转换后成为IEEE 754标准中的无穷大;

非0浮点量太小,使得内部转换后成为0。

但如果内部转换后能获得一个正常浮点值的浮点量,将不出编译错误。

以下是一些float量的例子:

1e1f 2.f .3f 0f 3.14f 6.022137e+23f

以下是一些double量的例子:

1e1 2. .3 0.0 3.14 3.2e-8d 1e137

§2.3.3.3 布尔量
bool型有两个值,分别由关键字true和false来表示。布尔量总是bool型数据。

<布尔量>定义为以下之一:

true false

§2.3.3.4 字符量
字符量是由ASCII单引号(',\u0027)括起来的字符或转义系列。字符量总是字符型数据。

<字符量>定义为:

´<单字符>´ 或
´<转义系列>´

<单字符>定义为:

非 ´ 和 \ 的输入字符

按§2.1.4的定义ASCII字符CR和LF均不能作为输入字符,它们是行结束符。以下情况均视为语法错误:

在<单字符>后不是 ´;

<行结束符>出现在单引号之间,即出现在在开始 ´ 之后,或结束 ´ 之前。

以下是以下字符量的例子:

´a´
´\r´
´\n´
´\177´
´海´
´\u03a9´
´?´

值得注意的是,对Unicode转义系列的转换(§2.1.2)先于其它转义的转换,´\u000a´ 将是一个错误的字符量,因为词法转换的第1步就将\u000a转换成实际的换行符LF,LF不可出现在字符量中,正确的表示应该为´\n´;同样,´\u000d´ 应改为 ´\r´。

§2.3.3.5 字符串量
字符串量是由ASCII双引号括起来的零个或多个字符组成的系列。其中每个字符都可以采用转义系列来表示。
字符串量的类型总是String,字符串量也总是表示一个对String的实例的引用。

<字符串量>定义为:

"{<字符串字符>}"

<字符串字符>定义为:

非 " 和 \ 的输入字符
<转移系列>

§2.1.4的定义ASCII字符CR和LF均不能作为输入字符,它们是行结束符。<行结束符>出现在字符串量中将视为语法错误。对于一个过长的字符串量,可以表示成几个短些的字符串量,通过串并联运算符 + 连接起来的表达式。

以下是几个字符串量的例子:

""
"\""
"\n"
"这是一个字符串"
"这是一个" +
"两行字符串"

由于系统最早进行Unicode的转义处理,因此不能采用"\u000a"来表示包含一个ASCII字符LF的字符串量,因为\u000a会在词法转换(§2.1.2)的第1步就被转换成实际的字符LF而被分析为<行结束符>(§2.1.4),正确的形式应该为"\n";类似地,"\u000d"应表示为"\r"。

§2.3.3.6 字符和字符串量的转义系列
字符或字符串量的转义系列允许在字符或字符串量中使用ASCII单引号、双引号或反斜杠以及一些非图形(nongraphic)字符。

<转义系列>定义为以下之一:

\b /* \u0008 退格BS */
\t /* \u0009 水平制表符 HT */
\n /* \u000a 换行 LF */
\f /* \u000c 进表 FF */
\r /* \u000d 回车 CR */
\" /* \u0022 双引号 " */
\' /* \u0027 单引号 ' */
\\ /* \u005c 反斜杠 \ */
<八进制转移系列> /* \u0000 ~ \u00FF */

<八进制转移系列>定义为:

\<八进制数字>
\<八进制数字><八进制数字>
\<零到三><八进制数字><八进制数字>

<八进制数字>定义为:

<零到三> 或
4 5 6 7

<零到三>定义为:

0 1 2 3

如果ASCII反斜杠后面不是紧跟ASCII字符b、t、n、f、r、"、'、0、1、2、3、4、5、6、7将视为语法错误。八进制转义系列是为了保持和C等语言的兼容性,八进制转义系列只能表示\u0000到\u00FF之间的字符。

§2.3.3.7 空类型量
空类型(Null type)只有一个值,即由关键字null表示的空引用(Null reference)。空类型量(Null literal)也总是空类型。

<空类型量>定义为:

null

§2.3.4 分隔符
以下17个由ASCII字符组成符号或符号系列,称为Fuxi的分隔符(Separator)。

<分隔符>定义为以下之一:

, . : ; .. { } [ ] ( ) = <- -> # @ ://

§2.3.5 运算符
以下35个符号为Fuxi的运算符(Operator)。

<运算符>定义为以下之一:

+ - * / %
~ & | ^
<< >> >>>
&& || !
> >= < <= == !=
:= ++ --
+= -= *= /= %=
~~ &= |= ^=
<<= >>=

 
   
   
   
 

友情链接:深圳市触品科技有限公司 www.touchbuy.cn

友情链接:深圳市趋高智能系统有限公司 www.hitrend.com

友情链接:深圳市触品便利店有限公司 www.touchstore.cn

关于我们  联系我们  加入我们

©2006-2019 fuxi.org, 版权所有. 粤ICP备11003046号