返回列表

帖子详情

经验分享

Y语言-Y++基础语法说明

作者:管理员发布:2026-08-11 01:42:35浏览:1
# Y++ 基础语法说明

本文说明 D2D 项目中最常用的 Y++ 基础语法:变量、常量、数据类型、类型转换、运算符、数组、函数、作用域、条件和循环。支持库命令、窗口组件、`.yt``.ypi``.ypp` 的专门写法请继续查看同目录对应文档。

## 1. 源文件与代码结构

常用文件:

| 文件 | 用途 |
|---|---|
| `source/main.yc` | 窗口事件和主要业务代码 |
| `source/globals.yc` | 全工程共享变量,项目自动引用 |
| `source/constants.yc` | 全工程共享常量,项目自动引用 |
| `source/结构体文件/*.yt` | 自定义数据类型和结构体 |
| `source/类文件/*.ypp` | 自写类、属性、方法和继承 |
| `source/API声明/*.ypi` | DLL、Windows API 和第三方 C 接口声明 |

语句通常一行一条;代码块使用英文半角 `{``}`

```yc
函数 演示() {
    整数 数量 = 10
    输出(数量)
}
```

错误写法:

```yc
// 错误:使用中文全角括号和花括号可能造成解析失败
函数 演示(整数 数量){
    输出(数量)
```

应使用 IDE 自动转换后的英文半角标点。

## 2. 标识符与注释

变量、函数、类型、类和方法可使用中文名、英文字母、数字及下划线,但名称不能以数字开头,也不能与关键字冲突。

```yc
整数 用户数量 = 0
文本 user_name = "张三"
逻辑 已登录 = 假
```

单行注释:

```yc
// 这是一行注释
整数 次数 = 3 // 行尾注释
```

多行注释:

```yc
/*
这里是多行说明。
可用于暂时屏蔽多行代码。
*/
```

错误写法:

```yc
整数 2号用户 = 0     // 错误:数字开头
整数 如果 = 1        // 错误:使用关键字作为名称
```

## 3. 变量定义

基本格式:

```text
类型 变量名
类型 变量名 = 初始值
```

常见变量:

```yc
整数 年龄 = 18
短整数 状态码 = 200
长整数 文件大小 = 4294967296
小数 温度 = 36.5
单浮点 比例 = 0.75
双浮点 金额 = 1234.56
文本 姓名 = "张三"
逻辑 已完成 = 假
字节 一个字节 = 65
字节集 文件数据 = 创建字节集(1024)
通用 任意值 = "开始是文本"
```

先声明后赋值:

```yc
整数 总数
总数 = 10
总数 = 总数 + 5
```

一次只声明一个名称,最利于补全、错误定位和 AI 生成:

```yc
整数 左 = 10
整数 上 = 20
整数 宽 = 800
整数 高 = 600
```

错误写法:

```yc
年龄 整数 = 18       // 不推荐:统一使用“类型 名称”
整数 = 18            // 错误:缺少变量名
整数 年龄 = "十八"   // 错误:文本不能直接赋给整数
```

需要把文本年龄变成整数时显式转换:

```yc
整数 年龄 = 到整数("18")
```

## 4. 基本数据类型怎么选择

| 类型 | 常见用途 | 示例 |
|---|---|---|
| `整数` | 计数、索引、状态码 | `整数 行 = 0` |
| `短整数` | 明确需要较小整数的原生接口 | `短整数 端口片段 = 80` |
| `长整数` | 文件大小、时间戳、句柄、地址 | `长整数 句柄 = 0` |
| `小数` / `双浮点` | 金额、坐标、测量值 | `小数 单价 = 9.9` |
| `单浮点` | 第三方接口明确要求 float | `单浮点 透明度 = 0.5` |
| `文本` | Unicode 字符串 | `文本 标题 = "主页"` |
| `逻辑` | 真/假状态 | `逻辑 运行中 = 真` |
| `字节` | 单个 0~255 数据 | `字节 标记 = 255` |
| `字节集` | 文件、图片、网络二进制 | `字节集 图片 = 读文件(路径)` |
| `通用` | 类型不固定的数据 | `通用 值 = 123` |

能确定类型时优先使用明确类型。`通用` 适合动态数据,但会降低类型检查和成员补全的准确性。

## 5. 文本与转义

文本使用英文双引号:

```yc
文本 标题 = "Y++ IDE"
文本 路径 = "D:\\data\\config.json"
文本 换行内容 = "第一行\n第二行"
文本 制表内容 = "名称\t数量"
文本 引号内容 = "他说:\"你好\""
```

Windows 路径也可使用 `/`,可减少转义:

```yc
文本 路径 = "D:/data/config.json"
```

拼接不同类型时显式转换:

```yc
文本 姓名 = "张三"
整数 年龄 = 18
文本 简介 = 姓名 + ",年龄=" + 到文本(年龄)
```

错误写法:

```yc
文本 路径 = "D:\data\new" // 错误风险:\n 会被解释成换行
文本 简介 = "年龄=" + 年龄 // 不要依赖隐式转换
```

## 6. 类型转换与类型判断

常用转换命令:

```yc
整数 数量 = 到整数("123")
小数 单价 = 到小数("19.95")
文本 数量文本 = 到文本(数量)
逻辑 开关 = 到逻辑(1)
字节集 数据 = 到字节集("你好")
文本 当前类型 = 取类型(数量)
```

组合示例:读取文本框并校验:

```yc
函数 保存按钮.单击(整数 X, 整数 Y) {
    文本 原始年龄 = 年龄输入框.标题
    整数 年龄 = 到整数(原始年龄)
    如果 (年龄 <= 0) {
        输出("年龄必须是正整数")
        返回
    }
    输出("保存年龄:" + 到文本(年龄))
}
```

小数转整数会去掉小数部分:

```yc
整数 a = 到整数(3.9)   // 结果为 3
整数 b = 到整数(-3.9)  // 向零截断
```

错误写法:

```yc
整数 数量 = "123"          // 错误:没有转换
整数 数量 = 到文本(123)     // 错误:转换结果仍是文本
小数 金额 = 到整数("9.9")  // 结果先被截断,不符合金额用途
```

正确写法:

```yc
整数 数量 = 到整数("123")
小数 金额 = 到小数("9.9")
```

## 7. 常量

局部常量:

```yc
函数 计算() {
    常量 整数 每页数量 = 50
    输出(每页数量)
}
```

`source/constants.yc` 中的项目常量:

```yc
全局常量 文本 程序版本 = "2.6.0"
全局常量 整数 默认端口 = 8080
全局常量 逻辑 启用日志 = 真
```

其它文件使用项目全局常量:

```yc
输出("版本=" + #程序版本)
整数 端口 = #默认端口
```

错误写法:

```yc
#默认端口 = 9000 // 错误:常量不能重新赋值
输出(默认端口)   // 跨文件项目常量漏写 #
```

## 8. 局部变量、全局变量和作用域

函数或方法内部定义的是局部变量,只在当前代码块所属函数或方法中使用:

```yc
函数 计算总价(整数 数量, 小数 单价) 小数 {
    小数 总价 = 数量 * 单价
    返回(总价)
}
```

`source/globals.yc` 中定义全局变量:

```yc
整数 登录次数 = 0
逻辑 程序运行中 = 真
文本 当前用户 = ""
学生 学生列表[]
```

其它 `.yc``.ypp` 文件可直接使用这些全局变量。

方法参数也属于当前方法的局部变量:

```ypp
类 日志器 {
    方法 写入(文本 内容, 整数 级别) {
        // 内容、级别在本方法内应参与代码补全
        输出("[" + 到文本(级别) + "] " + 内容)
    }
}
```

错误写法:

```yc
函数 A() {
    整数 临时值 = 10
}

函数 B() {
    输出(临时值) // 错误:A 的局部变量在 B 中不可见
}
```

## 9. 赋值与运算符

```yc
整数 a = 10
整数 b = 3

整数 和 = a + b
整数 差 = a - b
整数 积 = a * b
整数 商 = a / b
整数 余数 = a % b

a += 2
a -= 1
a *= 3
a /= 2
a++
b--
```

比较与逻辑:

```yc
逻辑 相等 = (a == b)
逻辑 不等 = (a != b)
逻辑 大于 = (a > b)
逻辑 范围内 = (a >= 1 && a <= 100)
逻辑 任一成立 = (a == 0 || b == 0)
逻辑 未完成 = !已完成
```

不要把比较 `==` 写成赋值 `=`

```yc
如果 (状态 = 1) { }  // 错误:条件中误用了赋值
如果 (状态 == 1) { } // 正确:比较是否相等
```

复杂表达式用括号明确顺序:

```yc
小数 平均值 = (总分 + 加分) / 人数
逻辑 可提交 = 已登录 && (数量 > 0) && (金额 <= 余额)
```

## 10. 一维数组

强类型数组:

```yc
整数 分数[] = [90, 85, 100]
文本 姓名[] = ["张三", "李四"]
学生 学生列表[]
```

固定初始容量或长度提示:

```yc
多线程 dxc[10] = []
```

访问下标从 `0` 开始:

```yc
输出(分数[0])
分数[1] = 88
数组添加(姓名, "王五")
整数 人数 = 数组长度(姓名)
```

遍历:

```yc
整数 i = 0
当 (i < 数组长度(姓名)) {
    输出(到文本(i) + ":" + 姓名[i])
    i++
}
```

错误写法:

```yc
输出(姓名[2]) // 如果当前只有两个元素,下标越界
姓名[0] = 123 // 错误:文本数组元素不能直接放整数
```

## 11. 二维、三维及嵌套数组

```yc
整数 表格[][] = [[1, 2], [3, 4]]
输出(表格[0][1])

文本 立方体[][][] = [
    [["A", "B"], ["C", "D"]]
]
输出(立方体[0][1][0])
```

自定义类型数组可继续访问成员:

```yc
学校 我校
输出(我校.班级列表[0].成员[0].姓名)
输出(我校.班级列表[0].成员[0].家庭住址.门牌坐标.X)
```

类型数组元素里包含类对象时也可继续调用方法:

```yc
多线程 dxc[10] = []
dxc[0].主OL.我是ola第一个方法("任务一")
```

这类写法要求每一层都有明确类型:`dxc``多线程[]``主OL``ola`、目标方法属于 `ola`。若中间一层声明成 `通用`,IDE 无法可靠推出后续成员。

## 12. 条件语句

```yc
如果 (分数 >= 90) {
    输出("优秀")
} 否则如果 (分数 >= 60) {
    输出("及格")
} 否则 {
    输出("不及格")
}
```

嵌套条件:

```yc
如果 (已登录) {
    如果 (权限级别 >= 10) {
        输出("管理员")
    } 否则 {
        输出("普通用户")
    }
}
```

错误写法:

```yc
如果 分数 >= 60 {       // 错误:条件缺少括号
    输出("及格")
}
```

## 13. 循环、跳出和继续

`当` 循环:

```yc
整数 i = 0
当 (i < 10) {
    i++
    如果 (i == 3) {
        继续
    }
    如果 (i > 8) {
        跳出
    }
    输出(i)
}
```

循环必须保证条件最终会改变:

```yc
整数 i = 0
当 (i < 10) {
    输出(i)
    // 错误:漏写 i++,将形成无限循环
}
```

## 14. 函数定义、参数和返回值

无参数、无返回值:

```yc
函数 显示欢迎() {
    输出("欢迎使用 Y++")
}

显示欢迎()
```

带参数:

```yc
函数 显示用户(文本 姓名, 整数 年龄) {
    输出(姓名 + "," + 到文本(年龄) + "岁")
}

显示用户("张三", 18)
```

带返回值:

```yc
函数 计算面积(整数 宽, 整数 高) 整数 {
    返回(宽 * 高)
}

整数 面积 = 计算面积(800, 600)
```

提前返回:

```yc
函数 保存(文本 路径) 逻辑 {
    如果 (路径 == "") {
        输出("路径不能为空")
        返回(假)
    }
    写文件(路径, "内容")
    返回(真)
}
```

错误写法:

```yc
函数 相加(整数 a, 整数 b) 整数 {
    输出(a + b)
} // 错误:声明返回整数但没有返回值

相加("1", "2") // 错误:参数类型不匹配
```

## 15. 窗口事件中的变量

事件参数由组件事件签名决定:

```yc
函数 按钮1.单击(整数 X, 整数 Y) {
    文本 坐标 = 到文本(X) + "," + 到文本(Y)
    输出(坐标)
}
```

不要自行复制另一种组件的参数签名,应从设计器事件面板生成:

```yc
// 错误示意:当前组件的单击事件可能并不提供“行、列”
函数 按钮1.单击(整数 行, 整数 列, 文本 内容) {
}
```

## 16. 自定义数据类型变量

`.yt`

```yt
地址 {
    文本 省
    文本 市
}

学生 {
    文本 姓名
    整数 年龄
    地址 家庭住址
}
```

`.yc`

```yc
学生 张三
张三.姓名 = "张三"
张三.年龄 = 18
张三.家庭住址.省 = "广东省"
张三.家庭住址.市 = "深圳市"
输出(张三.家庭住址.市)
```

错误写法:

```yc
张三.家庭地址.市 = "深圳市" // 错误:声明的成员叫“家庭住址”
```

## 17. 自写类变量和方法参数

`.ypp`

```ypp
类 订单服务 {
    文本 当前用户 = ""

    方法 设置用户(文本 用户名) {
        当前用户 = 用户名
    }

    方法 计算金额(整数 数量, 小数 单价) 小数 {
        小数 金额 = 数量 * 单价
        返回(金额)
    }
}
```

`.yc`

```yc
订单服务 服务
服务.设置用户("张三")
小数 金额 = 服务.计算金额(3, 19.9)
```

方法形参 `用户名``数量``单价` 只在各自方法体内有效,并应像局部变量一样参与代码补全。

## 18. 通用类型的使用边界

```yc
通用 值 = 123
输出(取类型(值))
值 = "文本"
输出(取类型(值))
```

不要用 `通用` 代替本来明确的自定义类型:

```yc
通用 学生值
// 学生值.姓名  // IDE 无法保证成员类型和补全

学生 学生值2
学生值2.姓名 = "张三"
```

## 19. 常见错误对照

| 错误写法 | 原因 | 正确写法 |
|---|---|---|
| `整数 = 1` | 缺少变量名 | `整数 数量 = 1` |
| `整数 数量 = "1"` | 类型不同 | `整数 数量 = 到整数("1")` |
| `如果 (a = 1)` | 把赋值写成比较 | `如果 (a == 1)` |
| `输出(未声明变量)` | 名称不在作用域 | 先声明或放入 `globals.yc` |
| `数组[数组长度(数组)]` | 下标越界 | 最后一个下标是长度减一 |
| `#常量 = 新值` | 常量不可修改 | 改用全局变量 |
| `对象.不存在成员` | 名称或类型链错误 | 按 `.yt`/`.ypp` 声明逐层访问 |
| `类名 对象(参数)` | 当前声明语法不接收该写法 | 先 `类名 对象`,再调用初始化方法 |
| `用户 a = new 用户()` | 混入其它语言语法 | `用户 a` |
| 方法参数在方法外使用 | 已离开参数作用域 | 传给其它函数或保存到类属性 |

## 20. 综合示例

`source/types/订单.yt`

```yt
订单项 {
    文本 商品名
    整数 数量
    小数 单价
}

订单数据 {
    文本 编号
    订单项 项目[]
}
```

`source/classes/订单计算器.ypp`

```ypp
类 订单计算器 {
    方法 计算总额(订单数据 订单) 小数 {
        小数 总额 = 0
        整数 i = 0
        当 (i < 数组长度(订单.项目)) {
            总额 += 订单.项目[i].数量 * 订单.项目[i].单价
            i++
        }
        返回(总额)
    }
}
```

`source/main.yc`

```yc
函数 计算按钮.单击(整数 X, 整数 Y) {
    订单数据 订单
    订单.编号 = "NO-1001"

    订单项 商品
    商品.商品名 = "键盘"
    商品.数量 = 到整数(数量输入框.标题)
    商品.单价 = 到小数(单价输入框.标题)
    数组添加(订单.项目, 商品)

    订单计算器 计算器
    小数 总额 = 计算器.计算总额(订单)
    结果标签.标题 = "订单" + 订单.编号 + ",总额=" + 到文本(总额)
}
```

这个示例同时使用了事件参数、局部变量、文本转整数、小数转换、自定义数据类型、类型数组、自写类方法、循环和返回值。

评论