第8章
语言定义
air语言是C语法系的编程语言,提供面向对象、函数式、模板等高级语言功能。
air语言是C语法系的编程语言,提供面向对象、函数式、模板等高级语言功能。
语法使用非严格的EBNF语法描述。
文件单元
FileUnit = PkgDef (ImportDef) Decl*
包定义
PkgDef = package ID (.ID)*
依赖导入(可选)
ImportDef = 'import' STRING as ID; |'{' (STRING as ID; )* '}'
声明定义
Decl = ScopeDecl | VarDecl | FuncDecl | EnumDecl | StructDecl | UnionDecl | InterfaceDecl | ClassDecl | EntrustDecl | ~
表达式
Exp = BaseExp | DotExp | UnaryExp | BinaryExp | TernaryExp | NewExp | PriorityExp
基础表达式
BaseExp = IDExp | ConstExp | CallExp | ArrarExp | ThisExp | SuperExp
IDExp = ID
ConstExp = c
CallExp = ID '(' ArgList')'
ArrarExp = ID '[' Exp ']'
ThisExp = 'this'
SuperExp = 'super'
成员访问表达式
DotExp = BaseExp ( '.' BaseExp)* //BaseExp不得是ConstExp
一元表达式
UnaryExp = UnaryOP BaseExp
UnaryOP = '-' | '+' | '--' | '++' | '~' | '!'
二元表达式
BinaryExp = Exp BinaryOP Exp
BinaryOP = '+' | '-' | '*' | '/' | '%' |
'&' | '|' | '&&' | '||' |
'<<' | '>>' | '>>>' |
'<' | '>' | '<=' | '>=' |
'==' | '!=' | '=' |
三元表达式
TernaryExp = Exp '?' Exp ':' Exp
括号表达式
PriorityExp = '(' Exp ')'
作用域声明
ScopeDecl = ( 'public' | 'protected' | 'private' ) ':'
变量声明
VarDecl = Scope Type 'id' [=initExp] ';'
Scope = ['public' | 'protected' | 'private'| 'extern' | 'static']
Type = ['const' ] 'id'( '.' 'id')*
代理变量
Scope Type 'id''(' [ arglist] ')' 'delegate' ';'
闭包变量
Scope Type 'id''(' [ arglist] ')' 'closure' ';'
函数申明
VarDecl = Scope Type 'id''(' [ arglist] ')'[@override] [@cfun] [const] [final] (';' | funbody )
arglist = argitem (',' argitem)*
argitem = type ['id']
funbody = BlkState
BlkState = '{' [Statement] '}'
Statement = ( BlkState | ExpState | IfState | ElseifState |
ElseState | SwitchState | ForState | DoState |
WhileState | GotoState | BreakState | ContinueState |
ReturnState )*
TypeDecl = EnumDecl | StructDecl | UnionDecl |EntrustDecl
FuncDecl = Type 'id''(' [ arglist] ')' '=' Serial
Serial = 'u32'
枚举声明
EnumDecl = 'enum' id [: BaseType]'{' EnumItem* '}'
BaseType = 基本整数类型
EnumItem = 'id'[=initExp] ','
每一个文件都必须定义一个作用域名,其他内容在此作用域定义。
生成的声明符号都在该作用域内,只能通过该作用域才能访问代码文件中声明的符号内容。
package pkg.pkg2;
Import file=“dir/file.ext”;
Import file2=“dir/file2.ext”;
或者
Import{
file=“dir/file.ext” ;
file2=“dir/file2.ext”;
}
enum name : int32{
item=0,
item2=23,
…
}
Struct name{
Int32 i32;
Union{
Int32 s32;
Flt32 f32;
}
}
Union name{
Int32 s32;
Flt32 f32;
Struct{…}
}
Interface IFather{
void eat(int32 arg);
}
Interface IFather2{
void say(int32 arg);
}
Interface IChild :[ IFather,IFather2 ]{
void walk(int32 arg);
}
Class Parent {
Private:
Int32 mI32;
Public Flt32 mF32;
Public:
Void print(){}
Protected void toString(){}
Virtual void vfun()=0;
}
Class child: Parent :[ IChild ]{
void eat(int32 arg) @override{}
void say(int32 arg) @override{}
void walk(int32 arg) @override{}
void vfun()@override{}
}
airlang 的关键字分为两种:普通关键字,宏关键字。 两者差别不大,但是宏关键字有特殊的标记作用,一般用于注解一些信息。
关键字 | 注解 |
---|---|
@file | 代码中获取文件的名称字符串 |
@line | 代码中获取代码所作行号数字 |
@func | 代码中获取函数声明字符串 |
@debug | 用于标记只在debug标志下启用的代码 |
@NotNulptr | 用于标记需要检查函数的指针参数非空 |
@override | 标记非静态成员函数是重写父类的函数 |
固定位宽类型关键字 | 注解 | 位宽(bit) |
---|---|---|
void | 空,一般用于表示无返回值 | 0 |
bool | 布尔类型 | 8 |
flt32 | 32位单精度浮点 | 32 |
flt64 | 64位双精度浮点 | 32 |
int8 | 8位有符号整数 | 8 |
int16 | 8位有符号整数 | 16 |
int32 | 8位有符号整数 | 32 |
int64 | 8位有符号整数 | 64 |
uint8 | 8位无符号整数 | 8 |
uint16 | 16位无符号整数 | 16 |
uint32 | 32位无符号整数 | 32 |
uint64 | 64位无符号整数 | 64 |
char | 字符 | 8 |
可变位宽类型的位宽由编译的目标CPU架构有关。
可变位宽类型关键字 | 注解 | CPU32 | CPU64 |
---|---|---|---|
sint | 有符号整数 | 32 | 64 |
uint | 无符号整数 | 32 | 64 |
uintptr | 指针 | 32 | 64 |
cstring | 字符串指针 | 32 | 64 |
修饰关键字 | 注解 |
---|---|
static | 静态 |
public | 完全公开的 |
protected | 对部分成员公开的 |
private | 私有的 成员 |
const | 常量化,只读 |
friend | 友元定义 |
分支关键字 | 注解 |
---|---|
if | 比较分支 |
elsif | 次比较分支 |
else | 比较默认分支 |
for | 循环 |
foreach | 循环 |
while | 循环 |
do | 循环 |
break | 跳出循环 |
continue | 继续下一轮循环 |
goto | 跳转到标签 |
return | 函数返回 |
类型定义关键字 | 注解 |
---|---|
enum | 枚举 |
struct | 结构体 |
union | 联合体 |
interface | 接口 |
class | 类 |
entrust | 委托指针 |
其他关键字 | 注解 |
---|---|
false | |
true | |
nullptr | |
this | |
super |
成员访问操作符的优先级最高。
成员访问操作符 | 优先级 | 注解 |
---|---|---|
. | 0 | 成员访问 |
.? | 0 | 带null检查的成员访问 |
一元操作符优先级一致,主要查看其声明的先后顺序。
一元操作符 | 优先级 | 注解 |
---|---|---|
~ | -10 | 按位取反 |
! | -10 | 逻辑取反 |
- | -10 | 符号取反 |
+ | -10 | 取绝对值 |
++ | -10 | 自增 |
-- | -10 | 自减 |
在语法解析表达式中,二元表达式最复杂的。
二元操作符 | 优先级 | 注解 |
---|---|---|
* | -20 | 乘运算操作符 |
/ | -20 | 除运算操作符 |
% | -20 | 模运算操作符 |
+ | -30 | 加运算操作符 |
- | -30 | 减运算操作符 |
<< | -40 | 左移操作符 |
>> | -40 | 逻辑右移操作符 |
>>> | -40 | 算术右移操作符 |
< | -50 | 小于操作符 |
<= | -50 | 小于等于操作符 |
> | -50 | 大于于操作符 |
>= | -50 | 大于等于操作符 |
== | -60 | 等于操作符 |
!= | -60 | 不等于操作符 |
& | -70 | 位与操作符 |
^ | -71 | 位异或操作符 |
| | -72 | 位或操作符 |
&& | -80 | 逻辑与操作符 |
|| | -81 | 逻辑或操作符 |
三元操作符主要用于比较赋值、简单的比较分支操作。
三元操作符 | 优先级 | 注解 |
---|---|---|
? : | -90 |
赋值类操作符的优先级一致,优先级最低。
赋值操作符 | 优先级 | 注解 |
---|---|---|
= | -100 | 赋值操作符 |
*= | -100 | 乘运算复合赋值操作符 |
/= | -100 | 除运算复合赋值操作符 |
%= | -100 | 模运算复合赋值操作符 |
+= | -100 | 加运算复合赋值操作符 |
-= | -100 | 减运算复合赋值操作符 |
&= | -100 | 位与运算复合赋值操作符 |
= | -100 | 位或运算复合赋值操作符 |
^= | -100 | 位异或运算复合赋值操作符 |
~= | -100 | 位取反运算复合赋值操作符 |
<<= | -100 | 左移运算复合赋值操作符 |
>>= | -100 | 逻辑右移运算复合赋值操作符 |
>>>= | -100 | 算术右移运算复合赋值操作符 |
括号表达式中的括号操作符,用于提升表达式的优先级,在算符优先解析算法,该系列是作为基本表达式进行解析的。
括号操作符 | 优先级 | 注解 |
---|---|---|
() | -10 | 括号操作符 |
[] | -10 | 数组下标 |
cast | -10 | 静态类型转换 |
dyn_cast | -10 | 动态类型转换 |
() | -10 | 函数调用 |
固定位宽类型 | 注解 | 位宽(bit) |
---|---|---|
void | 空,一般用于表示无返回值 | — |
bool | 布尔类型 | 8 |
flt32 | 32位单精度浮点 | 32 |
flt64 | 64位双精度浮点 | 32 |
int8 | 8位有符号整数 | 8 |
int16 | 8位有符号整数 | 16 |
int32 | 8位有符号整数 | 32 |
int64 | 8位有符号整数 | 64 |
uint8 | 8位无符号整数 | 8 |
uint16 | 16位无符号整数 | 16 |
uint32 | 32位无符号整数 | 32 |
uint64 | 64位无符号整数 | 64 |
char | 字符 | 8 |
可变位宽类型的位宽由编译的目标CPU架构有关。
可变位宽类型 | 注解 | CPU32 | CPU64 |
---|---|---|---|
sint | 有符号整数 | 32 | 64 |
uint | 无符号整数 | 32 | 64 |
uintptr | 指针 | 32 | 64 |
cstring | 字符串指针 | 32 | 64 |
枚举定义只能是定义整数类的值,其占用的字节数、有无符号性,通过基类标识指定。
如下所示:
enum Color:uint32{
Red,
Black,
}
结构体在airlang中是值类型,不会进入GC系统,除通过API分配独立的堆内存。
一般用于构成类中的共同属性。
struct Vec2{
int32 x;
int32 y;
}
struct Vec3 :Vec2{
int32 z;
}
union Int32{
int32 i32;
struct{
int8 [4] v4;
}
}
interface IEvent{
void eat();
}
class Parent{
int32 i32;
void doing(){}
}
class Child :Parent <IEvent>{
int64 i64;
void eat()@override{}
}
entrust Func = void (int32,int64)@clang;