compiler2: proof of concept cgen
parent
fe8a6abb41
commit
8d9f89e728
|
@ -980,6 +980,9 @@ fn (p mut Parser) fn_args(f mut Fn) {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//if types_only && p.peek() == .lcbr {
|
||||||
|
//println('wtf')
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
// foo *(1, 2, 3, mut bar)*
|
// foo *(1, 2, 3, mut bar)*
|
||||||
|
|
|
@ -10,15 +10,19 @@ import (
|
||||||
|
|
||||||
struct Foo {}
|
struct Foo {}
|
||||||
|
|
||||||
// pub type Expr = Foo | IfExpr | BinaryExpr | IntegerExpr
|
pub type Expr = Foo | IfExpr | BinaryExpr | ScalarExpr | UnaryExpr |
|
||||||
pub type Expr = Foo | IfExpr | BinaryExpr | ScalarExpr | UnaryExpr
|
StringLiteral | IntegerExpr
|
||||||
|
pub type Stmt = Foo | VarDecl
|
||||||
|
|
||||||
/*
|
|
||||||
pub struct IntegerExpr {
|
pub struct IntegerExpr {
|
||||||
pub:
|
pub:
|
||||||
val int
|
val int
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
pub struct StringLiteral {
|
||||||
|
pub:
|
||||||
|
val string
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
|
@ -28,10 +32,24 @@ pub enum Expr {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
pub struct Stmt {
|
pub struct Stmt {
|
||||||
pos int
|
pos int
|
||||||
//end int
|
//end int
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub struct VarDecl {
|
||||||
|
pub:
|
||||||
|
name string
|
||||||
|
expr Expr
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Program {
|
||||||
|
pub:
|
||||||
|
exprs []Expr
|
||||||
|
}
|
||||||
|
|
||||||
// A single identifier
|
// A single identifier
|
||||||
struct Ident {
|
struct Ident {
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
module cgen
|
||||||
|
|
||||||
|
import (
|
||||||
|
strings
|
||||||
|
compiler2.ast
|
||||||
|
)
|
||||||
|
|
||||||
|
struct Gen {
|
||||||
|
out strings.Builder
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen(program ast.Program) {
|
||||||
|
mut g := Gen{out:strings.new_builder(100)}
|
||||||
|
for expr in program.exprs {
|
||||||
|
g.expr(expr)
|
||||||
|
g.writeln('')
|
||||||
|
}
|
||||||
|
println(g.out.str())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (g &Gen) save() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (g mut Gen) write(s string) {
|
||||||
|
g.out.write(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (g mut Gen) writeln(s string) {
|
||||||
|
g.out.writeln(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Type {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
string_type = Type{'string'}
|
||||||
|
int_type = Type{'int'}
|
||||||
|
void_type = Type{'void'}
|
||||||
|
)
|
||||||
|
|
||||||
|
fn (g mut Gen) expr(node ast.Expr) Type {
|
||||||
|
//println('cgen expr()')
|
||||||
|
match node {
|
||||||
|
ast.IntegerExpr {
|
||||||
|
g.write(it.val.str())
|
||||||
|
return int_type
|
||||||
|
}
|
||||||
|
ast.StringLiteral {
|
||||||
|
g.write('"$it.val"')
|
||||||
|
return string_type
|
||||||
|
}
|
||||||
|
ast.BinaryExpr {
|
||||||
|
typ := g.expr(it.left)
|
||||||
|
match it.op {
|
||||||
|
.plus { g.write(' + ') }
|
||||||
|
.minus { g.write(' - ') }
|
||||||
|
.mul { g.write(' * ') }
|
||||||
|
.div { g.write(' / ') }
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
typ2 := g.expr(it.right)
|
||||||
|
if typ.name != typ2.name {
|
||||||
|
println('bad types $typ.name $typ2.name')
|
||||||
|
}
|
||||||
|
return typ
|
||||||
|
}
|
||||||
|
ast.VarDecl {
|
||||||
|
g.write('var $it.name = ')
|
||||||
|
g.expr(it.expr)
|
||||||
|
g.writeln(';')
|
||||||
|
return void_type
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println('bad node')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return void_type
|
||||||
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ import (
|
||||||
struct Parser {
|
struct Parser {
|
||||||
scanner &scanner.Scanner
|
scanner &scanner.Scanner
|
||||||
mut:
|
mut:
|
||||||
tok token.Token
|
tok token.Token
|
||||||
lit string
|
lit string
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_expr(text string) ast.Expr {
|
pub fn parse_expr(text string) ast.Expr {
|
||||||
|
@ -28,10 +28,21 @@ pub fn parse_expr(text string) ast.Expr {
|
||||||
return p.expr(token.lowest_prec)
|
return p.expr(token.lowest_prec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_stmt(text string) ast.Stmt {
|
||||||
|
mut s := scanner.new_scanner(text)
|
||||||
|
res := s.scan()
|
||||||
|
mut p := Parser{
|
||||||
|
scanner: s
|
||||||
|
tok: res.tok
|
||||||
|
lit: res.lit
|
||||||
|
}
|
||||||
|
return p.stmt()
|
||||||
|
}
|
||||||
|
|
||||||
fn (p mut Parser) next() {
|
fn (p mut Parser) next() {
|
||||||
res := p.scanner.scan()
|
res := p.scanner.scan()
|
||||||
p.tok = res.tok
|
p.tok = res.tok
|
||||||
//println(p.tok.str())
|
// println(p.tok.str())
|
||||||
p.lit = res.lit
|
p.lit = res.lit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,37 +52,76 @@ pub fn (p mut Parser) expr(rbp int) ast.Expr {
|
||||||
tok := p.tok
|
tok := p.tok
|
||||||
lit := p.lit
|
lit := p.lit
|
||||||
p.next()
|
p.next()
|
||||||
mut left := ast.Expr{}
|
mut node := ast.Expr{
|
||||||
|
}
|
||||||
match tok {
|
match tok {
|
||||||
.lpar {
|
.lpar {
|
||||||
left = p.expr(0)
|
node = p.expr(0)
|
||||||
if p.tok != .rpar {
|
if p.tok != .rpar {
|
||||||
panic("Parse Error: expected )")
|
panic('Parse Error: expected )')
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO: fix bug. note odd conditon instead of else if (same below)
|
// TODO: fix bug. note odd conditon instead of else if (same below)
|
||||||
if tok.is_scalar() {
|
if tok.is_scalar() {
|
||||||
left = ast.ScalarExpr{val: lit, typ: tok}
|
node = ast.ScalarExpr{
|
||||||
|
val: lit
|
||||||
|
typ: tok
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if !tok.is_scalar() && tok.is_unary() {
|
if !tok.is_scalar() && tok.is_unary() {
|
||||||
left = ast.UnaryExpr{left: p.expr(token.highest_prec), op: tok}
|
node = ast.UnaryExpr{
|
||||||
|
left: p.expr(token.highest_prec)
|
||||||
|
op: tok
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}}
|
||||||
}
|
|
||||||
|
|
||||||
// left binding power
|
// left binding power
|
||||||
for rbp < p.tok.precedence() {
|
for rbp < p.tok.precedence() {
|
||||||
tok2 := p.tok
|
tok2 := p.tok
|
||||||
p.next()
|
p.next()
|
||||||
// left denotation (infix)
|
// left denotation (infix)
|
||||||
if tok2.is_right_assoc() {
|
if tok2.is_right_assoc() {
|
||||||
left = ast.BinaryExpr{left: left, op: tok2, right: p.expr(tok2.precedence() - 1)}
|
node = ast.BinaryExpr{
|
||||||
|
left: node
|
||||||
|
op: tok2
|
||||||
|
right: p.expr(tok2.precedence() - 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if !tok2.is_right_assoc() && tok2.is_left_assoc() {
|
if !tok2.is_right_assoc() && tok2.is_left_assoc() {
|
||||||
left = ast.BinaryExpr{left: left, op: tok2, right: p.expr(tok2.precedence())}
|
node = ast.BinaryExpr{
|
||||||
|
left: node
|
||||||
|
op: tok2
|
||||||
|
right: p.expr(tok2.precedence())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return left
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (p mut Parser) stmt() ast.Stmt {
|
||||||
|
if p.tok == .name {
|
||||||
|
name := p.lit
|
||||||
|
p.next()
|
||||||
|
if p.tok == .decl_assign {
|
||||||
|
p.next()
|
||||||
|
return ast.VarDecl{
|
||||||
|
name: name
|
||||||
|
expr: p.expr(token.lowest_prec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
match node {
|
||||||
|
Ident {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
return ast.VarDecl{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
module parser
|
module parser
|
||||||
|
|
||||||
import compiler2.ast
|
import (
|
||||||
|
compiler2.ast
|
||||||
|
compiler2.cgen
|
||||||
|
)
|
||||||
|
|
||||||
fn test_parser() {
|
fn test_parser() {
|
||||||
//expr := ast.IntegerExpr {val:10}
|
//expr := ast.IntegerExpr {val:10}
|
||||||
|
@ -62,4 +65,17 @@ fn walk(node ast.Expr) {
|
||||||
}
|
}
|
||||||
else { }
|
else { }
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
//expr := parse_expr('3 + 7 * 2')
|
||||||
|
expr := parse_stmt('a := 3 + "f"')
|
||||||
|
program := ast.Program{
|
||||||
|
exprs: [
|
||||||
|
expr,
|
||||||
|
//parse_expr('2 * 2'),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
cgen.gen(program)
|
||||||
|
//cgen.save()
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,9 @@ pub fn (b mut Builder) write_b(data byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (b mut Builder) write(s string) {
|
pub fn (b mut Builder) write(s string) {
|
||||||
|
if s == '' {
|
||||||
|
return
|
||||||
|
}
|
||||||
b.buf.push_many(s.str, s.len)
|
b.buf.push_many(s.str, s.len)
|
||||||
// for c in s {
|
// for c in s {
|
||||||
// b.buf << c
|
// b.buf << c
|
||||||
|
|
Loading…
Reference in New Issue