compiler2: proof of concept cgen
parent
fe8a6abb41
commit
8d9f89e728
|
@ -980,6 +980,9 @@ fn (p mut Parser) fn_args(f mut Fn) {
|
|||
p.next()
|
||||
}
|
||||
}
|
||||
//if types_only && p.peek() == .lcbr {
|
||||
//println('wtf')
|
||||
//}
|
||||
}
|
||||
|
||||
// foo *(1, 2, 3, mut bar)*
|
||||
|
|
|
@ -10,15 +10,19 @@ import (
|
|||
|
||||
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:
|
||||
val int
|
||||
}
|
||||
*/
|
||||
|
||||
pub struct StringLiteral {
|
||||
pub:
|
||||
val string
|
||||
}
|
||||
|
||||
/*
|
||||
pub enum Expr {
|
||||
|
@ -28,10 +32,24 @@ pub enum Expr {
|
|||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
pub struct Stmt {
|
||||
pos int
|
||||
//end int
|
||||
}
|
||||
*/
|
||||
|
||||
pub struct VarDecl {
|
||||
pub:
|
||||
name string
|
||||
expr Expr
|
||||
|
||||
}
|
||||
|
||||
pub struct Program {
|
||||
pub:
|
||||
exprs []Expr
|
||||
}
|
||||
|
||||
// A single identifier
|
||||
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
|
||||
}
|
||||
|
|
@ -28,6 +28,17 @@ pub fn parse_expr(text string) ast.Expr {
|
|||
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() {
|
||||
res := p.scanner.scan()
|
||||
p.tok = res.tok
|
||||
|
@ -41,37 +52,76 @@ pub fn (p mut Parser) expr(rbp int) ast.Expr {
|
|||
tok := p.tok
|
||||
lit := p.lit
|
||||
p.next()
|
||||
mut left := ast.Expr{}
|
||||
mut node := ast.Expr{
|
||||
}
|
||||
match tok {
|
||||
.lpar {
|
||||
left = p.expr(0)
|
||||
node = p.expr(0)
|
||||
if p.tok != .rpar {
|
||||
panic("Parse Error: expected )")
|
||||
panic('Parse Error: expected )')
|
||||
}
|
||||
p.next()
|
||||
}
|
||||
else {
|
||||
// TODO: fix bug. note odd conditon instead of else if (same below)
|
||||
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() {
|
||||
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
|
||||
for rbp < p.tok.precedence() {
|
||||
tok2 := p.tok
|
||||
p.next()
|
||||
// left denotation (infix)
|
||||
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() {
|
||||
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
|
||||
|
||||
import compiler2.ast
|
||||
import (
|
||||
compiler2.ast
|
||||
compiler2.cgen
|
||||
)
|
||||
|
||||
fn test_parser() {
|
||||
//expr := ast.IntegerExpr {val:10}
|
||||
|
@ -62,4 +65,17 @@ fn walk(node ast.Expr) {
|
|||
}
|
||||
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) {
|
||||
if s == '' {
|
||||
return
|
||||
}
|
||||
b.buf.push_many(s.str, s.len)
|
||||
// for c in s {
|
||||
// b.buf << c
|
||||
|
|
Loading…
Reference in New Issue