Toy Go Compiler
ooo (pronounced /oːo/, in Japanese 「おおお」,) is a toy Go compiler. It reads (subsets of) Go programs and generates x86_64 assembly code.
rm -f *.s
# Build 1st generation ooo
go build -o ooo1 .
# Generate 2nd generation assembly code
./ooo1 < go_files.txt > ooo2.s
# Build 2nd generation ooo
cc -Wa,--noexecstack -fPIE -g -o ooo2 ooo2.s asm/syscall.s asm/print.s asm/readAll.s asm/mem.s asm/files.s
# Generate 3rd generation assembly code
./ooo2 < go_files.txt > ooo3.s
# Check if ooo2 and ooo3 are identical
diff ooo2.s ooo3.sprogram = packageClause ";" ( (funcDecl | varDecl | typeDecl | constDecl) ";" )*
packageClause = "package" ident
funcDecl = "func" ident parameters result? compStmt?
parameters = "(" (parameterDecl, ("," parameterDecl)* ","? )? ")"
parameterDecl = ident type
type = ident | "*" type | arrayType | sliceType | structType
arrayType = "[" num "]" type
sliceType = "[" "]" type
structType = "struct" "{" ( fieldDecl ";" )* "}"
fieldDecl = ident type
selector = "." ident
result = type
stmt = "return" expr?
| "continue"
| "break"
| ifStmt
| forStmt
| varDecl
| constDecl
| typeDecl
| gotoStmt
| labeledStmt
| assign
| emptyStmt
forStmt = "for" (stmt? ";" expr? ";" stmt?)? compStmt
compStmt = "{" (stmt ";" )* "}"
ifStmt = "if" expr compStmt ( "else" (compStmt | ifStmt) )?
gotoStmt = "goto" ident
labeledStmt = ident ":" stmt
emptyStmt = ""
varDecl = "var" ident type
constDecl = "const" ident type "=" expr
typeDecl = "type" ident type
assign = expr ( "=" expr)?
expr = or
or = and ( "||" and )*
and = equality ( "&&" equality )*
equality = relational ("==" relational | "!=" relational)*
relational = add ("<" add | "<=" add | ">" add | ">=" add)*
add = mul ("+" mul | "-" mul)*
mul = unary ("*" unary | "/" unary)*
unary = ("+" | "-")? primary | "*" unary | "&" unary | "!" unary
index = "[" expr "]"
slice = "[" expr ":" expr "]"
compLit = litType litValue
litType = arrayType | sliceType | structType | ident
litValue = "{" ( elemList (",")? )? "}"
elemList = keyedElem ( "," keyedElem )*
keyedElemKey = expr | ident
keyedElem = keyedElemKey ":" expr | expr
primary = num
| str
| "(" expr ")"
| ident ( "(" ( expr | type ("," expr)* ","? )? ")" )?
| compLit
| primary index
| primary slice
| primary selector
str = `"` { any char except `"` } `"`