# 语法检查功能说明

## 概述

ycIDE 语法检查功能由两个核心组件组成：

1. **词法分析器（Lexer）** - 将源代码分解为Token序列
2. **语法分析器（Parser）** - 检查Token序列是否符合易语言语法规则

## 文件结构

```
ycIDE/
├── Lexer.h          # 词法分析器头文件
├── Lexer.cpp        # 词法分析器实现
├── Parser.h         # 语法分析器头文件
└── Parser.cpp       # 语法分析器实现
```

## 词法分析器（Lexer）

### 主要功能

- 识别易语言关键字（如果、循环、变量等）
- 识别数据类型（整数型、文本型等）
- 识别标识符（变量名、函数名）
- 识别字面量（数字、字符串）
- 识别运算符（+、-、×、÷、=、>、<等）
- 识别分隔符（括号、逗号等）
- 识别注释（' 和 //）
- 支持中文字符

### 使用示例

```cpp
#include "Lexer.h"

// 创建词法分析器
Lexer lexer;

// 设置源代码
std::wstring code = L"变量 x 整数型 = 100";
lexer.SetSource(code);

// 逐个获取Token
Token token = lexer.NextToken();
while (token.type != TokenType::EOF_TOKEN) {
    // 处理Token
    std::wcout << token.GetTypeName() << L": " << token.value << std::endl;
    token = lexer.NextToken();
}

// 或者一次性扫描所有Token
lexer.Reset();
std::vector<Token> tokens = lexer.ScanAll();
```

### Token类型

- **关键字**：`KEYWORD_IF`, `KEYWORD_WHILE`, `KEYWORD_VAR`, `KEYWORD_SUB`等
- **数据类型**：`TYPE_INT`, `TYPE_TEXT`, `TYPE_BOOL`等
- **标识符**：`IDENTIFIER`
- **字面量**：`NUMBER`, `STRING`
- **运算符**：`OP_PLUS`, `OP_MINUS`, `OP_EQ`等
- **分隔符**：`LPAREN`, `RPAREN`, `COMMA`等
- **其他**：`COMMENT`, `NEWLINE`, `EOF_TOKEN`, `ERROR`

## 语法分析器（Parser）

### 主要功能

- 构建抽象语法树（AST）
- 检测语法错误
- 验证语句结构
- 支持错误恢复

### 支持的语法结构

#### 声明
- 变量声明：`变量 x 整数型 = 0`
- 常量声明：`常量 PI 小数型 = 3.14`
- 数组声明：`变量 arr 整数型[10]`
- 子程序声明：`子程序 函数名 返回类型`

#### 语句
- 赋值语句：`x = 100`
- 如果语句：`如果(条件) ... 否则 ...`
- 循环语句：`判断循环首(条件) ...`
- 计次循环：`计次循环首(i, 1, 10, 1) ...`
- 返回语句：`返回(值)`
- 跳出/继续循环：`跳出循环`, `继续循环`

#### 表达式
- 算术运算：`a + b`, `x × y`, `m ÷ n`
- 比较运算：`a > b`, `x = y`, `m ≠ n`
- 逻辑运算：`a 并且 b`, `x 或者 y`, `非 z`
- 函数调用：`函数名(参数1, 参数2)`
- 数组访问：`arr[index]`

### 使用示例

```cpp
#include "Parser.h"

// 创建语法分析器
Parser parser;

// 方式1：解析并构建AST
std::wstring code = L"变量 x 整数型 = 100";
auto ast = parser.Parse(code);

// 检查错误
if (parser.HasErrors()) {
    for (const auto& error : parser.GetErrors()) {
        std::wcout << L"错误[" << error.line << L":" << error.column << L"]: ";
        std::wcout << error.message << std::endl;
    }
}

// 方式2：仅检查语法（不构建AST，性能更好）
std::vector<SyntaxError> errors = parser.CheckSyntax(code);
for (const auto& error : errors) {
    std::wcout << L"语法错误：" << error.message << std::endl;
}
```

### AST节点类型

- **程序结构**：`PROGRAM`, `SUBROUTINE`
- **声明**：`VAR_DECL`, `CONST_DECL`
- **语句**：`ASSIGN_STMT`, `IF_STMT`, `WHILE_STMT`, `FOR_STMT`, `RETURN_STMT`
- **表达式**：`BINARY_EXPR`, `UNARY_EXPR`, `LITERAL_EXPR`, `IDENTIFIER_EXPR`, `CALL_EXPR`

## 集成到编辑器

### 实时语法检查

在YiEditor中集成实时语法检查：

```cpp
// 在文本变化时调用
void OnTextChanged() {
    std::wstring code = GetEditorText();
    
    Parser parser;
    auto errors = parser.CheckSyntax(code);
    
    // 清除旧的错误标记
    ClearErrorMarkers();
    
    // 添加新的错误标记
    for (const auto& error : errors) {
        AddErrorMarker(error.line, error.column, error.message);
    }
    
    // 刷新显示
    InvalidateRect(hWnd, NULL, FALSE);
}
```

### 显示错误提示

```cpp
void DrawErrorMarkers(HDC hdc) {
    for (const auto& error : currentErrors) {
        // 在编辑器中绘制波浪下划线
        DrawWavyUnderline(hdc, error.line, error.column);
        
        // 鼠标悬停时显示错误消息
        if (IsMouseHover(error.line, error.column)) {
            ShowTooltip(error.message);
        }
    }
}
```

## 测试程序

运行 `test_syntax.cpp` 来测试词法和语法分析器：

```bash
# 编译测试程序（需要先在VS中将Lexer.cpp和Parser.cpp加入项目）
# 然后运行测试
./test_syntax.exe
```

测试程序包含：
1. 词法分析器测试 - 显示Token扫描结果
2. 语法分析器测试 - 显示AST树结构
3. 语法检查测试 - 显示错误检测结果

## 下一步工作

### 立即可做
1. 在ycIDE项目文件中添加Lexer.cpp和Parser.cpp
2. 编译并运行test_syntax.cpp验证功能
3. 在YiEditor.cpp中集成语法检查

### 后续优化
1. 完善错误恢复机制
2. 添加更多语法规则支持
3. 优化性能（大文件处理）
4. 添加语义分析（类型检查、作用域检查）
5. 实现代码补全提示
6. 支持增量解析（只解析修改的部分）

## 注意事项

1. **字符编码**：所有代码使用UTF-16（wstring），确保正确处理中文
2. **性能**：对于大文件，考虑使用增量解析或后台线程
3. **错误提示**：提供友好的中文错误消息
4. **扩展性**：设计允许后续添加新的语法规则

## 常见问题

**Q: 如何添加新的关键字？**
A: 在Lexer.cpp的GetKeywordType函数中添加映射关系

**Q: 如何添加新的语法规则？**
A: 在Parser.cpp中添加相应的Parse方法

**Q: 性能如何优化？**
A: 1) 使用增量解析 2) 缓存解析结果 3) 后台线程处理

**Q: 如何调试语法分析器？**
A: 使用test_syntax.cpp，查看Token序列和AST树结构
