What is go-basic?
go-basic is a real compiler pipeline: a hand-written lexer, a recursive-descent/Pratt parser, a semantic analyzer that infers types from BASIC's variable suffixes, and a code generator that emits idiomatic Go. Point it at a .bas file and it either prints the equivalent Go source or builds it straight into a standalone executable.
What sets it apart from a toy transpiler is the runtime: SCREEN graphics modes, sprites (GET/PUT), CIRCLE/LINE/PAINT/DRAW, and SOUND/PLAY audio are all reimplemented in pure Go on top of Ebiten and Oto. That's enough to run real DOS-era software, not just PRINT demos.
- Open source
- MIT licensed
- Go 1.24+
- 65 example programs
- Bytecode VM
- Free
Features
Full BASIC parser
Handles real-world programs including the 58KB QBasic Gorillas source — not just textbook subsets of the language.
Go source output
Generates standalone, readable .go files you can inspect, hand-edit, or drop into a larger Go project.
Graphics runtime
SCREEN modes, sprites (GET/PUT), CIRCLE, LINE, PAINT, DRAW, and PALETTE, built on Ebiten.
Audio support
SOUND and PLAY commands, reimplemented in pure Go via Oto.
Bytecode VM
An alternative backend that compiles the AST to stack-based bytecode and interprets it directly, instead of generating Go.
Educational codebase
Every major file is extensively commented to explain the compiler concept it implements — lexing, Pratt parsing, AST design, codegen, VMs.
In action: QBasic Gorillas
The classic QBasic Gorillas game, compiled straight from its original .bas source and running as a native Go binary through go-basic's graphics runtime:
./go-basic compile examples/gorilla.bas
./gorilla
What the transpiler produces
A BASIC program becomes readable, idiomatic Go — loops become for, typed variables keep their BASIC-inferred type, and PRINT maps to fmt.
hello.bas
10 PRINT "HELLO WORLD"
20 FOR I = 1 TO 5
30 PRINT "COUNT:"; I
40 NEXT I
50 END
hello.go
package main
import "fmt"
func main() {
fmt.Println("HELLO WORLD")
var I float32
for I = float32(1); I <= float32(5); I += float32(1) {
fmt.Print("COUNT:", I)
fmt.Println()
}
}
Language support
| Category | Supported |
|---|---|
| Control flow | IF/THEN/ELSE/ELSEIF, FOR/NEXT, WHILE/WEND, DO/LOOP, SELECT CASE, GOTO, GOSUB/RETURN |
| Procedures | SUB, FUNCTION, DEF FN, DECLARE, CALL |
| Variables | Integer (%), Long (&), Single (!), Double (#), String ($) |
| Arrays | DIM, REDIM, ERASE, multi-dimensional |
| Data | DATA, READ, RESTORE |
| I/O | PRINT, INPUT, LINE INPUT, PRINT USING, WRITE |
| File I/O | OPEN, CLOSE, PRINT#, INPUT#, WRITE#, sequential/random/binary |
| String functions | LEFT$, RIGHT$, MID$, CHR$, ASC, STR$, VAL, INSTR, UCASE$, LCASE$, LTRIM$, RTRIM$, HEX$, OCT$, BIN$, STRING$, SPACE$ |
| Math functions | ABS, SGN, INT, FIX, SQR, SIN, COS, TAN, ATN, EXP, LOG, RND, CINT, CLNG, CSNG, CDBL |
| User types | TYPE...END TYPE with field access |
| Graphics | SCREEN, CIRCLE, LINE, PSET, PRESET, PAINT, DRAW, GET, PUT, PALETTE, COLOR, VIEW, WINDOW, CLS |
| Sound | SOUND, PLAY |
| Turbo BASIC extensions | DO/LOOP, EXIT, SELECT CASE, INCR/DECR, $DYNAMIC, $IF/$ENDIF |
Screen modes
| Mode | Resolution | Colors | Hardware origin |
|---|---|---|---|
| SCREEN 0 | Text 80x25 | 16 | Text mode |
| SCREEN 1 | 320x200 | 4 | CGA |
| SCREEN 2 | 640x200 | 2 | CGA |
| SCREEN 7 | 320x200 | 16 | EGA |
| SCREEN 9 | 640x350 | 16 | EGA |
| SCREEN 12 | 640x480 | 16 | VGA |
| SCREEN 13 | 320x200 | 256 | VGA/MCGA |
Quick start
Requires Go 1.24+. The graphics/audio runtime uses Ebiten and Oto — macOS and Windows need nothing extra; Linux (Debian/Ubuntu) needs a handful of system packages for OpenGL, X11, and ALSA.
git clone https://github.com/andrewloable/go-basic.git
cd go-basic
go build -o go-basic .
Compile a .bas file straight to a binary
./go-basic compile examples/gorilla.bas
./go-basic compile examples/gorilla.bas -o mygame
./gorilla
Or just transpile to Go source
./go-basic transpile examples/gorilla.bas -o gorilla.go
Useful for inspecting the generated code, hand-editing it, or wiring it into a larger Go project.
View go-basic on GitHubHow it works
A classical multi-stage compiler pipeline, each stage in its own internal/ package:
- Lexer. A hand-written scanner turns source text into a stream of typed tokens — keywords, type suffixes (
%&!#$), string and numeric literals (decimal, hex&H, octal&O), and line structure. - Parser. Recursive descent for statements, Pratt (TDOP) parsing for expressions, resolving BASIC's ambiguity between function calls, array access, and plain variable references into a typed AST.
- Semantic analysis. Builds a symbol table with types inferred from variable suffixes,
DIMdeclarations, and assignment context. - Code generation. A tree-walking transpiler maps BASIC constructs to Go equivalents, calling into a runtime library for BASIC-specific behavior.
- Runtime. Pure Go implementations of BASIC builtins — math, strings, formatted output, file I/O, graphics, and sound.
A second backend, the bytecode VM, skips Go codegen entirely: it compiles the AST straight to stack-based bytecode and interprets it.
Status
| Metric | Count |
|---|---|
| Example programs | 65 (all parse successfully) |
| Generated Go files that compile | 64 / 65 |
| Test packages passing | 10 / 10 |
| Parser regression tests | 24 |
The examples/ directory ranges from hello-world to the full Gorillas game — try circle_draw.bas or fibonacci.bas for smaller demos.
Frequently asked questions
What is go-basic?
A free, open-source compiler that transpiles Turbo BASIC and QBasic .bas source files into standalone Go programs. It has a full lexer, parser, semantic analyzer, and code generator, plus a graphics and audio runtime so classic programs like QBasic Gorillas run as native Go binaries.
Does it require the original QBasic or DOS?
No. Only Go 1.24+ is required. Graphics and audio are reimplemented as a pure Go runtime on Ebiten and Oto, so compiled programs run natively on macOS, Windows, and Linux without DOS or an emulator.
Can it really run the QBasic Gorillas game?
Yes — the original, unmodified Gorillas .bas source compiles and runs as a native Go binary via go-basic's graphics runtime, which is the project's flagship demo.
What BASIC language features are supported?
Control flow, procedures, typed variables and arrays, DATA/READ, file I/O, string and math functions, user-defined TYPE records, graphics, sound, and several Turbo BASIC extensions. See the language support table above.
Is go-basic meant to teach compiler design?
Yes, explicitly. The codebase is heavily commented to explain lexical analysis, recursive descent and Pratt parsing, AST design, tree-walking code generation, and bytecode virtual machines — each major file doubles as a walkthrough of the concept it implements.