FnDecl, Return, statement block
parent
6c16bac908
commit
66a07d7fe0
|
@ -793,13 +793,13 @@ fn (p mut Parser) type_decl() {
|
|||
if p.tok == .key_struct {
|
||||
p.error('use `struct $name {` instead of `type $name struct {`')
|
||||
}
|
||||
if p.tok == .assign {
|
||||
is_sum := p.tok == .assign
|
||||
if is_sum {
|
||||
p.next()
|
||||
|
||||
}
|
||||
parent := p.get_type2()
|
||||
mut parent := Type{}
|
||||
// Sum type
|
||||
is_sum := p.tok == .pipe
|
||||
//is_sum := p.tok == .pipe
|
||||
if is_sum {
|
||||
if !p.builtin_mod && p.mod != 'main' {
|
||||
name = p.prepend_mod(name)
|
||||
|
@ -815,10 +815,15 @@ fn (p mut Parser) type_decl() {
|
|||
*/
|
||||
// Register the rest of them
|
||||
mut idx := 0
|
||||
for p.tok == .pipe {
|
||||
mut done := false
|
||||
for {//p.tok == .pipe {
|
||||
idx++
|
||||
p.next()
|
||||
//p.next()
|
||||
child_type_name := p.check_name()
|
||||
//println('$idx $child_type_name')
|
||||
if p.tok != .pipe {
|
||||
done = true
|
||||
}
|
||||
if p.pass == .main {
|
||||
// Update the type's parent
|
||||
//println('child=$child_type_name parent=$name')
|
||||
|
@ -830,13 +835,17 @@ fn (p mut Parser) type_decl() {
|
|||
p.table.rewrite_type(t)
|
||||
p.cgen.consts << '#define SumType_$child_type_name $idx // DEF2'
|
||||
}
|
||||
if done {
|
||||
break
|
||||
}
|
||||
p.check(.pipe)
|
||||
}
|
||||
if p.pass == .decl {
|
||||
p.table.sum_types << name
|
||||
println(p.table.sum_types)
|
||||
}
|
||||
// Register the actual sum type
|
||||
//println('registering sum $name')
|
||||
println('registering sum $name')
|
||||
p.table.register_type(Type{
|
||||
name: name
|
||||
mod: p.mod
|
||||
|
@ -849,6 +858,10 @@ int typ;
|
|||
} $name;
|
||||
')
|
||||
}
|
||||
else {
|
||||
|
||||
parent = p.get_type2()
|
||||
}
|
||||
nt_pair := p.table.cgen_name_type_pair(name, parent.name)
|
||||
// TODO dirty C typedef hacks for DOOM
|
||||
// Unknown type probably means it's a struct, and it's used before the struct is defined,
|
||||
|
|
|
@ -11,10 +11,12 @@ import (
|
|||
|
||||
struct Foo {}
|
||||
|
||||
pub type Expr = Foo | IfExpr | BinaryExpr | UnaryExpr |
|
||||
StringLiteral | IntegerLiteral | FloatLiteral | VarDecl
|
||||
pub type Expr = BinaryExpr | UnaryExpr | IfExpr |
|
||||
StringLiteral | IntegerLiteral | FloatLiteral | VarDecl |
|
||||
FnDecl | Return
|
||||
|
||||
pub type Stmt = Foo//VarDecl
|
||||
|
||||
pub type Stmt = Foo | Foo //VarDecl
|
||||
|
||||
pub struct IntegerLiteral {
|
||||
pub:
|
||||
|
@ -32,6 +34,20 @@ pub:
|
|||
val string
|
||||
}
|
||||
|
||||
pub struct FnDecl {
|
||||
pub:
|
||||
name string
|
||||
//stmts []Stmt
|
||||
exprs []Expr
|
||||
typ types.Type
|
||||
|
||||
}
|
||||
|
||||
pub struct Return {
|
||||
pub:
|
||||
expr Expr
|
||||
}
|
||||
|
||||
/*
|
||||
pub enum Expr {
|
||||
Binary(BinaryExpr)
|
||||
|
|
|
@ -31,16 +31,6 @@ 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) {
|
||||
//println('cgen expr()')
|
||||
match node {
|
||||
|
@ -57,6 +47,18 @@ fn (g mut Gen) expr(node ast.Expr) {
|
|||
ast.StringLiteral {
|
||||
g.write('tos3("$it.val")')
|
||||
}
|
||||
ast.FnDecl {
|
||||
g.writeln('$it.typ.name $it.name () { ')
|
||||
for expr in it.exprs {
|
||||
g.expr(expr)
|
||||
}
|
||||
g.writeln('}')
|
||||
}
|
||||
ast.Return {
|
||||
g.write('return ')
|
||||
g.expr(it.expr)
|
||||
g.writeln(';')
|
||||
}
|
||||
ast.BinaryExpr {
|
||||
g.expr(it.left)
|
||||
match it.op {
|
||||
|
|
|
@ -18,6 +18,7 @@ mut:
|
|||
lit string
|
||||
//vars []string
|
||||
table &table.Table
|
||||
return_type types.Type
|
||||
}
|
||||
|
||||
pub fn parse_expr(text string, table &table.Table) ast.Expr {
|
||||
|
@ -33,6 +34,20 @@ pub fn parse_expr(text string, table &table.Table) ast.Expr {
|
|||
return expr
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) get_type() types.Type {
|
||||
defer {
|
||||
p.next()
|
||||
}
|
||||
if p.lit == 'int' { return types.int_type }
|
||||
else if p.lit == 'string' { return types.string_type }
|
||||
else if p.lit == 'f64' { return types.f64_type }
|
||||
else {
|
||||
verror('bad type lit')
|
||||
exit(1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn parse_file(text string, table &table.Table) ast.Program {
|
||||
s := scanner.new_scanner(text)
|
||||
mut exprs := []ast.Expr
|
||||
|
@ -57,6 +72,24 @@ pub fn parse_file(text string, table &table.Table) ast.Program {
|
|||
return ast.Program{exprs}
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) parse_block() []ast.Expr {
|
||||
mut exprs := []ast.Expr
|
||||
|
||||
for {
|
||||
//res := s.scan()
|
||||
if p.tok == .eof || p.tok == .rcbr {
|
||||
break
|
||||
}
|
||||
//println('expr at ' + p.tok.str())
|
||||
expr,_ := p.expr(token.lowest_prec)
|
||||
exprs << expr
|
||||
}
|
||||
p.next()
|
||||
println('nr exprs in block = $exprs.len')
|
||||
return exprs
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn parse_stmt(text string) ast.Stmt {
|
||||
mut s := scanner.new_scanner(text)
|
||||
|
@ -78,12 +111,59 @@ fn (p mut Parser) next() {
|
|||
p.lit = res.lit
|
||||
}
|
||||
|
||||
fn (p mut Parser) check(expected token.Token) {
|
||||
if p.tok != expected {
|
||||
s := 'syntax error: unexpected `${p.tok.str()}`, expecting `${expected.str()}`'
|
||||
verror(s)
|
||||
}
|
||||
p.next()
|
||||
}
|
||||
|
||||
fn (p mut Parser) check_name() string {
|
||||
name := p.lit
|
||||
p.check(.name)
|
||||
return name
|
||||
}
|
||||
|
||||
// Implementation of Pratt Precedence
|
||||
pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
||||
// null denotation (prefix)
|
||||
tok := p.tok
|
||||
lit := p.lit
|
||||
if p.tok == .name {
|
||||
if p.tok == .key_fn {
|
||||
p.next()
|
||||
name := p.lit
|
||||
println('fn decl $name')
|
||||
p.check(.name)
|
||||
p.check(.lpar)
|
||||
p.check(.rpar)
|
||||
// Return type
|
||||
mut typ := types.void_type
|
||||
if p.tok == .name {
|
||||
typ = p.get_type()
|
||||
p.return_type = typ
|
||||
|
||||
}
|
||||
p.check(.lcbr)
|
||||
//p.check(.rcbr)
|
||||
println('OK!')
|
||||
exprs := p.parse_block()
|
||||
|
||||
mut node := ast.Expr{}
|
||||
node = ast.FnDecl{name: name, exprs: exprs, typ: typ}
|
||||
return node, types.void_type
|
||||
}
|
||||
else if p.tok == .key_return {
|
||||
p.next()
|
||||
mut node := ast.Expr{}
|
||||
expr, typ := p.expr(0)
|
||||
if !types.check(p.return_type, typ) {
|
||||
verror('bad ret type')
|
||||
}
|
||||
node = ast.Return{expr: expr}
|
||||
return node, types.void_type
|
||||
}
|
||||
else if p.tok == .name {
|
||||
name := p.lit
|
||||
p.next()
|
||||
if p.tok == .decl_assign {
|
||||
|
@ -117,34 +197,30 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
|||
}
|
||||
p.next()
|
||||
}
|
||||
.str {
|
||||
node = ast.StringLiteral{
|
||||
val: lit
|
||||
}
|
||||
typ = types.string_type
|
||||
|
||||
}
|
||||
.number {
|
||||
if lit.contains('.') {
|
||||
node = ast.FloatLiteral{
|
||||
//val: lit.f64()
|
||||
val: lit
|
||||
}
|
||||
typ = types.int_type
|
||||
} else {
|
||||
node = ast.IntegerLiteral{
|
||||
val: lit.int()
|
||||
}
|
||||
typ = types.int_type
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO: fix bug. note odd conditon instead of else if (same below)
|
||||
if tok.is_scalar() {
|
||||
if tok == .str {
|
||||
node = ast.StringLiteral{
|
||||
val: lit
|
||||
}
|
||||
typ = types.string_type
|
||||
}
|
||||
if tok == .number {
|
||||
if lit.contains('.') {
|
||||
node = ast.FloatLiteral{
|
||||
//val: lit.f64()
|
||||
val: lit
|
||||
}
|
||||
typ = types.int_type
|
||||
} else {
|
||||
node = ast.IntegerLiteral{
|
||||
val: lit.int()
|
||||
}
|
||||
typ = types.int_type
|
||||
}
|
||||
}
|
||||
// else {
|
||||
// verror('bad scalar token')
|
||||
// }
|
||||
}
|
||||
if !tok.is_scalar() && tok.is_unary() {
|
||||
if tok.is_unary() {
|
||||
expr,_ := p.expr(token.highest_prec)
|
||||
node = ast.UnaryExpr{
|
||||
// left: p.expr(token.highest_prec)
|
||||
|
|
|
@ -7,10 +7,16 @@ import (
|
|||
)
|
||||
|
||||
fn test_parse_file() {
|
||||
s := '12 + 3
|
||||
x := 10
|
||||
5+7
|
||||
8+4
|
||||
s := '
|
||||
fn foo() string {
|
||||
f := 23
|
||||
return 10+4
|
||||
}
|
||||
|
||||
12 + 3
|
||||
x := 10
|
||||
5+7
|
||||
8+4
|
||||
'
|
||||
table := &table.Table{}
|
||||
prog := parse_file(s, table)
|
||||
|
@ -20,6 +26,7 @@ fn test_parse_file() {
|
|||
|
||||
|
||||
fn test_parse_expr() {
|
||||
//if true { return }
|
||||
input := [
|
||||
'2 + 3',
|
||||
'2+2*4',
|
||||
|
|
|
@ -287,19 +287,20 @@ fn (t []Token) contains(val Token) bool {
|
|||
}
|
||||
|
||||
pub fn (t Token) str() string {
|
||||
lit := 't.lit'
|
||||
if t == .number {
|
||||
return 'number'
|
||||
}
|
||||
if t == .chartoken {
|
||||
return '`lit`'
|
||||
return 'char'//'`lit`'
|
||||
}
|
||||
if t == .str {
|
||||
return "'lit'"
|
||||
return 'str' //"'lit'"
|
||||
}
|
||||
/*
|
||||
if t < .plus {
|
||||
return lit // string, number etc
|
||||
}
|
||||
*/
|
||||
return token_str[int(t)]
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ pub const (
|
|||
void_type = Type{'void', 0}
|
||||
int_type = Type{'int', 1}
|
||||
string_type = Type{'string', 2}
|
||||
f64_type = Type{'f64', 3}
|
||||
)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue