C++ 实战项目 · 从零造一门语言

MiniTurtle

用 C++ 从零写一台海龟绘图脚本语言解释器——词法分析、语法分析、抽象语法树、解释执行、海龟画布,一条流水线全打通。你写的程序,能让海龟在屏幕上画出正方形、六边形、螺旋,甚至一棵分形树。

解释器 / Interpreter 词法 → 语法 → AST → 执行 递归 · 分形 C++17 · 零依赖
minturtle — 终端
$ ./minturtle
# 例4 分形树:过程 + 递归(下面是终端真实输出)
*  *   *  *
* **   ** *
***     ***
*     **     **     *
*    *       *    *
*    *       *    *
*****   *       *   *****
     ** *       * **
      ***       ***
        *       *
         *     *
          *   *
           * *
            *
全部示例运行完成。
01 / PLAYGROUND

在浏览器里,跑一台迷你海龟解释器

选了例子的源码,点「运行」——海龟真的会走起来、画出图形。这就是这台解释器的核心魅力:写下指令,立刻看见效果。

说明:这里的画布是同一套解释器语义的前端复刻(按屏幕像素缩放),方便在网页里即时看效果;真实程序是命令行程序,输出是终端字符画——见下面「跑起来」。

examples / 当前程序
参数调节 · 拖动滑块看图形变化
02 / PIPELINE

一台解释器是怎么跑起来的

从「一段文字」到「一幅画」,源码经过 5 个阶段。每一段都是可单独实现的模块,这正是本项目适合当 C++ 实战练习的原因。

STAGE 01

词法分析 Lexer

把源码字符串逐字符切成带类型的 Token。

main.cpp / token.hpp / lexer.cpp
STAGE 02

语法分析 Parser

递归下降,把 Token 拼成抽象语法树。

ast.hpp / parser.cpp
STAGE 03

抽象语法树 AST

程序的「结构」——循环、条件、过程调用各就各位。

ast.hpp(11 个结点结构)
STAGE 04

解释执行 Interpreter

遍历 AST、查符号表、递归求值,驱动海龟。

interpreter.cpp
STAGE 05

海龟绘图 Turtle + 画布

海龟按指令前进转弯,Bresenham 把线画到画布。

turtle.cpp / canvas.cpp
03 / SYNTAX

MiniTurtle 语言,一分钟上手

核心思想:程序 = 给海龟下指令。命令之间用空格或换行分隔,没有分号;花括号 { } 表示一段。

minilang / 语法一览minilang.mt
# 海龟命令(核心) fd 100 # forward 前进 100 bk 50 # backward 后退 lt 90 # left 左转 90° rt 90 # right 右转 90° pu pd # 抬笔 / 落笔(抬笔移动不画线) color "red" # 换笔色 circle 30 # 画半径 30 的圆 home # 回到中心、面朝上 # 变量 / 循环 / 条件 / 过程 let n = 6 repeat n { fd 15 rt 360 / n } if len > 4 { ... } else { ... } to branch len { ... } # 定义过程(支持递归) branch 10 # 调用过程
语法含义写法示例
fd / bk前进 / 后退fd 距离fd 100
lt / rt左转 / 右转rt 角度rt 90
pu / pd抬笔 / 落笔pupd
let存一个数到名字let 名 = 表达式let side = 30
repeat重复一段指令repeat 次数 { ... }repeat 4 { ... }
if / else条件分支if 条件 { ... }if len > 4 { ... }
to定义过程(子程序)to 名 参数 { ... }to branch len { ... }
#注释# 说明# 一行注释

语言约定(照这些规则写就不会错)

约定说明举例注意
初始状态海龟在画布中心、面朝上,笔是落下的home 即回到此状态不是朝右、也不在角落
转向rt 顺时针、lt 逆时针;角度累加不回绕rt 360 / n画正 n 边形就用这个角
数字只有一种数值:小数(浮点)360 / 6 → 60没有整数类型,也没有取模 %
真值条件判断「非 0 即真」;比较运算返回 1 / 0if len > 4 { … }比较符 == != < > <= >=
表达式+ - * / 与括号,优先级同数学(i + 1) * 0.4括号可以直接写
变量let 名 = 表达式;同名再写一次就是改值let i = i + 1过程里新声明的是局部变量
过程to 名 参数 { … } 定义;调用按形参个数取参branch len * 0.72过程体用 { } 收尾,支持递归
颜色color "名字";字符画布用字母表示color "red" → Rred / green / blue / yellow / cyan / magenta
圆circle r 用 36 段折线近似circle 30不是真圆,是正 36 边形
暂不支持数组、字符串变量、函数返回值、布尔类型—字符串只在 color 里出现
04 / EXAMPLES

四个示例,把语言能力走一遍

从最简单的正方形,到用「过程 + 递归」画出的分形树——每个示例都验证解释器的一项核心能力。

例1 · 正方形loop + fd/rt
repeat 4 { fd 24 rt 90 }
例2 · 正六边形变量 + 表达式
let n = 6 let side = 15 repeat n { fd side rt 360 / n }
例3 · 螺旋变量自增 + 循环
let i = 0 repeat 30 { fd (i + 1) * 0.4 rt 24 let i = i + 1 }
例4 · 分形树过程 + 递归
to branch len { fd len if len > 4 { lt 30 branch len * 0.72 rt 60 branch len * 0.72 lt 30 } bk len } to main { pu home pd branch 10 } main
05 / RUN IT

在自己电脑上跑起来

MiniTurtle 是一个命令行程序:编译一次,两种玩法——跑内置的 4 个示例,或者跑你自己写的 .mt 程序。真实输出是终端字符画(就是首屏那种),不依赖任何图形库。

第 1 步 · 编译(6 个源文件一起编)C++17 · g++
g++ -std=c++17 -Wall -Wextra -o minturtle.exe \ main.cpp lexer.cpp parser.cpp canvas.cpp turtle.cpp interpreter.cpp
第 2 步 · 跑内置示例演示模式
./minturtle.exe # 依次画出正方形 / 正六边形 / 螺旋 / 分形树
第 3 步 · 跑自己的程序文件模式
./minturtle.exe star.mt # 用记事本写个 star.mt 就能跑
你的第一个程序 · star.mt画一个五角星
# 我的第一个 MiniTurtle 程序:画一个五角星 repeat 5 { fd 22 rt 144 }
它的真实输出终端字符画 · 88×42
                                            **
                                            **
                                            * *
                                            *  *        **
                                            *   *    ****
                                            *   * ***   *
                                            *  ***     *
                                            ***   *   *
                                         ****     *  *
                                      ***   *      * *
                                    **      *       *
                                      ***   *      * *
                                         ****      * *
                                            ***   *   *
                                            *  ***     *
                                            *   * ***   *
                                            *   *    ****
                                            *  *        **
                                            * *
                                            **
                                            **
                                            *

项目文件结构(13 个文件:6 个 .cpp + 7 个头文件)

文件职责对应阶段一句话
token.hppToken 的定义(类型 + 文本 + 数值 + 行号)阶段 2「单词」长什么样
lexer.cpp词法分析:源码 → Token 序列(跳空白/注释、认数字/命令/标识符)阶段 2把字切成词
ast.hpp抽象语法树结点(11 个结构)阶段 4程序的结构
parser.cpp递归下降解析:Token → AST,含表达式优先级与过程参数个数表阶段 4把词拼成句
interpreter.cpp遍历 AST 执行:作用域栈、变量、循环、条件、过程调用阶段 5–8让程序跑起来
turtle.cpp海龟:位置 / 朝向 / 笔状态;把一次前进算成一条线段阶段 5海龟怎么走
canvas.cpp字符画布:Bresenham 画线 + 渲染到终端阶段 1、5怎么落到画布
main.cpp入口:演示模式(4 个示例)与文件模式(minturtle xxx.mt)阶段 0从哪开始跑

其余 5 个头文件(lexer.hpp、parser.hpp、interpreter.hpp、turtle.hpp、canvas.hpp)只放类与函数声明——C++ 的「声明与实现分离」,编译命令里只需列出 6 个 .cpp。

源码 & 项目文档 付费会员

把这台解释器完整带走:可以直接编译运行的源码工程 + 配套文档。

  • minturtle-source.zip —— 全部 13 个源文件(6 .cpp + 7 .hpp)+ star.mt + 编译运行说明
  • 《MiniTurtle 分阶段开发计划》 —— 10 个阶段的任务拆解,照着做就能自己写一台
  • 《MiniTurtle 项目验证报告》 —— 零基础手把手:装 g++、编译、运行、4 示例逐条讲解、FAQ
⬇ 下载源码包(.zip) 仅供已开通「OJ / C++」会员下载,请勿二次分发。
06 / PITFALLS

开发中踩到的 3 个真坑

这几个 bug 不是编的,是开发这台解释器时真实踩到、又亲手修掉的——每个都是一堂扎实的编译原理课。

PIT 01

AST 结点无法构造

结构体继承了带虚析构的基类后,不再是可以花括号初始化的聚合类型,编译直接报错。

修复 → 给需要传参的结点补上构造函数(其余用默认构造 + 字段赋值)
PIT 02

分形树越界崩溃

解析器在等 end 关键字,但代码用 } 收尾,解析器静默吞掉分隔符一路越界到数组尽头。

修复 → 过程体统一用 { } 收尾
PIT 03

命令吞掉过程名

pd branch 12 里,pd 误把 branch 当成了自己的参数。

修复 → 命令建参数个数表、过程按形参个数取参
07 / ROADMAP

从零到能画图,10 个阶段

每个阶段都有清晰可见的成果物——不断看到东西跑出来,正是这个项目适合当 C++ 学习实战的原因。

阶段 0–1

工程骨架 · 字符画布

搭出能编译运行的工程;先有"能画图的画布"。

→ 终端画出字符线
阶段 2–3

词法分析 · 表达式求值

源码切成 Token;递归下降算出 2+3*4=14。

→ 打印 Token / 算出表达式
阶段 4–5

语法分析 · 解释执行

Token 拼成 AST;程序真正跑起来驱动海龟。

→ 画出第一个正方形
阶段 6–7

变量 / 循环 / 条件

语言会存储、重复、分支决策,画出可配置图形。

→ 多边形 / 螺旋
阶段 8

过程与递归 · 高光时刻

递归在视觉上开花,画出经典分形。

→ 科赫雪花 / 分形树
阶段 9

错误处理 · 图形窗口(可选)

报错定位到行;字符画布可换成彩色窗口。

→ 更健壮、更好看

怎么学:4 级目标 · 7 个单元

单元主题对应开发阶段拿到什么
单元 0会用:认识语言 + 搭好环境阶段 0跑通 4 个示例、画出自己的五角星
单元 1词法分析:源码 → Token阶段 2能打印程序的 Token 序列
单元 2语法分析 + 表达式 + AST阶段 3–4解析器跑通、能算表达式
单元 3解释执行 + 海龟绘图 + 画布阶段 1、5第一次画出正方形
单元 4变量 / 循环 / 条件阶段 6–7可配置的多边形、螺旋
单元 5过程与递归:分形(高光时刻)阶段 8递归分形树 / 科赫雪花
单元 6错误处理 + 创造扩展阶段 9报错定位 + 自创图形 / 新命令

四级目标:会用(读懂并写出程序)→ 懂原理(说清「源码怎么变成一幅画」)→ 能实现(独立写出 lexer / parser / interpreter)→ 能创造(扩展语言、创作复杂作品)。本项目的核心目标落在「能实现」。

10个阶段
分阶段开发计划
5大模块
词法→语法→AST→执行→绘图
11种
AST 结点结构(含程序根)
3个
真踩过并修掉的 bug