├── .gitignore ├── vm ├── heap_memory.go ├── op_code.go └── vm.go ├── ast ├── op.go ├── ast.go ├── class_body.go ├── null_stmnt.go ├── vm_function.go ├── block_stmnt.go ├── number_literal.go ├── string_literal.go ├── name.go ├── array_literal.go ├── parameter_list.go ├── negative_expr.go ├── func.go ├── function.go ├── stone_object.go ├── array_ref.go ├── def_stmnt.go ├── ast_leaf.go ├── while_stmnt.go ├── class_stmnt.go ├── class_info.go ├── ast_list.go ├── dot.go ├── primary.go ├── if_stmnt.go ├── arguments.go └── binary_expr.go ├── environment ├── environment.go ├── native_function.go ├── nested_env.go └── native_env.go ├── lexer ├── lexer_test ├── lexer_test.go └── lexer.go ├── token ├── id_token.go ├── str_token.go ├── num_token.go └── token.go ├── parser ├── parser_test ├── parser_test.go ├── eval_test └── parser.go ├── main.go ├── test └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | stone 2 | .idea/ -------------------------------------------------------------------------------- /vm/heap_memory.go: -------------------------------------------------------------------------------- 1 | package vm 2 | 3 | type HeapMemory interface{ 4 | Read(index int) interface{} 5 | Write(index int, v interface{}) 6 | } 7 | -------------------------------------------------------------------------------- /ast/op.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/token" 5 | ) 6 | 7 | type OP struct { 8 | astLeaf 9 | } 10 | 11 | func NewOP(token token.Token) *OP { 12 | return &OP{astLeaf{token}} 13 | } 14 | -------------------------------------------------------------------------------- /environment/environment.go: -------------------------------------------------------------------------------- 1 | package environment 2 | 3 | type Environment interface { 4 | Get(name string) interface{} 5 | Set(name string, value interface{}) 6 | SetNew(name string, value interface{}) 7 | 8 | Where(name string) Environment 9 | SetOuter(e Environment) 10 | } 11 | -------------------------------------------------------------------------------- /lexer/lexer_test: -------------------------------------------------------------------------------- 1 | // 123adasdf 2 | 3 | abc 12fdasfa3 4 | 5 | "123123asdbd1" 6 | 7 | func add(int x, int y) { 8 | x + y 9 | } 10 | 11 | class Animal { 12 | age = 0 13 | } 14 | 15 | class Dog extends Animal { 16 | def spark() { 17 | "wang wang" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ast/ast.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/environment" 5 | ) 6 | 7 | type ASTree interface { 8 | Child(i int) ASTree 9 | Children() []ASTree 10 | NumChildren() int 11 | Location() string 12 | String() string 13 | 14 | Eval(env environment.Environment, args... interface{}) interface{} 15 | } 16 | -------------------------------------------------------------------------------- /token/id_token.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | type IdToken struct { 4 | token 5 | text string 6 | } 7 | 8 | func NewIdToken(lineNumber int, id string) *IdToken { 9 | return &IdToken{token{lineNumber}, id} 10 | } 11 | 12 | func (self *IdToken) IsIdentifier() bool { 13 | return true 14 | } 15 | 16 | func (self *IdToken) GetText() string { 17 | return self.text 18 | } 19 | -------------------------------------------------------------------------------- /token/str_token.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | type StrToken struct { 4 | token 5 | str string 6 | } 7 | 8 | func NewStrToken(lineNumber int, str string) *StrToken { 9 | return &StrToken{token{lineNumber}, str} 10 | } 11 | 12 | func (self *StrToken) IsString() bool { 13 | return true 14 | } 15 | 16 | func (self *StrToken) GetText() string { 17 | return self.str 18 | } 19 | -------------------------------------------------------------------------------- /ast/class_body.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import "stone/environment" 4 | 5 | type ClassBody struct { 6 | astList 7 | } 8 | 9 | func NewClassBody(list []ASTree) *ClassBody { 10 | return &ClassBody{astList{list}} 11 | } 12 | 13 | func (self *ClassBody) Eval(env environment.Environment, args... interface{}) interface{} { 14 | for _, t := range self.Children() { 15 | t.Eval(env) 16 | } 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /ast/null_stmnt.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/environment" 5 | ) 6 | 7 | type NullStmnt struct { 8 | astList 9 | } 10 | 11 | func NewNullStmnt () *NullStmnt { 12 | return &NullStmnt{astList{nil}} 13 | } 14 | 15 | func (self *NullStmnt) Eval(env environment.Environment, args... interface{}) interface{} { 16 | return nil 17 | } 18 | 19 | func (self *NullStmnt) String() string { 20 | return "(null)" 21 | } 22 | -------------------------------------------------------------------------------- /lexer/lexer_test.go: -------------------------------------------------------------------------------- 1 | package lexer 2 | 3 | import ( 4 | "stone/token" 5 | 6 | "testing" 7 | "os" 8 | "fmt" 9 | "reflect" 10 | ) 11 | 12 | func Test_Lexer_Read(t *testing.T) { 13 | fin, err := os.Open("lexer_test") 14 | if err != nil { 15 | panic(err) 16 | } 17 | 18 | l := NewLexer(fin) 19 | for t := l.Read(); t != token.EOF; t = l.Read() { 20 | fmt.Printf("%v %d %s\n", reflect.TypeOf(t), t.GetLineNumber(), t.GetText()) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ast/vm_function.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import "stone/environment" 4 | 5 | type VMFunction struct { 6 | Function 7 | entry int 8 | } 9 | 10 | func NewVMFunction(name string, 11 | parameters *ParameterList, 12 | body *BlockStmnt, 13 | env environment.Environment, 14 | entry int) *VMFunction { 15 | return &VMFunction{Function{name, parameters, body, env}, entry} 16 | } 17 | 18 | func (self *VMFunction) Entry() int { 19 | return self.entry 20 | } 21 | -------------------------------------------------------------------------------- /token/num_token.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | import "strconv" 4 | 5 | type NumToken struct { 6 | token 7 | value int 8 | } 9 | 10 | func NewNumToken(lineNumber int, value int) *NumToken { 11 | return &NumToken{token{lineNumber}, value} 12 | } 13 | 14 | func (self *NumToken) IsNumber() bool { 15 | return true 16 | } 17 | 18 | func (self *NumToken) GetNumber() int { 19 | return self.value 20 | } 21 | 22 | func (self *NumToken) GetText() string { 23 | return strconv.Itoa(self.value) 24 | } 25 | -------------------------------------------------------------------------------- /ast/block_stmnt.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/environment" 5 | ) 6 | 7 | type BlockStmnt struct { 8 | astList 9 | } 10 | 11 | func NewBlockStmnt(list []ASTree) *BlockStmnt{ 12 | return &BlockStmnt{astList{list}} 13 | } 14 | 15 | func (self *BlockStmnt) Eval(env environment.Environment, args... interface{}) interface{} { 16 | var result interface{} 17 | 18 | // 返回最后一条语句执行结果 19 | for _, value := range self.children { 20 | result = value.Eval(env) 21 | } 22 | return result 23 | } 24 | -------------------------------------------------------------------------------- /ast/number_literal.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/token" 5 | "stone/environment" 6 | ) 7 | 8 | type NumberLiteral struct { 9 | astLeaf 10 | } 11 | 12 | func NewNumberLiteral (token token.Token) *NumberLiteral { 13 | return &NumberLiteral{astLeaf{token}} 14 | } 15 | 16 | func (self *NumberLiteral) Value() int { 17 | return self.token.GetNumber() 18 | } 19 | 20 | func (self *NumberLiteral) Eval(env environment.Environment, args... interface{}) interface{} { 21 | return self.Value() 22 | } 23 | -------------------------------------------------------------------------------- /ast/string_literal.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/token" 5 | "stone/environment" 6 | ) 7 | 8 | type StringLiteral struct { 9 | astLeaf 10 | } 11 | 12 | func NewStringLiteral(token token.Token) *StringLiteral { 13 | return &StringLiteral{astLeaf{token}} 14 | } 15 | 16 | func (self *StringLiteral) Value() string { 17 | return self.Token().GetText() 18 | } 19 | 20 | func (self *StringLiteral) Eval(env environment.Environment, args... interface{}) interface{} { 21 | return self.Value() 22 | } 23 | -------------------------------------------------------------------------------- /ast/name.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/token" 5 | "stone/environment" 6 | ) 7 | 8 | type Name struct { 9 | astLeaf 10 | } 11 | 12 | func NewName(token token.Token) *Name { 13 | return &Name{astLeaf{token}} 14 | } 15 | 16 | func (self *Name) Name() string { 17 | return self.token.GetText() 18 | } 19 | 20 | func (self *Name) Eval(env environment.Environment, args... interface{}) interface{} { 21 | value := env.Get(self.Name()) 22 | if value == nil { 23 | panic("undefined name " + self.Name()) 24 | } else { 25 | return value 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ast/array_literal.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import "stone/environment" 4 | 5 | type ArrayLiteral struct { 6 | astList 7 | } 8 | 9 | func NewArrayLiteral(list []ASTree) *ArrayLiteral { 10 | return &ArrayLiteral{astList{list}} 11 | } 12 | 13 | func (self *ArrayLiteral) Size() int { 14 | return self.NumChildren() 15 | } 16 | 17 | func (self *ArrayLiteral) Eval(env environment.Environment, args... interface{}) interface{} { 18 | res := make([]interface{}, self.NumChildren()) 19 | for index, t := range self.Children() { 20 | res[index] = t.Eval(env) 21 | } 22 | return res 23 | } 24 | -------------------------------------------------------------------------------- /ast/parameter_list.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import "stone/environment" 4 | 5 | /* 6 | 抽象语法树——函数定义参数列表 7 | */ 8 | 9 | type ParameterList struct { 10 | astList 11 | } 12 | 13 | func NewParameterList(list []ASTree) *ParameterList { 14 | return &ParameterList{astList{list}} 15 | } 16 | 17 | func (self *ParameterList) Name(i int) string { 18 | return self.Child(i).(ASTLeaf).Token().GetText() 19 | } 20 | 21 | func (self *ParameterList) Size() int { 22 | return self.NumChildren() 23 | } 24 | 25 | func (self *ParameterList) Eval(env environment.Environment, args... interface{}) interface{} { 26 | index := args[0].(int) 27 | env.SetNew(self.Name(index), args[1]) 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /ast/negative_expr.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "fmt" 5 | "stone/environment" 6 | ) 7 | 8 | type NegativeExpr struct { 9 | astList 10 | } 11 | 12 | func NewNegativeExpr(list []ASTree) *NegativeExpr { 13 | return &NegativeExpr{astList{list}} 14 | } 15 | 16 | func (self *NegativeExpr) Operand() ASTree { 17 | return self.Child(0) 18 | } 19 | 20 | func (self *NegativeExpr) String() string { 21 | return fmt.Sprintf("(-%v)", self.Operand()) 22 | } 23 | 24 | func (self *NegativeExpr) Eval(env environment.Environment, args... interface{}) interface{} { 25 | v := self.Operand().Eval(env) 26 | switch v.(type) { 27 | case int: 28 | return -v.(int) 29 | } 30 | panic("bad type for -") 31 | } 32 | -------------------------------------------------------------------------------- /parser/parser_test: -------------------------------------------------------------------------------- 1 | even = 0 2 | odd = 0 3 | i = 1 4 | while i < 10 { 5 | if i % 2 == 0 { // event number ? 6 | even = even + i 7 | } else { 8 | odd = odd + i 9 | } 10 | i = i + 1 11 | } 12 | event + -odd 13 | 14 | def fib(n) { 15 | if n < 2 { 16 | n 17 | } else { 18 | fib(n - 1) + fib(n - 2) 19 | } 20 | } 21 | fib(10) 22 | 23 | def counter(c) { 24 | func () {c = c + 1} 25 | } 26 | c1 = counter(1) 27 | c1() 28 | counter(2)() 29 | 30 | class Animal { 31 | age = 0 32 | weight = 0 33 | } 34 | 35 | class Dog extends Animal { 36 | def spark() { 37 | "wang wang" 38 | } 39 | } 40 | 41 | a = [1, 2, 3, 4, 5] 42 | a[1] = 2 43 | a[1] 44 | -------------------------------------------------------------------------------- /ast/func.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/environment" 5 | ) 6 | 7 | type Func struct { 8 | astList 9 | } 10 | 11 | func NewFunc(list []ASTree) *Func { 12 | return &Func{astList{list}} 13 | } 14 | 15 | func (self *Func) Parameters() *ParameterList { 16 | return self.Child(0).(*ParameterList) 17 | } 18 | 19 | func (self *Func) Body() *BlockStmnt { 20 | return self.Child(1).(*BlockStmnt) 21 | } 22 | 23 | func (self *Func) String() string { 24 | return "(func " + self.Parameters().String() + " " + self.Body().String() + ")" 25 | } 26 | 27 | func (self *Func) Eval(env environment.Environment, args... interface{}) interface{} { 28 | return NewFunction(self.Parameters().String(), self.Parameters(), self.Body(), env) 29 | } 30 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "stone/lexer" 6 | "stone/environment" 7 | "stone/token" 8 | "stone/parser" 9 | "fmt" 10 | ) 11 | 12 | func usage() { 13 | fmt.Println("[Usage] stone test") 14 | } 15 | 16 | func main() { 17 | defer func(){ 18 | if err := recover(); err!=nil{ 19 | fmt.Println(err) 20 | } 21 | }() 22 | 23 | if os.Args == nil || len(os.Args) != 2 { 24 | usage() 25 | return 26 | } 27 | 28 | fin, err := os.Open(os.Args[1]) 29 | if err != nil { 30 | panic(err) 31 | } 32 | 33 | LEXER := lexer.NewLexer(fin) 34 | PARSER := parser.NewParser(LEXER) 35 | ENV := environment.NewNativeEnv() 36 | 37 | for LEXER.Peek(0) != token.EOF { 38 | stmnt := PARSER.Parse() 39 | stmnt.Eval(ENV) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /environment/native_function.go: -------------------------------------------------------------------------------- 1 | package environment 2 | 3 | import "reflect" 4 | 5 | type NativeFunction struct { 6 | name string 7 | method reflect.Value 8 | numParams int 9 | } 10 | 11 | func NewNativeFunction(name string, method reflect.Value) *NativeFunction { 12 | if method.Kind() != reflect.Func { 13 | panic("not a func") 14 | } 15 | return &NativeFunction{name, method, method.Type().NumIn()} 16 | } 17 | 18 | func (self *NativeFunction) NumParammeters() int { 19 | return self.numParams 20 | } 21 | 22 | func (self *NativeFunction) String() string { 23 | return "" 24 | } 25 | 26 | func (self *NativeFunction) Invoke(in []reflect.Value) interface{} { 27 | reslut := self.method.Call(in) 28 | return reslut[0].Interface() 29 | } 30 | -------------------------------------------------------------------------------- /parser/parser_test.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "testing" 5 | "os" 6 | "fmt" 7 | "stone/lexer" 8 | "stone/token" 9 | "stone/environment" 10 | ) 11 | 12 | func Test_Parser(t *testing.T) { 13 | fin, err := os.Open("parser_test") 14 | if err != nil { 15 | panic(err) 16 | } 17 | 18 | l := lexer.NewLexer(fin) 19 | p := NewParser(l) 20 | for l.Peek(0) != token.EOF { 21 | fmt.Println(p.program().String()) 22 | } 23 | } 24 | 25 | func Test_Eval(t *testing.T) { 26 | fin, err := os.Open("test") 27 | if err != nil { 28 | panic(err) 29 | } 30 | 31 | l := lexer.NewLexer(fin) 32 | p := NewParser(l) 33 | e := environment.NewNativeEnv() 34 | for l.Peek(0) != token.EOF { 35 | program := p.program() 36 | result := program.Eval(e) 37 | fmt.Println(result) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ast/function.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/environment" 5 | ) 6 | 7 | type Function struct { 8 | name string 9 | parameters *ParameterList 10 | body *BlockStmnt 11 | env environment.Environment 12 | } 13 | 14 | func NewFunction(name string, parameters *ParameterList, body *BlockStmnt, env environment.Environment) *Function { 15 | return &Function{name, parameters, body, env} 16 | } 17 | 18 | func (self *Function) Parameters() *ParameterList { 19 | return self.parameters 20 | } 21 | 22 | func (self *Function) Body() *BlockStmnt { 23 | return self.body 24 | } 25 | 26 | func (self *Function) MakeEnv() environment.Environment { 27 | e := environment.NewNestedEnv() 28 | e.SetOuter(self.env) 29 | return e 30 | } 31 | 32 | func (self *Function) String() string { 33 | return "" 34 | } 35 | -------------------------------------------------------------------------------- /ast/stone_object.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/environment" 5 | "fmt" 6 | ) 7 | 8 | type StoneObject struct { 9 | env environment.Environment 10 | } 11 | 12 | func NewStoneObject(e environment.Environment) *StoneObject { 13 | return &StoneObject{e} 14 | } 15 | 16 | func (self *StoneObject) String() string { 17 | return fmt.Sprintf("", self) 18 | } 19 | 20 | func (self *StoneObject) Read(name string) interface{} { 21 | return self.GetEnv(name).Get(name) 22 | } 23 | 24 | func (self *StoneObject) Write(name string, value interface{}) { 25 | self.GetEnv(name).SetNew(name, value) 26 | } 27 | 28 | func (self *StoneObject) GetEnv(name string) environment.Environment { 29 | e := self.env.Where(name) 30 | if e == self.env { 31 | return e 32 | } else { 33 | panic("class member access error") 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /token/token.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | /* 4 | 单词接口 5 | 数字,字符串,标识符三种类型 6 | */ 7 | 8 | var EOF Token = &token{-1} 9 | var EOL string = "\\n" 10 | 11 | type Token interface { 12 | GetLineNumber() int 13 | GetNumber() int 14 | GetText() string 15 | IsIdentifier() bool 16 | IsNumber() bool 17 | IsString() bool 18 | } 19 | 20 | type token struct { 21 | lineNumber int 22 | } 23 | 24 | func (self *token) GetLineNumber() int { 25 | return self.lineNumber 26 | } 27 | 28 | func (self *token) GetNumber() int { 29 | panic("not number token") 30 | } 31 | 32 | func (self *token) GetText() string { 33 | return "" 34 | } 35 | 36 | func (self *token) IsIdentifier() bool { 37 | return false 38 | } 39 | 40 | func (self *token) IsNumber() bool { 41 | return false 42 | } 43 | 44 | func (self *token) IsString() bool { 45 | return false 46 | } 47 | 48 | -------------------------------------------------------------------------------- /ast/array_ref.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/environment" 5 | "reflect" 6 | ) 7 | 8 | type ArrayRef struct { 9 | astList 10 | } 11 | 12 | func NewArrayRef(list []ASTree) *ArrayRef { 13 | return &ArrayRef{astList{list}} 14 | } 15 | 16 | func (self *ArrayRef) Index() ASTree { 17 | return self.Child(0) 18 | } 19 | 20 | func (self *ArrayRef) String() string { 21 | return "[" + self.Index().String() + "]" 22 | } 23 | 24 | func (self *ArrayRef) Eval(env environment.Environment, args... interface{}) interface{} { 25 | if value, ok := args[0].([]interface{}); ok { 26 | index := self.Index().Eval(env) 27 | if reflect.TypeOf(index).Kind() == reflect.Int && index.(int) >= 0 && index.(int) < len(value){ 28 | return (value)[index.(int)] 29 | } else { 30 | panic("bad index") 31 | } 32 | } else { 33 | panic("bad array access") 34 | } 35 | } -------------------------------------------------------------------------------- /ast/def_stmnt.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import "stone/environment" 4 | 5 | type DefStmnt struct { 6 | astList 7 | } 8 | 9 | func NewDefStmnt(list []ASTree) *DefStmnt { 10 | return &DefStmnt{astList{list}} 11 | } 12 | 13 | func (self *DefStmnt) Name() string { 14 | return self.Child(0).(ASTLeaf).Token().GetText() 15 | } 16 | 17 | func (self *DefStmnt) Parameters() *ParameterList { 18 | return self.Child(1).(*ParameterList) 19 | } 20 | 21 | func (self *DefStmnt) Body() *BlockStmnt { 22 | return self.Child(2).(*BlockStmnt) 23 | } 24 | 25 | func (self *DefStmnt) String() string { 26 | return "(def " + self.Name() + " " + self.Parameters().String() + self.Body().String() + ")" 27 | } 28 | 29 | func (self *DefStmnt) Eval(env environment.Environment, args... interface{}) interface{} { 30 | env.SetNew(self.Name(), NewFunction(self.Name(), self.Parameters(), self.Body(), env)) 31 | return "" 32 | } 33 | -------------------------------------------------------------------------------- /ast/ast_leaf.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/token" 5 | "strconv" 6 | "stone/environment" 7 | ) 8 | 9 | type ASTLeaf interface { 10 | ASTree 11 | Token() token.Token 12 | } 13 | 14 | type astLeaf struct { 15 | token token.Token 16 | } 17 | 18 | func (self *astLeaf) Child(i int) ASTree { 19 | panic("index out of range") 20 | } 21 | 22 | func (self *astLeaf) NumChildren() int{ 23 | return 0 24 | } 25 | 26 | func (self *astLeaf) Children() []ASTree { 27 | return nil 28 | } 29 | 30 | func (self *astLeaf) Location() string { 31 | return "at line " + strconv.Itoa(self.token.GetLineNumber()) 32 | } 33 | 34 | func (self *astLeaf) String() string { 35 | return self.token.GetText() 36 | } 37 | 38 | func (self *astLeaf) Eval(env environment.Environment, args... interface{}) interface{} { 39 | panic("cannot eval " + self.String()) 40 | } 41 | 42 | func (self *astLeaf) Token() token.Token { 43 | return self.token 44 | } 45 | -------------------------------------------------------------------------------- /ast/while_stmnt.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "reflect" 5 | "stone/environment" 6 | ) 7 | 8 | type WhileStmnt struct { 9 | astList 10 | } 11 | 12 | func NewWhileStmnt(list []ASTree) *WhileStmnt { 13 | return &WhileStmnt{astList{list}} 14 | } 15 | 16 | func (self *WhileStmnt) Condition() ASTree { 17 | return self.Child(0) 18 | } 19 | 20 | func (self *WhileStmnt) Body() ASTree { 21 | return self.Child(1) 22 | } 23 | 24 | func (self *WhileStmnt) String() string { 25 | b := self.Body() 26 | return "(while " + self.Condition().String() + " " + b.String() + ")" 27 | } 28 | 29 | func (self *WhileStmnt) Eval(env environment.Environment, args... interface{}) interface{} { 30 | var result interface{} 31 | for true { 32 | c := self.Condition().Eval(env) 33 | if reflect.TypeOf(c).Kind() == reflect.Int && c.(int) == FALSE { 34 | return result 35 | } else { 36 | result = self.Body().Eval(env) 37 | } 38 | } 39 | panic("runtime error") 40 | } 41 | -------------------------------------------------------------------------------- /ast/class_stmnt.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import "stone/environment" 4 | 5 | type ClassStmnt struct { 6 | astList 7 | } 8 | 9 | func NewClassStmnt(list []ASTree) *ClassStmnt { 10 | return &ClassStmnt{astList{list}} 11 | } 12 | 13 | func (self *ClassStmnt) Name() string { 14 | return self.Child(0).(*Name).token.GetText() 15 | } 16 | 17 | func (self *ClassStmnt) SuperClass() string { 18 | if self.NumChildren() < 3 { 19 | return "" 20 | } else { 21 | return self.Child(2).(*Name).token.GetText() 22 | } 23 | } 24 | 25 | func (self *ClassStmnt) Body() *ClassBody { 26 | return self.Child(1).(*ClassBody) 27 | } 28 | 29 | func (self *ClassStmnt) String() string { 30 | return "(class " + self.Name() + " " + self.SuperClass() + " " + self.Body().String() + ")" 31 | } 32 | 33 | func (self *ClassStmnt) Eval(env environment.Environment, args... interface{}) interface{} { 34 | ci := NewClassInfo(self, env) 35 | env.Set(self.Name(), ci) 36 | return self.Name() 37 | } 38 | -------------------------------------------------------------------------------- /ast/class_info.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import "stone/environment" 4 | 5 | type ClassInfo struct { 6 | def *ClassStmnt 7 | env environment.Environment 8 | super *ClassInfo 9 | } 10 | 11 | func NewClassInfo(def *ClassStmnt, env environment.Environment) *ClassInfo { 12 | obj := env.Get(def.SuperClass()) 13 | if obj == nil { 14 | return &ClassInfo{def, env, nil} 15 | } else if super, ok := obj.(*ClassInfo); ok { 16 | return &ClassInfo{def, env, super} 17 | } else { 18 | panic("super not a class") 19 | } 20 | } 21 | 22 | func (self *ClassInfo) Name() string { 23 | return self.def.Name() 24 | } 25 | 26 | func (self *ClassInfo) SuperClass() *ClassInfo { 27 | return self.super 28 | } 29 | 30 | func (self *ClassInfo) Body() *ClassBody { 31 | return self.def.Body() 32 | } 33 | 34 | func (self *ClassInfo) Environment() environment.Environment { 35 | return self.env 36 | } 37 | 38 | func (self *ClassInfo) String() string { 39 | return "" 40 | } 41 | -------------------------------------------------------------------------------- /environment/nested_env.go: -------------------------------------------------------------------------------- 1 | package environment 2 | 3 | type NestedEnv struct { 4 | values map[string]interface{} 5 | outer Environment 6 | } 7 | 8 | func NewNestedEnv() *NestedEnv { 9 | return &NestedEnv{make(map[string]interface{}), nil} 10 | } 11 | 12 | func (self *NestedEnv) Get(name string) interface{} { 13 | v, ok := self.values[name] 14 | if !ok && self.outer != nil { 15 | return self.outer.Get(name) 16 | } else { 17 | return v 18 | } 19 | } 20 | 21 | func (self *NestedEnv) SetNew(name string, value interface{}) { 22 | self.values[name] = value 23 | } 24 | 25 | func (self *NestedEnv) Set(name string, value interface{}) { 26 | e := self.Where(name) 27 | if e == nil { 28 | e = self 29 | } 30 | e.SetNew(name, value) 31 | } 32 | 33 | func (self *NestedEnv) Where(name string) Environment { 34 | _, ok := self.values[name] 35 | if ok { 36 | return self 37 | } else if self.outer != nil { 38 | return self.outer.Where(name) 39 | } else { 40 | return nil 41 | } 42 | } 43 | 44 | func (self *NestedEnv) SetOuter(e Environment) { 45 | self.outer = e 46 | } 47 | -------------------------------------------------------------------------------- /ast/ast_list.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "bytes" 5 | "stone/environment" 6 | ) 7 | 8 | type ASTList interface { 9 | ASTree 10 | } 11 | 12 | type astList struct { 13 | children []ASTree 14 | } 15 | 16 | func (self *astList) Child(i int) ASTree { 17 | return self.children[i] 18 | } 19 | 20 | func (self *astList) NumChildren() int{ 21 | return len(self.children) 22 | } 23 | 24 | func (self *astList) Children() []ASTree { 25 | return self.children 26 | } 27 | 28 | func (self *astList) Location() string { 29 | for _, t := range self.children { 30 | if t.Location() != "" { 31 | return t.Location() 32 | } 33 | } 34 | return "" 35 | } 36 | 37 | func (self *astList) String() string { 38 | var buf bytes.Buffer 39 | buf.WriteString("(") 40 | sep := "" 41 | for _, t := range self.children { 42 | buf.WriteString(sep) 43 | buf.WriteString(t.String()) 44 | sep = " " 45 | } 46 | buf.WriteString(")") 47 | return buf.String() 48 | } 49 | 50 | func (self *astList) Eval(env environment.Environment, args... interface{}) interface{} { 51 | panic("cannot eval " + self.String()) 52 | } 53 | -------------------------------------------------------------------------------- /ast/dot.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import "stone/environment" 4 | 5 | type Dot struct { 6 | astList 7 | } 8 | 9 | func NewDot(list []ASTree) *Dot { 10 | return &Dot{astList{list}} 11 | } 12 | 13 | func (self *Dot) Name() string { 14 | return self.Child(0).(*Name).token.GetText() 15 | } 16 | 17 | func (self *Dot) String() string { 18 | return "." + self.Name() 19 | } 20 | 21 | func (self *Dot) Eval(env environment.Environment, args... interface{}) interface{} { 22 | member := self.Name() 23 | if ci, ok := args[0].(*ClassInfo); ok { 24 | if member == "new" { 25 | e := environment.NewNestedEnv() 26 | e.SetOuter(ci.Environment()) 27 | obj := NewStoneObject(e) 28 | e.SetNew("this", obj) 29 | self.initObject(ci, e) 30 | return obj 31 | } else { 32 | panic(member + " not a class func") 33 | } 34 | } else if so, ok := args[0].(*StoneObject); ok { 35 | return so.Read(member) 36 | } else { 37 | panic("unkown ." + self.Name()) 38 | } 39 | } 40 | 41 | func (self *Dot) initObject(ci *ClassInfo, env environment.Environment) { 42 | if ci.SuperClass() != nil { 43 | self.initObject(ci.SuperClass(), env) 44 | } 45 | ci.Body().Eval(env) 46 | } 47 | -------------------------------------------------------------------------------- /ast/primary.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/environment" 5 | ) 6 | 7 | type Primary struct { 8 | astList 9 | } 10 | 11 | func NewPrimary(list []ASTree) *Primary { 12 | return &Primary{astList{list}} 13 | } 14 | 15 | func (self *Primary) Name() string { 16 | return self.Child(0).(*Name).Token().GetText() 17 | } 18 | 19 | func (self *Primary) HasPostfix(index int) bool { 20 | return index < self.NumChildren() 21 | } 22 | 23 | func (self *Primary) Eval(env environment.Environment, args... interface{}) interface{} { 24 | return self.Eval2(0, env, args) 25 | } 26 | 27 | func (self *Primary) Eval2(offset int, env environment.Environment, args... interface{}) interface{} { 28 | result := self.Child(0).(*Name).Eval(env) 29 | 30 | for index := 1; self.HasPostfix(index + offset); index++ { 31 | a := self.Child(index) 32 | if args, ok := a.(*Arguments); ok { 33 | result = args.Eval(env, result) 34 | } else if dot, ok := a.(*Dot); ok { 35 | result = dot.Eval(env, result) 36 | } else if arrref, ok := a.(*ArrayRef); ok{ 37 | result = arrref.Eval(env, result) 38 | } else { 39 | panic("error postfix") 40 | } 41 | } 42 | return result 43 | } 44 | -------------------------------------------------------------------------------- /ast/if_stmnt.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "reflect" 5 | "stone/environment" 6 | ) 7 | 8 | type IfStmnt struct { 9 | astList 10 | } 11 | 12 | func NewIfStmnt(list []ASTree) *IfStmnt{ 13 | return &IfStmnt{astList{list}} 14 | } 15 | 16 | func (self *IfStmnt) Condition() ASTree{ 17 | return self.Child(0) 18 | } 19 | 20 | func (self *IfStmnt) ThenBlock() ASTree { 21 | return self.Child(1) 22 | } 23 | 24 | func (self *IfStmnt) ElseBlock() ASTree { 25 | if self.NumChildren() > 2 { 26 | return self.Child(2) 27 | } else { 28 | return nil 29 | } 30 | } 31 | 32 | func (self *IfStmnt) String() string { 33 | result := "(if " + self.Condition().String() + " " + self.ThenBlock().String() 34 | if self.ElseBlock() != nil { 35 | result += " else " + self.ElseBlock().String() 36 | } 37 | return result + ")" 38 | } 39 | 40 | func (self *IfStmnt) Eval(env environment.Environment, args... interface{}) interface{} { 41 | c := self.Condition().Eval(env) 42 | if reflect.TypeOf(c).Kind() == reflect.Int && c.(int) == TRUE { 43 | return self.ThenBlock().Eval(env) 44 | } else { 45 | e := self.ElseBlock() 46 | if e == nil { 47 | return 0 48 | } else { 49 | return e.Eval(env) 50 | } 51 | } 52 | } 53 | 54 | 55 | -------------------------------------------------------------------------------- /parser/eval_test: -------------------------------------------------------------------------------- 1 | // 循环判断 2 | even = 0 3 | odd = 0 4 | sum = 0 5 | i = 1 6 | while i < 10 { 7 | if i % 2 == 0 { // event number ? 8 | even = even + i 9 | } else { 10 | odd = odd + i 11 | } 12 | sum = sum + (i + 1) 13 | i = i + 1 14 | } 15 | even 16 | -odd 17 | 18 | // 字符串数字相加 19 | "sum = " + sum 20 | "Hello " + "World " + sum 21 | 22 | // 函数 23 | def fib(n) { 24 | if n < 2 { 25 | n 26 | } else { 27 | fib(n - 1) + fib(n - 2) 28 | } 29 | } 30 | "fib(10) == " + fib(10) 31 | 32 | // 闭包 33 | def add(c) { 34 | func (x) { c = c + x } 35 | } 36 | add(1)(10) 37 | c1 = add(1) 38 | c1(2) 39 | 40 | // 内置函数 41 | size("test") 42 | "print return " + itoa(print("Hello " + "World!\n")) 43 | timestamp() 44 | atoi("12345") 45 | 46 | a = [1, 2, 3, 4, 5] 47 | a[1] = 2 48 | a[1] 49 | a[0] 50 | a[4] 51 | 52 | class Animal { 53 | age = 0 54 | weight = 100 55 | c = [1, 3, 5] 56 | 57 | def info() { 58 | "father info" 59 | } 60 | 61 | def father() { 62 | "father test" 63 | } 64 | } 65 | 66 | class Dog extends Animal { 67 | def info() { 68 | "age = " + age + "; weight = " + weight 69 | } 70 | } 71 | 72 | d = Dog.new 73 | d.age = 1 74 | d.info() 75 | d.weight 76 | d.father() 77 | 78 | d.c 79 | d.info 80 | 81 | c = d 82 | -------------------------------------------------------------------------------- /ast/arguments.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "stone/environment" 5 | "reflect" 6 | ) 7 | 8 | type Arguments struct { 9 | astList 10 | } 11 | 12 | func NewArguments(list []ASTree) *Arguments { 13 | return &Arguments{astList{list}} 14 | } 15 | 16 | func (self *Arguments) Size() int { 17 | return self.NumChildren() 18 | } 19 | 20 | func (self *Arguments) Eval(callerEnv environment.Environment, args... interface{}) interface{} { 21 | value := reflect.ValueOf(args[0]) 22 | if value.Type().ConvertibleTo(reflect.TypeOf((*Function)(nil))) { 23 | fnc := args[0].(*Function) 24 | params := fnc.Parameters() 25 | if params.Size() != self.Size() { 26 | panic("bad number of arguments") 27 | } 28 | 29 | newEnv := fnc.MakeEnv() 30 | for num, a := range self.Children() { 31 | params.Eval(newEnv, num, a.Eval(callerEnv)) 32 | } 33 | return fnc.Body().Eval(newEnv) 34 | } else if value.Type().ConvertibleTo(reflect.TypeOf((*environment.NativeFunction)(nil))) { 35 | fnc := args[0].(*environment.NativeFunction) 36 | nparams := fnc.NumParammeters() 37 | if nparams != self.Size() { 38 | panic("bad number of arguments") 39 | } 40 | params := make([]reflect.Value, nparams) 41 | for i := 0; i < len(params); i++ { 42 | params[i] = reflect.ValueOf(self.Child(i).Eval(callerEnv)) 43 | } 44 | return fnc.Invoke(params) 45 | } else { 46 | panic("bad function") 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /vm/op_code.go: -------------------------------------------------------------------------------- 1 | package vm 2 | 3 | 4 | const ( 5 | NULL int8 = iota 6 | ICONST 7 | BCONST // load int8 8 | SCONST // load string 9 | MOVE 10 | GMOVE // move global variable 11 | IFZERO 12 | GOTO 13 | CALL 14 | RETURN 15 | SAVE // save all registers 16 | RESTORE // restore all rigisters 17 | NEG 18 | ADD 19 | SUB 20 | MUL 21 | DIV 22 | REM 23 | EQUAL 24 | MORE 25 | LESS 26 | ) 27 | 28 | const ( 29 | MAX_INT8 = 1 << 7 - 1 30 | MAX_INT16 = 1 << 15 - 1 31 | ) 32 | 33 | func encodeRegister(reg int) int8 { 34 | if reg > NUM_OF_REG { 35 | panic("to many registers required") 36 | } else { 37 | return int8(-(reg + 1)) 38 | } 39 | } 40 | 41 | func decodeRegister(operand int8) int { 42 | return int(-1 - operand) 43 | } 44 | 45 | func encodeOffset(offset int) int8 { 46 | if offset > MAX_INT8 { 47 | panic("too big int8 offset") 48 | } else { 49 | return int8(offset) 50 | } 51 | } 52 | 53 | func decodeOffset(operand int8) int { 54 | return int(operand) 55 | } 56 | 57 | func encodeShortOffset(offset int) int16 { 58 | if offset > MAX_INT16 { 59 | panic("too big int8 offset") 60 | } else { 61 | return int16(offset) 62 | } 63 | } 64 | 65 | func decodeShortOffset(operand int16) int { 66 | return int(operand) 67 | } 68 | 69 | func isRegister(operand int8) bool { 70 | return operand < 0 71 | } 72 | 73 | func isOffset(operand int8) bool { 74 | return operand >= 0 75 | } 76 | -------------------------------------------------------------------------------- /environment/native_env.go: -------------------------------------------------------------------------------- 1 | package environment 2 | 3 | import ( 4 | 5 | "fmt" 6 | "strconv" 7 | "time" 8 | "bufio" 9 | "os" 10 | "reflect" 11 | ) 12 | 13 | type NativeEnv struct { 14 | *NestedEnv 15 | } 16 | 17 | func NewNativeEnv() *NativeEnv { 18 | env := NewNestedEnv() 19 | appendNatives(env) 20 | return &NativeEnv{env} 21 | } 22 | 23 | func appendNatives(env Environment) { 24 | append1(env, "read", read) 25 | append1(env, "print", print) 26 | append1(env, "size", size) 27 | append1(env, "atoi", atoi) 28 | append1(env, "itoa", itoa) 29 | append1(env, "timestamp", timestamp) 30 | } 31 | 32 | func append1(env Environment, name string, fun interface{}) { 33 | env.Set(name, NewNativeFunction(name, reflect.ValueOf(fun))) 34 | } 35 | 36 | // native methods 37 | 38 | var scanner *bufio.Scanner = bufio.NewScanner(os.Stdin) 39 | func read() string { 40 | scanner.Split(bufio.ScanWords) 41 | if scanner.Scan() { 42 | return scanner.Text() 43 | } else { 44 | return "" 45 | } 46 | } 47 | 48 | func print(obj interface{}) int { 49 | fmt.Print(obj) 50 | return 0 51 | } 52 | 53 | func size(s string) int { 54 | return len(s) 55 | } 56 | 57 | func atoi(s string) int { 58 | x, err := strconv.Atoi(s) 59 | if err != nil { 60 | panic("atoi error") 61 | } 62 | return x 63 | } 64 | 65 | func itoa(i int) string { 66 | x := strconv.Itoa(i) 67 | return x 68 | } 69 | 70 | func timestamp() int { 71 | return int(time.Now().Unix()) 72 | } 73 | -------------------------------------------------------------------------------- /test: -------------------------------------------------------------------------------- 1 | // 分支条件 2 | even = 0 3 | odd = 0 4 | sum = 0 5 | i = 1 6 | while i < 10 { 7 | if i % 2 == 0 { // event number ? 8 | even = even + i 9 | } else { 10 | odd = odd + i 11 | } 12 | sum = sum + (i + 1) 13 | i = i + 1 14 | } 15 | print(even) 16 | print("\n") 17 | print(-odd) 18 | print("\n") 19 | 20 | // 字符串数字相加 21 | print("sum = " + sum) 22 | print("\n") 23 | print("Hello " + "World " + sum) 24 | print("\n") 25 | 26 | // 函数 27 | def fib(n) { 28 | if n < 2 { 29 | n 30 | } else { 31 | fib(n - 1) + fib(n - 2) 32 | } 33 | } 34 | print("fib(10) == " + fib(10)) 35 | print("\n") 36 | 37 | // 闭包 38 | def add(c) { 39 | func (x) { c = c + x } 40 | } 41 | print(add(1)(10)) 42 | print("\n") 43 | print(c1 = add(1)) 44 | print("\n") 45 | print(c1(2)) 46 | print("\n") 47 | 48 | // 内置函数 49 | print(size("test")) 50 | print("\n") 51 | print("print return " + itoa(print("Hello " + "World!\n"))) 52 | print("\n") 53 | print(timestamp()) 54 | print("\n") 55 | print(atoi("12345")) 56 | print("\n") 57 | 58 | // 数组 59 | print(a = [1, 2, 3, 4, 5]) 60 | print("\n") 61 | a[1] = 2 62 | print(a[1]) 63 | print("\n") 64 | a[0] 65 | a[4] 66 | 67 | // 类 68 | class Animal { 69 | age = 0 70 | weight = 100 71 | c = [1, 3, 5] 72 | 73 | def info() { 74 | "father info" 75 | } 76 | 77 | def father() { 78 | "father test" 79 | } 80 | } 81 | 82 | // 继承 83 | class Dog extends Animal { 84 | def info() { 85 | "age = " + age + "; weight = " + weight 86 | } 87 | } 88 | 89 | d = Dog.new 90 | d.age = 1 91 | print(d.info()) 92 | print("\n") 93 | print(d.weight) 94 | print("\n") 95 | print(d.father()) 96 | print("\n") 97 | 98 | d.c 99 | d.info 100 | 101 | c = d 102 | print(d) 103 | print("\n") 104 | print(c) 105 | print("\n") 106 | 107 | // 终端输入 108 | while 1 { 109 | print(read()) 110 | } 111 | -------------------------------------------------------------------------------- /lexer/lexer.go: -------------------------------------------------------------------------------- 1 | package lexer 2 | 3 | import ( 4 | "stone/token" 5 | 6 | "regexp" 7 | "bufio" 8 | "io" 9 | "strconv" 10 | "bytes" 11 | ) 12 | 13 | /* 14 | 词法分析器 15 | 源文件被分割为——数字,字符串,标识符序列 16 | */ 17 | 18 | // 注释|数字|字符串|标识符(且不许为空) 19 | var regexPat string = 20 | `\s*(?:(//.*)|([0-9]+)|"((?:\\"|\\\\|\\n|[^"])*)"|([A-Z_a-z][A-Z_a-z0-9]*|==|<=|>=|&&|\|\||[[:punct:]]))|\s+` 21 | 22 | type Lexer struct { 23 | queue []token.Token 24 | hasMore bool 25 | pattern *regexp.Regexp 26 | reader *bufio.Scanner 27 | lineNo int 28 | } 29 | 30 | func NewLexer(r io.Reader) *Lexer{ 31 | return &Lexer{nil, true, regexp.MustCompile(regexPat), bufio.NewScanner(r), 0} 32 | } 33 | 34 | func (self *Lexer) Read() token.Token { 35 | if self.fillQueue(0) { 36 | defer func() {self.queue = self.queue[1:]}() 37 | return self.queue[0] 38 | } else { 39 | return token.EOF 40 | } 41 | } 42 | 43 | func (self *Lexer) Peek(i int) token.Token { 44 | if self.fillQueue(i) { 45 | return self.queue[i] 46 | } else { 47 | return token.EOF 48 | } 49 | } 50 | 51 | func (self *Lexer) fillQueue(i int) bool { 52 | for i >= len(self.queue) { 53 | if self.hasMore { 54 | self.readLine() 55 | } else { 56 | return false 57 | } 58 | } 59 | return true 60 | } 61 | 62 | func (self *Lexer) readLine() { 63 | if self.reader.Scan() { 64 | self.lineNo++ 65 | line := self.reader.Text() 66 | groups := self.pattern.FindStringSubmatch(line) 67 | for len(line) > 0 { 68 | if (groups == nil) { 69 | panic("lexer error at line " + strconv.Itoa(self.lineNo) + " " + line) 70 | } 71 | self.addToken(groups) 72 | line = line[len(groups[0]):] 73 | groups = self.pattern.FindStringSubmatch(line) 74 | } 75 | self.queue = append(self.queue, token.NewIdToken(self.lineNo, token.EOL)) 76 | } else { 77 | self.hasMore = false 78 | } 79 | } 80 | 81 | func (self *Lexer) addToken(groups []string) { 82 | if groups[1] != "" { 83 | 84 | } else if groups[2] != "" { 85 | number, err := strconv.Atoi(groups[2]) 86 | if err != nil { 87 | panic("Atoi error") 88 | } 89 | self.queue = append(self.queue, token.NewNumToken(self.lineNo, number)) 90 | } else if groups[3] != "" { 91 | self.queue = append(self.queue, token.NewStrToken(self.lineNo, self.toStringLiteral(groups[3]))) 92 | } else if groups[4] != "" { 93 | self.queue = append(self.queue, token.NewIdToken(self.lineNo, groups[4])) 94 | } 95 | //white space 96 | } 97 | 98 | func (self *Lexer) toStringLiteral(s string) string { 99 | var buffer bytes.Buffer 100 | for i := 0; i < len(s); i++ { 101 | c := s[i] 102 | if c == '\\' && i + 1 < len(s) { 103 | c2 := s[i + 1] 104 | if c2 == '"' || c2 == '\\' { 105 | i++ 106 | c = s[i] 107 | } else if c2 == 'n' { 108 | i++ 109 | c = '\n' 110 | } 111 | } 112 | buffer.WriteByte(c) 113 | } 114 | return buffer.String() 115 | } 116 | 117 | func (self *Lexer) GetLineNumber() string { 118 | return strconv.Itoa(self.lineNo) 119 | } 120 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # stone 2 | 3 | A Scripting Language based on Golang 4 | 5 | ## Specification 6 | ### Types 7 | 8 | ``` 9 | comments Comments are ignored by the interpreter 10 | // ... 11 | 12 | int The set of all signed 32-bit integers (-2147483648 to 2147483647) 13 | i = 123 14 | 15 | string A string type represents the set of string values 16 | s = "HelloWorld" 17 | 18 | function A function type denotes the set of all functions with the same parameter and result types 19 | The return value is the result of the last statement 20 | 21 | add = func(a, b) { a + b } [ Anonymous function ] 22 | 23 | def max (a, b) { 24 | if a > b { 25 | a 26 | } else { 27 | b 28 | } 29 | } 30 | 31 | array An array is a numbered sequence of elements of a single type 32 | a = [1, 2, 3, 4, 5] 33 | 34 | object See "Object Oriented Programming" 35 | ``` 36 | 37 | ### Operators 38 | 39 | ``` 40 | + A string can be added to an integer and returned as a string 41 | "HelloWorld" + 123 == "HelloWorld123" 42 | 43 | - Only integer types are supported 44 | * Only integer types are supported 45 | / Only integer types are supported 46 | > Only integer types are supported 47 | < Only integer types are supported 48 | 49 | == Returns true if the variable name points to the same object 50 | If operands are the basic data type, it depends on whether the values are equal or not 51 | 52 | = Initialize the variable 53 | ``` 54 | 55 | ### Statements 56 | 57 | ``` 58 | if if a > b { 59 | max = a 60 | } else { 61 | max = b 62 | } 63 | 64 | while while a > b { 65 | print "HelloWorld!" 66 | } 67 | ``` 68 | 69 | ### Clousure 70 | 71 | ``` 72 | def add(c) { 73 | func(x) {c + x} 74 | } 75 | 76 | c1 = add(1) 77 | print(c1(2)) 78 | print("\n") 79 | print(c1(1)) 80 | 81 | Output: 82 | 3 83 | 4 84 | ``` 85 | 86 | ### Parameter Passing 87 | 88 | ``` 89 | The base data type is passed as a value 90 | Arrays and objects are passed as references 91 | ``` 92 | 93 | ### Object Oriented Programming 94 | 95 | ``` 96 | class def Animal { 97 | age = 0 98 | def getAge { 99 | "Animal age = " + age 100 | } 101 | } 102 | 103 | def Dog extends Animal { 104 | sex = "girl" 105 | def getAge { 106 | "Dog age == " + age 107 | } 108 | def getSex { 109 | "Dog sex == " + sex 110 | } 111 | } 112 | 113 | d = Dog.new 114 | d.sex = "boy" 115 | print(d.getAge()) 116 | print("\n") 117 | print(d.getSex()) 118 | 119 | Output: 120 | "Dog age == 0" 121 | "Dog sex == boy" 122 | ``` 123 | 124 | ### Built-in functions 125 | 126 | ``` 127 | read() string Read a word from terminal 128 | print(any[any type]) int Show "any" in terminal 129 | size(s[string]) int Return length of string 130 | atoi(s[string]) int Convert string to int 131 | itoa(i[int]) string Convert int to string 132 | timestamp() int Return UNIX timpstamp 133 | ``` 134 | 135 | ## Requirement 136 | 137 | * Golang 138 | 139 | ## Build 140 | 141 | ``` 142 | cp -r stone $GOPATH/src 143 | cd $GOPATH/src/stone 144 | go build 145 | ``` 146 | 147 | ## Usage 148 | ``` 149 | ./stone [source file name] 150 | ``` 151 | 152 | ## TODO 153 | - Virtual Machine 154 | 155 | ## References 156 | - 两周自制脚本语言 157 | - The Go Programming Language 158 | -------------------------------------------------------------------------------- /ast/binary_expr.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "reflect" 5 | "strconv" 6 | "stone/environment" 7 | ) 8 | 9 | const ( 10 | TRUE = 1 11 | FALSE = 0 12 | ) 13 | 14 | type BinaryExpr struct { 15 | astList 16 | } 17 | 18 | func NewBinaryExpr(list []ASTree) *BinaryExpr { 19 | return &BinaryExpr{astList{list}} 20 | } 21 | 22 | func (self *BinaryExpr) Left() ASTree{ 23 | return self.Child(0) 24 | } 25 | 26 | func (self *BinaryExpr) Operator() string { 27 | op, ok := self.Child(1).(*OP) 28 | if ok { 29 | return op.token.GetText() 30 | } else { 31 | panic("bad operator") 32 | } 33 | } 34 | 35 | func (self *BinaryExpr) Right() ASTree { 36 | return self.Child(2) 37 | } 38 | 39 | func (self *BinaryExpr) Eval(env environment.Environment, args... interface{}) interface{} { 40 | op := self.Operator() 41 | if op == "=" { 42 | right := self.Right().Eval(env) 43 | return self.computeAssign(env, right) 44 | } else { 45 | left := self.Left().Eval(env) 46 | right := self.Right().Eval(env) 47 | return self.computeOp(left, op, right) 48 | } 49 | } 50 | 51 | func (self *BinaryExpr) computeAssign(env environment.Environment, right interface{}) interface{} { 52 | left := self.Left() 53 | 54 | if name, ok := left.(*Name); ok { 55 | env.Set(name.Name(), right) 56 | return right 57 | } else if primary, ok := left.(*Primary); ok{ 58 | obj := primary.Eval2(1, env) 59 | if so, ok := obj.(*StoneObject); ok { 60 | dot := primary.Child(primary.NumChildren() - 1).(*Dot) 61 | so.Write(dot.Name(), right) 62 | return right 63 | } else if arr, ok := obj.([]interface{}); ok { 64 | arrref := primary.Child(primary.NumChildren() - 1).(*ArrayRef) 65 | index := arrref.Index().Eval(env).(int) 66 | if index >= 0 && index < len(arr) { 67 | arr[index] = right 68 | return right 69 | } else { 70 | panic("index out of range") 71 | } 72 | } else { 73 | panic("not left value") 74 | } 75 | } else { 76 | panic("not left value") 77 | } 78 | } 79 | 80 | func (self *BinaryExpr) setField(obj *StoneObject, expr *Dot, rvalue interface{}) interface{} { 81 | name := expr.Name() 82 | obj.Write(name, rvalue) 83 | return rvalue 84 | } 85 | 86 | func (self *BinaryExpr) computeOp(left interface{}, op string, right interface{}) interface{} { 87 | leftKind := reflect.TypeOf(left).Kind() 88 | rightKind := reflect.TypeOf(right).Kind() 89 | 90 | if leftKind == reflect.Int && rightKind == reflect.Int { 91 | return self.computeNumber(left.(int), op, right.(int)) 92 | } else { 93 | if op == "+" { 94 | if leftKind == reflect.String && rightKind == reflect.String { 95 | return left.(string) + right.(string) 96 | } else if leftKind == reflect.String && rightKind == reflect.Int { 97 | return left.(string) + strconv.Itoa(right.(int)) 98 | } else if leftKind == reflect.Int && rightKind == reflect.String { 99 | return strconv.Itoa(left.(int)) + right.(string) 100 | } else { 101 | panic("bad +") 102 | } 103 | } else if op == "==" { 104 | if left == right { 105 | return TRUE 106 | } else { 107 | return FALSE 108 | } 109 | } else { 110 | panic("bad type") 111 | } 112 | } 113 | } 114 | 115 | func (self *BinaryExpr) computeNumber(left int, op string, right int) int { 116 | switch op { 117 | case "+": return left + right 118 | case "-": return left - right 119 | case "*": return left * right 120 | case "/": return left / right 121 | case "%": return left % right 122 | case "==": if left == right { 123 | return TRUE 124 | } else { 125 | return FALSE 126 | } 127 | case ">": if left > right { 128 | return TRUE 129 | } else { 130 | return FALSE 131 | } 132 | case "<": if left < right { 133 | return TRUE 134 | } else { 135 | return FALSE 136 | } 137 | default: panic("bad operator") 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /vm/vm.go: -------------------------------------------------------------------------------- 1 | package vm 2 | 3 | import ( 4 | "unsafe" 5 | "reflect" 6 | "stone/environment" 7 | "stone/ast" 8 | "strconv" 9 | ) 10 | 11 | /* 12 | register address [-1 ~ -7] 13 | heap address [0 ~ 4G] 14 | */ 15 | 16 | const ( 17 | NUM_OF_REG = 6 18 | SAVE_AREA_SIZE = NUM_OF_REG + 2 19 | TRUE = 1 20 | FALSE = 0 21 | ) 22 | 23 | type VM struct { 24 | code []int8 25 | stack []interface{} 26 | strings []string 27 | heap HeapMemory 28 | 29 | pc, fp, sp, ret int // pc program counter; fp frame pointer; sp stack pointer; ret return value 30 | registers []interface{} 31 | } 32 | 33 | func NewVM(codeSize, stackSize, stringsSize int, hm HeapMemory) *VM { 34 | return &VM{code: make([]int8, codeSize), 35 | stack: make([]interface{}, stringsSize), 36 | strings: make([]string, stringsSize), 37 | heap: hm, 38 | registers: make([]interface{}, NUM_OF_REG)} 39 | } 40 | 41 | func (self *VM) GetReg(i int) interface{} { return self.registers[i] } 42 | func (self *VM) SetReg(i int, value interface{}) { self.registers[i] = value } 43 | func (self *VM) Strings() []string { return self.strings } 44 | func (self *VM) Code() []int8 { return self.code } 45 | func (self *VM) Stack() []interface{} { return self.stack } 46 | func (self *VM) Heap() HeapMemory { return self.heap } 47 | 48 | func (self *VM) Run(entry int) { 49 | self.pc = entry 50 | self.fp = 0 51 | self.sp = 0 52 | self.ret = -1 53 | 54 | for self.pc >= 0 { 55 | self.mainLoop() 56 | } 57 | } 58 | 59 | func (self *VM) mainLoop() { 60 | switch self.code[self.pc] { 61 | case ICONST: 62 | self.registers[decodeRegister(self.code[self.pc + 5])] = readInt(self.code, self.pc + 1) 63 | self.pc += 6 64 | case BCONST: 65 | self.registers[decodeRegister(self.code[self.pc + 2])] = int(self.code[self.pc + 1]) 66 | self.pc += 3 67 | case SCONST: 68 | self.registers[decodeRegister(self.code[self.pc + 3])] = 69 | self.strings[readShort(self.code, self.pc + 1)] 70 | self.pc += 4 71 | case MOVE: 72 | self.moveValue() 73 | case GMOVE: 74 | self.moveHeapValue() 75 | case IFZERO: 76 | value := self.registers[decodeRegister(self.code[self.pc + 1])] 77 | if i, ok := value.(int); ok && i == 0 { 78 | self.pc += readShort(self.code, self.pc + 2) 79 | } else { 80 | self.pc += 4 81 | } 82 | case GOTO: 83 | self.pc += readShort(self.code, self.pc + 1) 84 | case CALL: 85 | self.callFunction() 86 | case RETURN: 87 | self.pc = self.ret 88 | case SAVE: 89 | self.saveRegisters() 90 | case RESTORE: 91 | self.restoreRegisters() 92 | case NEG: 93 | reg := decodeRegister(self.code[self.pc + 1]) 94 | v := self.registers[reg] 95 | if i, ok := v.(int); ok { 96 | self.registers[reg] = -i 97 | } else { 98 | panic("bad operand value") 99 | } 100 | self.pc += 2 101 | default: 102 | if self.code[self.pc] > LESS { 103 | panic("bad instruction") 104 | } else { 105 | self.computeNumber() 106 | } 107 | } 108 | } 109 | 110 | func (self *VM) moveValue() { 111 | src, dest := self.code[self.pc + 1], self.code[self.pc + 2] 112 | var value interface{} 113 | if isRegister(src) { 114 | value = self.registers[decodeRegister(src)] 115 | } else { 116 | value = self.stack[self.fp + decodeOffset(src)] 117 | } 118 | 119 | if isRegister(dest) { 120 | self.registers[decodeRegister(src)] = value 121 | } else { 122 | self.stack[self.fp + decodeOffset(src)] = value 123 | } 124 | 125 | self.pc += 3 126 | } 127 | 128 | func (self *VM) moveHeapValue() { 129 | rand := self.code[self.pc + 1] 130 | if (isRegister(rand)) { 131 | dest := readShort(self.code, self.pc + 1) 132 | self.heap.Write(dest, self.registers[decodeRegister(rand)]) 133 | } else { 134 | src := readShort(self.code, self.pc + 1) 135 | self.registers[decodeRegister(self.code[self.pc + 3])] = self.heap.Read(src) 136 | } 137 | self.pc += 4 138 | } 139 | 140 | func (self *VM) callFunction() { 141 | value := self.registers[decodeRegister(self.code[self.pc + 1])] 142 | numOfArgs := int(self.code[self.pc + 2]) 143 | 144 | if fn, ok := value.(*ast.VMFunction); 145 | ok && fn.Parameters().Size() == numOfArgs { 146 | self.ret = self.pc + 3 147 | self.pc = fn.Entry() 148 | } else if fnc, ok := value.(*environment.NativeFunction); 149 | ok && fnc.NumParammeters() == numOfArgs { 150 | params := make([]reflect.Value, numOfArgs) 151 | for i := 0; i < numOfArgs; i++ { 152 | params[i] = reflect.ValueOf(self.stack[self.sp + i]) 153 | } 154 | self.stack[self.sp] = fnc.Invoke(params) 155 | self.pc += 3 156 | } else { 157 | panic("bac function call") 158 | } 159 | } 160 | 161 | func (self *VM) saveRegisters() { 162 | size := decodeOffset(self.code[self.pc + 1]) 163 | dest := size + self.sp 164 | 165 | for i := 0; i < NUM_OF_REG; i++ { 166 | self.stack[dest] = self.registers[i] 167 | dest++ 168 | } 169 | self.stack[dest] = self.fp 170 | dest++ 171 | self.fp = self.sp 172 | self.sp += size + SAVE_AREA_SIZE 173 | self.stack[dest] = self.ret 174 | self.pc += 2 175 | } 176 | 177 | func (self *VM) restoreRegisters() { 178 | dest := decodeOffset(self.code[self.pc + 1]) + self.fp 179 | for i := 0; i < NUM_OF_REG; i++ { 180 | self.registers[i] = self.stack[dest] 181 | dest++ 182 | } 183 | self.sp = self.fp 184 | self.fp = self.stack[dest].(int) 185 | dest++ 186 | self.ret = self.stack[dest].(int) 187 | self.pc += 2 188 | } 189 | 190 | func (self *VM) computeNumber() { 191 | leftIndex := decodeRegister(self.code[self.pc + 1]) 192 | rightIndex := decodeRegister(self.code[self.pc + 2]) 193 | left := self.registers[leftIndex] 194 | right := self.registers[rightIndex] 195 | leftKind := reflect.TypeOf(left).Kind() 196 | rightKind := reflect.TypeOf(right).Kind() 197 | 198 | if leftKind == reflect.Int && rightKind == reflect.Int { 199 | i1, i2 := left.(int), right.(int) 200 | var i3 int 201 | 202 | switch self.code[self.pc] { 203 | case ADD:i3 = i1 + i2 204 | case SUB: i3 = i1 - i2 205 | case MUL: i3 = i1 * i2 206 | case DIV: i3 = i1 / i2 207 | case REM: i3 = i1 % i2 208 | case EQUAL: if i1 == i2 { 209 | i3 = TRUE 210 | } else { 211 | i3 = FALSE 212 | } 213 | case MORE: if i1 > i2 { 214 | i3 = TRUE 215 | } else { 216 | i3 = FALSE 217 | } 218 | case LESS: if i1 < i2 { 219 | i3 = TRUE 220 | } else { 221 | i3 = FALSE 222 | } 223 | default: panic("bad operator") 224 | } 225 | 226 | self.registers[leftIndex] = i3 227 | } else { 228 | if self.code[self.pc] == ADD { 229 | if leftKind == reflect.String && rightKind == reflect.String { 230 | self.registers[leftIndex] = left.(string) + right.(string) 231 | } else if leftKind == reflect.String && rightKind == reflect.Int { 232 | self.registers[leftIndex] = left.(string) + strconv.Itoa(right.(int)) 233 | } else if leftKind == reflect.Int && rightKind == reflect.String { 234 | self.registers[leftIndex] = strconv.Itoa(left.(int)) + right.(string) 235 | } else { 236 | panic("bad operands for ADD") 237 | } 238 | } else if self.code[self.pc] == EQUAL { 239 | if left == right { 240 | self.registers[leftIndex] = TRUE 241 | } else { 242 | self.registers[leftIndex] = FALSE 243 | } 244 | } else { 245 | panic("bad instruction") 246 | } 247 | } 248 | } 249 | 250 | func readInt(b []int8, i int) int { 251 | x := uint32(b[i + 3]) | uint32(b[i + 2]) << 8 | uint32(b[i + 1]) << 16 | uint32(b[i]) << 24 252 | return int(*(*int32)(unsafe.Pointer(&x))) 253 | } 254 | 255 | func readShort(b []int8, i int) int { 256 | x := uint32(b[i + 1]) | uint32(b[i]) << 8 257 | return int(*(*int16)(unsafe.Pointer(&x))) 258 | } 259 | -------------------------------------------------------------------------------- /parser/parser.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "stone/lexer" 5 | "stone/token" 6 | "stone/ast" 7 | ) 8 | 9 | /* 10 | Grammer Definition 11 | 12 | // basic 13 | primary : ( "[" elements ]" | "(" expr ")" | NUMBER | IDENTIFIER { postfix } | FUNC | STRING ) 14 | factor : "-" primary | primary 15 | expr : factor { OP factor } 16 | block : "{" [ statement ] { ( ";" | EOL ) [ statement ] } "}" 17 | simple : expr 18 | statement : "if" expr block [ "else" block ] 19 | | "while" expr block 20 | | simple 21 | program : [ def | defclass | statement ] ( ";" | EOL ) 22 | 23 | // func 24 | parm : IDENTIFIER 25 | params : param { "," param } 26 | param_list : "(" [ param ] ")" 27 | def : "def" IDENTIFIER param_list block 28 | args : expr { "," expr } 29 | postfix : "(" [ args ] ")" | "." IDENTIFIER | "[" expr "]" 30 | 31 | // class 32 | member : def | simple 33 | class_body : "{" [ member ] { ( ";" | EOL ) [ member ] "}" 34 | defclass : "class" IDENTIFIER [ "extends" IDENTIFIER ] class_body 35 | 36 | // array 37 | elements: expr { "," expr } 38 | */ 39 | 40 | type Precedence struct { 41 | value int 42 | leftAssoc bool 43 | } 44 | 45 | func NewPrecedence(v int, a bool) *Precedence { 46 | return &Precedence{v, a} 47 | } 48 | 49 | type Parser struct { 50 | lexer *lexer.Lexer 51 | reserved map[string]bool 52 | operators map[string]*Precedence 53 | } 54 | 55 | func NewParser(lexer *lexer.Lexer) *Parser { 56 | reserved := map[string]bool { 57 | ";" : true, 58 | "}" : true, 59 | "{" : true, 60 | "(" : true, 61 | ")" : true, 62 | "+" : true, 63 | "-" : true, 64 | "*" : true, 65 | "/" : true, 66 | "%" : true, 67 | "==" : true, 68 | "=" : true, 69 | ">" : true, 70 | "<" : true, 71 | "if" : true, 72 | "else" : true, 73 | "while" : true, 74 | "def" : true, 75 | "func": true, 76 | "[" : true, 77 | "]" : true, 78 | "class" : true, 79 | "." : true, 80 | token.EOL : true, 81 | } 82 | 83 | operators := map[string]*Precedence { 84 | "=" : NewPrecedence(1, false), 85 | "==": NewPrecedence(2, true), 86 | "<" : NewPrecedence(2, true), 87 | ">" : NewPrecedence(2, true), 88 | "+" : NewPrecedence(3, true), 89 | "-" : NewPrecedence(3, true), 90 | "*" : NewPrecedence(4, true), 91 | "/" : NewPrecedence(4, true), 92 | "%" : NewPrecedence(4, true), 93 | } 94 | return &Parser{lexer, reserved, operators} 95 | } 96 | 97 | func (self *Parser) Parse() ast.ASTree { 98 | return self.program() 99 | } 100 | 101 | // primary type 102 | func (self *Parser) primary() ast.ASTree { 103 | var a ast.ASTree 104 | 105 | t := self.lexer.Read() 106 | if t.IsIdentifier() && t.GetText() == "(" { 107 | a = self.expr() 108 | self.readMatchToken(")") 109 | } else if t.IsIdentifier() && t.GetText() == "func" { 110 | a = ast.NewFunc([]ast.ASTree{self.paramList(), self.block()}) 111 | } else if t.IsIdentifier() && t.GetText() == "[" { 112 | a = self.elements() 113 | self.readMatchToken("]") 114 | } else if self.isName(t) { 115 | a = ast.NewName(t) 116 | if self.testPostfix() { 117 | list := []ast.ASTree{a, self.postfix()} 118 | for self.testPostfix() { 119 | list = append(list, self.postfix()) 120 | } 121 | a = ast.NewPrimary(list) 122 | } 123 | } else if t.IsString() { 124 | a = ast.NewStringLiteral(t) 125 | } else if t.IsNumber() { 126 | a = ast.NewNumberLiteral(t) 127 | } else { 128 | panic("line " + self.lexer.GetLineNumber() + " -- error" + t.GetText()) 129 | } 130 | 131 | return a 132 | } 133 | 134 | func (self *Parser) testPrimary() bool { 135 | t := self.lexer.Peek(0) 136 | if t.IsNumber() || t.IsString() { 137 | return true 138 | } else if t.IsIdentifier() && (t.GetText() == "func" || t.GetText() == "[" || t.GetText() == "(") { 139 | return true 140 | } else if self.isName(t) { 141 | return true 142 | } else { 143 | return false 144 | } 145 | 146 | } 147 | 148 | func (self *Parser) factor() ast.ASTree{ 149 | 150 | if self.isToken("-") { 151 | self.lexer.Read() 152 | return ast.NewNegativeExpr([]ast.ASTree{self.primary()}) 153 | } else { 154 | return self.primary() 155 | } 156 | } 157 | 158 | func (self *Parser) testFactor() bool { 159 | return self.isToken("-") || self.testPrimary() 160 | } 161 | 162 | // 算法优先分析法 163 | // 用于处理运算符优先级 164 | func (self *Parser) expr() ast.ASTree{ 165 | right := self.factor() 166 | next := self.nextOperator() 167 | for next != nil { 168 | right = self.doShift(right, next.value) 169 | next = self.nextOperator() 170 | } 171 | return right 172 | } 173 | 174 | func (self *Parser) testExpr() bool { 175 | return self.testFactor() 176 | } 177 | 178 | func (self *Parser) doShift(left ast.ASTree, prec int) ast.ASTree{ 179 | op := ast.NewOP(self.lexer.Read()) 180 | right := self.factor() 181 | next := self.nextOperator() 182 | for next != nil && self.rightIsExpr(prec, next) { 183 | right = self.doShift(right, next.value) 184 | next = self.nextOperator() 185 | } 186 | return ast.NewBinaryExpr([]ast.ASTree{left, op, right}) 187 | } 188 | 189 | func (self *Parser) nextOperator() *Precedence { 190 | t := self.lexer.Peek(0) 191 | if t.IsIdentifier() { 192 | return self.operators[t.GetText()] 193 | } else { 194 | return nil 195 | } 196 | } 197 | 198 | func (self *Parser) rightIsExpr(prec int, nextPrec *Precedence) bool { 199 | if nextPrec.leftAssoc { 200 | return prec < nextPrec.value 201 | } else { 202 | return prec <= nextPrec.value 203 | } 204 | } 205 | 206 | func (self *Parser) block() ast.ASTree{ 207 | self.readMatchToken("{") 208 | list := make([]ast.ASTree, 0) 209 | if self.testStatement() { 210 | list = append(list, self.statement()) 211 | } 212 | 213 | t := self.lexer.Peek(0) 214 | for t.IsIdentifier() && (t.GetText() == ";" || t.GetText() == token.EOL){ 215 | self.lexer.Read() 216 | if self.testStatement() { 217 | list = append(list, self.statement()) 218 | } 219 | t = self.lexer.Peek(0) 220 | } 221 | 222 | if len(list) == 0 { 223 | list = append(list, ast.NewNullStmnt()) 224 | } 225 | self.readMatchToken("}") 226 | return ast.NewBlockStmnt(list) 227 | } 228 | 229 | func (self *Parser) testBlock() bool { 230 | return self.isToken("{") 231 | } 232 | 233 | func (self *Parser) simple() ast.ASTree{ 234 | return self.expr() 235 | } 236 | 237 | func (self *Parser) testSimple() bool { 238 | return self.testExpr() 239 | } 240 | 241 | func (self *Parser) statement() ast.ASTree{ 242 | list := make([]ast.ASTree, 2) 243 | 244 | if self.isToken("if") { 245 | self.lexer.Read() 246 | list[0] = self.expr() 247 | list[1] = self.block() 248 | if self.isToken("else") { 249 | self.lexer.Read() 250 | list = append(list, self.block()) 251 | } 252 | return ast.NewIfStmnt(list) 253 | } else if self.isToken("while") { 254 | self.lexer.Read() 255 | list[0] = self.expr() 256 | list[1] = self.block() 257 | return ast.NewWhileStmnt(list) 258 | } else if self.testSimple() { 259 | return self.simple() 260 | } else { 261 | panic("line " + self.lexer.GetLineNumber() + " -- not a statement ") 262 | } 263 | } 264 | 265 | func (self *Parser) testStatement() bool { 266 | return self.isToken("if") || 267 | self.isToken("while") || 268 | self.testSimple() 269 | } 270 | 271 | func (self *Parser) program() ast.ASTree { 272 | var a ast.ASTree 273 | if self.testStatement() { 274 | a = self.statement() 275 | } else if self.isToken("def") { 276 | a = self.def() 277 | } else if self.isToken("class") { 278 | a = self.defclass() 279 | } else { 280 | a = ast.NewNullStmnt() 281 | } 282 | 283 | if self.isToken(";") || self.isToken(token.EOL) { 284 | self.lexer.Read() 285 | } else { 286 | panic("line " + self.lexer.GetLineNumber() + " -- lack of end symbol") 287 | } 288 | return a 289 | } 290 | 291 | func (self *Parser) testProgram() bool { 292 | return self.isToken("def") || self.isToken("class") || self.testStatement() 293 | } 294 | 295 | func (self *Parser) params() ast.ASTree { 296 | list := make([]ast.ASTree, 0) 297 | if self.testParams() { 298 | list = append(list, ast.NewName(self.lexer.Read())) 299 | } else { 300 | panic("line " + self.lexer.GetLineNumber() + " -- not param " + self.lexer.Peek(0).GetText()) 301 | } 302 | 303 | for self.isToken(",") { 304 | self.lexer.Read() 305 | if self.testParams() { 306 | list = append(list, ast.NewName(self.lexer.Read())) 307 | } else { 308 | panic("line " + self.lexer.GetLineNumber() + " -- not param " + self.lexer.Peek(0).GetText()) 309 | } 310 | } 311 | 312 | return ast.NewParameterList(list) 313 | } 314 | 315 | func (self *Parser) testParams() bool { 316 | return self.isName(self.lexer.Peek(0)) 317 | } 318 | 319 | func (self *Parser) paramList() ast.ASTree { 320 | self.readMatchToken("(") 321 | var a ast.ASTree = ast.NewParameterList(nil) 322 | if self.testParams() { 323 | a = self.params() 324 | } 325 | self.readMatchToken(")") 326 | return a 327 | } 328 | 329 | func (self *Parser) testParamList() bool { 330 | return self.isToken("(") 331 | } 332 | 333 | func (self *Parser) def() ast.ASTree { 334 | self.readMatchToken("def") 335 | list := make([]ast.ASTree, 3) 336 | if self.isName(self.lexer.Peek(0)) { 337 | list[0] = ast.NewName(self.lexer.Read()) 338 | list[1] = self.paramList() 339 | list[2] = self.block() 340 | } else { 341 | panic("line " + self.lexer.GetLineNumber() + " -- not identifer " + self.lexer.Peek(0).GetText()) 342 | } 343 | 344 | return ast.NewDefStmnt(list) 345 | } 346 | 347 | func (self *Parser) testDef() bool { 348 | return self.isToken("def") 349 | } 350 | 351 | func (self *Parser) args() ast.ASTree { 352 | list := make([]ast.ASTree, 1) 353 | list[0] = self.expr() 354 | for self.isToken(",") { 355 | self.lexer.Read() 356 | list = append(list, self.expr()) 357 | } 358 | return ast.NewArguments(list) 359 | } 360 | 361 | func (self *Parser) testArgs() bool { 362 | return self.testExpr() 363 | } 364 | 365 | // postfix : "(" [ args ] ")" | "." IDENTIFIER | "[" expr "]" 366 | func (self *Parser) postfix() ast.ASTree { 367 | if self.isToken("(") { 368 | self.lexer.Read() 369 | var a ast.ASTree = ast.NewArguments(nil) 370 | if self.testArgs() { 371 | a = self.args() 372 | } 373 | self.readMatchToken(")") 374 | return a 375 | } else if self.isToken(".") { 376 | self.lexer.Read() 377 | var a ast.ASTree 378 | if self.isName(self.lexer.Peek(0)) { 379 | a = ast.NewDot([]ast.ASTree{ast.NewName(self.lexer.Read())}) 380 | } else { 381 | panic("line " + self.lexer.GetLineNumber() + " -- not obj member " + 382 | self.lexer.Peek(0).GetText()) 383 | } 384 | return a 385 | } else if self.isToken("[") { 386 | self.lexer.Read() 387 | var a ast.ASTree = self.expr() 388 | self.readMatchToken("]") 389 | return ast.NewArrayRef([]ast.ASTree{a}) 390 | } else { 391 | panic("line " + self.lexer.GetLineNumber() + " -- not postfix " + self.lexer.Peek(0).GetText()) 392 | } 393 | } 394 | 395 | func (self *Parser) testPostfix() bool { 396 | return self.isToken("(") || self.isToken(".") || self.isToken("[") 397 | } 398 | 399 | func (self *Parser) member() ast.ASTree { 400 | if self.testDef() { 401 | return self.def() 402 | } else if self.testSimple() { 403 | return self.simple() 404 | } else { 405 | panic("line" + self.lexer.GetLineNumber() + " -- not class member " + self.lexer.Peek(0).GetText()) 406 | } 407 | } 408 | 409 | func (self *Parser) testMember() bool { 410 | return self.testDef() || self.testSimple() 411 | } 412 | 413 | func (self *Parser) classBody() ast.ASTree { 414 | self.readMatchToken("{") 415 | list := make([]ast.ASTree, 0) 416 | if self.testMember() { 417 | list = append(list, self.member()) 418 | } 419 | for self.isToken(";") || self.isToken(token.EOL) { 420 | self.lexer.Read() 421 | if self.testMember() { 422 | list = append(list, self.member()) 423 | } 424 | } 425 | if len(list) == 0 { 426 | list = append(list, ast.NewNullStmnt()) 427 | } 428 | self.readMatchToken("}") 429 | 430 | return ast.NewClassBody(list) 431 | } 432 | 433 | func (self *Parser) testClassBody() bool { 434 | return self.isToken("{") 435 | } 436 | 437 | func (self *Parser) defclass() ast.ASTree { 438 | self.readMatchToken("class") 439 | list := make([]ast.ASTree, 2, 3) 440 | if self.isName(self.lexer.Peek(0)) { 441 | list[0] = ast.NewName(self.lexer.Read()) 442 | } else { 443 | panic("line" + self.lexer.GetLineNumber() + " -- class name error") 444 | } 445 | 446 | if self.isToken("extends") { 447 | self.lexer.Read() 448 | if self.isName(self.lexer.Peek(0)) { 449 | list = append(list, ast.NewName(self.lexer.Read())) 450 | } else { 451 | panic("line" + self.lexer.GetLineNumber() + " -- extends error") 452 | } 453 | } 454 | 455 | list[1] = self.classBody() 456 | return ast.NewClassStmnt(list) 457 | } 458 | 459 | func (self *Parser) testDefclass() bool { 460 | return self.isToken("class") 461 | } 462 | 463 | func (self *Parser) elements() ast.ASTree { 464 | list := make([]ast.ASTree, 1) 465 | list[0] = self.expr() 466 | for self.isToken(",") { 467 | self.lexer.Read() 468 | list = append(list, self.expr()) 469 | } 470 | return ast.NewArrayLiteral(list) 471 | } 472 | 473 | func (self *Parser) testElements() bool { 474 | return self.testExpr() 475 | } 476 | 477 | // helper function 478 | 479 | func (self *Parser) isToken(name string) bool{ 480 | t := self.lexer.Peek(0) 481 | return t.IsIdentifier() && name == t.GetText() 482 | } 483 | 484 | func (self *Parser) readMatchToken(name string) { 485 | t := self.lexer.Read() 486 | if !(t.IsIdentifier() && name == t.GetText()) { 487 | panic("parser error at line " + self.lexer.GetLineNumber()) 488 | } 489 | } 490 | 491 | func (self *Parser) isName(t token.Token) bool { 492 | if t.IsIdentifier() { 493 | _, ok := self.reserved[t.GetText()] 494 | if ok { 495 | return false 496 | } else { 497 | return true 498 | } 499 | } else { 500 | return false 501 | } 502 | } 503 | --------------------------------------------------------------------------------