ycc

a toy compiler based on the screencast from destroy all software
git clone git://git.ter0.net/ycc.git
Log | Files | Refs

commit 5ed7349e8ec751cbf2732c67673b8d6b17ea35de
Author: Chris Johns <chris@ter0.net>
Date:   Mon, 11 Oct 2021 15:10:18 +0100

Initial commit

Diffstat:
A.gitignore | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AMakefile | 11+++++++++++
Ago.mod | 3+++
Atest.y | 3+++
Aycc | 0
Aycc.go | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 216 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,116 @@ +# Created by https://www.toptal.com/developers/gitignore/api/vim,linux,windows,macos,go +# Edit at https://www.toptal.com/developers/gitignore?templates=vim,linux,windows,macos,go + +### Go ### +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +### Go Patch ### +/vendor/ +/Godeps/ + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/vim,linux,windows,macos,go + diff --git a/Makefile b/Makefile @@ -0,0 +1,11 @@ +.PHONY: build +build: + go1.17.2 build + +.PHONY: run +run: + go1.17.2 run . + +.PHONY: fmt +fmt: + go1.17.2 fmt . diff --git a/go.mod b/go.mod @@ -0,0 +1,3 @@ +module git.ter0.net/ycc + +go 1.17 diff --git a/test.y b/test.y @@ -0,0 +1,3 @@ +def f() + 1 +end diff --git a/ycc b/ycc Binary files differ. diff --git a/ycc.go b/ycc.go @@ -0,0 +1,83 @@ +package main + +import "fmt" +import "os" +import "regexp" +import "bytes" + +type Tokenizer struct { + code []byte +} + +type TokenType struct { + name string + pattern string +} + +var tokenTypes = []TokenType{ + { + name: "def", + pattern: `\bdef\b`, + }, + { + name: "end", + pattern: `\bend\b`, + }, + { + name: "identifier", + pattern: `\b[a-zA-Z]\b`, + }, + { + name: "integer", + pattern: `\b[0-9]\b`, + }, + { + name: "oparen", + pattern: `\(`, + }, + { + name: "cparen", + pattern: `\)`, + }, +} + +type Token struct { + type_of string + value []byte +} + +func (t *Tokenizer) tokenize() { + var tokens []Token + for len(t.code) > 0 { + tokens = append(tokens, t.tokenize_one_token()) + t.code = bytes.TrimSpace(t.code) + } + fmt.Printf("%s\n", tokens) +} + +func (t *Tokenizer) tokenize_one_token() Token { + for _, tokenType := range tokenTypes { + pattern := fmt.Sprintf(`\A(%s)`, tokenType.pattern) + re := regexp.MustCompile(pattern) + match := re.Find(t.code) + if match != nil { + t.code = t.code[len(match):] + return Token{type_of: tokenType.name, value: match} + } + } + fmt.Printf("Couldn't match token on '%s'", t.code) + os.Exit(1) + // return token, err instead + return Token{} +} + +func main() { + code, err := os.ReadFile("test.y") + if err != nil { + panic("failed to read source") + } + t := &Tokenizer{ + code: code, + } + t.tokenize() +}