Browse Source

Tests and some fixes.

Beoran 6 years ago
parent
commit
34733a3ed1
6 changed files with 282 additions and 109 deletions
  1. 46 17
      ast.go
  2. 18 8
      design_muesli.muesli
  3. 33 7
      lexer.go
  4. 162 73
      parser.go
  5. 18 3
      parser_test.go
  6. 5 1
      token.go

+ 46 - 17
ast.go

@@ -12,6 +12,7 @@ type AstMetaKindNone AstBasicMetaKind
 type AstMetaKindProgram AstBasicMetaKind
 type AstMetaKindStatements AstBasicMetaKind
 type AstMetaKindStatement AstBasicMetaKind
+type AstMetaKindClosed AstBasicMetaKind
 type AstMetaKindSet AstBasicMetaKind
 type AstMetaKindGet AstBasicMetaKind
 type AstMetaKindTarget AstBasicMetaKind
@@ -29,6 +30,8 @@ type AstMetaKindType AstBasicMetaKind
 type AstMetaKindValue AstBasicMetaKind
 type AstMetaKindEnd AstBasicMetaKind
 type AstMetaKindError AstBasicMetaKind
+type AstMetaKindFlatten AstBasicMetaKind
+
 
 /** The actual types are defined as constants, the meta types are used to be able to have different behavior for them.*/
 const (
@@ -36,6 +39,7 @@ const (
 	AstKindProgram     = AstMetaKindProgram("Program")
 	AstKindStatements  = AstMetaKindStatements("Statements")
 	AstKindStatement   = AstMetaKindStatement("Statement")
+    AstKindClosed      = AstMetaKindSet("Closed")
 	AstKindSet         = AstMetaKindSet("Set")
 	AstKindGet         = AstMetaKindGet("Get")
 	AstKindTarget      = AstMetaKindTarget("Target")
@@ -53,6 +57,8 @@ const (
 	AstKindValue       = AstMetaKindValue("Value")
 	AstKindEnd         = AstMetaKindEnd("End")
 	AstKindError       = AstMetaKindError("Error")
+    // AstKindFlatten is a special ast kind that insruct the parser not to generate a token 
+	AstKindFlatten     = AstMetaKindFlatten("Flatten")
 )
 
 func (astkind AstBasicMetaKind) String() string {
@@ -67,6 +73,7 @@ func (astkind AstMetaKindNone) String() string        { return "AstNone       "
 func (astkind AstMetaKindProgram) String() string     { return "AstProgram    " }
 func (astkind AstMetaKindStatements) String() string  { return "AstStatements " }
 func (astkind AstMetaKindStatement) String() string   { return "AstStatement  " }
+func (astkind AstMetaKindClosed) String() string      { return "AstClosed     " }
 func (astkind AstMetaKindSet) String() string         { return "AstSet        " }
 func (astkind AstMetaKindGet) String() string         { return "AstGet        " }
 func (astkind AstMetaKindTarget) String() string      { return "AstTarget     " }
@@ -84,6 +91,8 @@ func (astkind AstMetaKindType) String() string        { return "AstType       "
 func (astkind AstMetaKindValue) String() string       { return "AstValue      " }
 func (astkind AstMetaKindEnd) String() string         { return "AstEnd        " }
 func (astkind AstMetaKindError) String() string       { return "AstError      " }
+func (astkind AstMetaKindFlatten) String() string     { return "AstFlatten    " }
+
 
 func (astkind AstMetaKindNone) Run(vm *VM, ast Ast, val []Value) []Value { return EmptyValueArray() }
 
@@ -101,6 +110,7 @@ func (astkind AstMetaKindStatements) Run(vm *VM, ast Ast, val []Value) []Value {
 func (astkind AstMetaKindStatement) Run(vm *VM, ast Ast, val []Value) []Value {
 	return EmptyValueArray()
 }
+func (astkind AstMetaKindClosed) Run(vm *VM, ast Ast, val []Value) []Value { return EmptyValueArray() }
 func (astkind AstMetaKindSet) Run(vm *VM, ast Ast, val []Value) []Value { return EmptyValueArray() }
 func (astkind AstMetaKindGet) Run(vm *VM, ast Ast, val []Value) []Value { return EmptyValueArray() }
 func (astkind AstMetaKindTarget) Run(vm *VM, ast Ast, val []Value) []Value {
@@ -140,6 +150,11 @@ func (astkind AstMetaKindEnd) Run(vm *VM, ast Ast, val []Value) []Value { return
 func (astkind AstMetaKindError) Run(vm *VM, ast Ast, val []Value) []Value {
 	return EmptyValueArray()
 }
+func (astkind AstMetaKindFlatten) Run(vm *VM, ast Ast, val []Value) []Value {
+	return EmptyValueArray()
+}
+
+
 
 type AstKind interface {
 	String() string
@@ -211,21 +226,31 @@ func AstNewChild(parent Ast, kind AstMetaKind, token Token) Ast {
 type Ast struct {
 	AstKind
 	parent   *Ast
-	children []Ast
+	children []*Ast
 	token    Token
 }
 
-func NewAst(kind AstKind, parent *Ast, children []Ast, token Token) Ast {
-	return Ast{kind, parent, children, token}
+func NewAst(kind AstKind, parent *Ast, children []*Ast, token Token) *Ast {
+	ast := &Ast{AstKind: kind, parent: parent, token: token}
+    return ast.AppendChildren(children...)
 }
 
-func (ast *Ast) AppendChild(child Ast) Ast {
-	ast.children = append(ast.children, child)
+func (ast *Ast) AppendChildren(children ...*Ast) *Ast {
+	for _, child := range children {
+        ast.AppendChild(child)
+    }
+    return ast
+}
+
+
+func (ast *Ast) AppendChild(child * Ast) *Ast {
+	child.SetParent(ast)
+    ast.children = append(ast.children, child)
 	return child
 }
 
-func (ast *Ast) NewChild(kind AstKind, token Token) Ast {
-	child := NewAst(kind, ast, make([]Ast, 0), token)
+func (ast *Ast) NewChild(kind AstKind, token Token) *Ast {
+	child := NewAst(kind, ast, make([]*Ast, 0), token)
 	ast.AppendChild(child)
 	return child
 }
@@ -242,6 +267,10 @@ func (ast Ast) IsNone() bool {
 	return ast.AstKind == AstKindNone
 }
 
+func (ast Ast) IsFlatten() bool {
+	return ast.AstKind == AstKindFlatten
+}
+
 func (ast Ast) Token() Token {
 	return ast.token
 }
@@ -250,7 +279,7 @@ func (ast Ast) Parent() *Ast {
 	return ast.parent
 }
 
-func (ast Ast) Children() []Ast {
+func (ast Ast) Children() []*Ast {
 	return ast.children
 }
 
@@ -267,7 +296,7 @@ func (ast Ast) Child(index int) *Ast {
 	if index < 0 || index > count {
 		return nil
 	}
-	return &ast.children[index]
+	return ast.children[index]
 }
 
 func (ast Ast) Run(vm *VM, val []Value) []Value {
@@ -292,7 +321,7 @@ func (ast Ast) String() string {
 
 func (ast Ast) Display() {
 	ast.Walk(func(node *Ast) *Ast {
-		depth := ast.Depth()
+		depth := node.Depth()
 		fmt.Printf("%s", strings.Repeat("--", depth))
 		if node != nil {
 			fmt.Printf("Ast: %s\n", node.String())
@@ -305,7 +334,7 @@ func (ast Ast) Display() {
 
 func (ast Ast) Depth() int {
 	var depth int = 0
-	parent := ast.parent
+	parent := ast.Parent()
 	for parent != nil {
 		depth++
 		parent = parent.Parent()
@@ -317,7 +346,7 @@ func (ast Ast) CountChildren() int {
 	return len(ast.children)
 }
 
-func AstIsError(ast Ast) bool {
+func AstIsError(ast * Ast) bool {
 	return ast.IsError()
 }
 
@@ -332,19 +361,19 @@ func (ast Ast) Errors() []*Ast {
 	return res
 }
 
-func EmptyAstArray() []Ast {
-	return make([]Ast, 0)
+func EmptyAstArray() []*Ast {
+	return make([]*Ast, 0)
 }
 
-func NewEmptyAst(astkind AstKind) Ast {
+func NewEmptyAst(astkind AstKind) *Ast {
 	return NewAst(astkind, nil, EmptyAstArray(), NoToken())
 }
 
-func NewAstNone() Ast {
+func NewAstNone() *Ast {
 	return NewEmptyAst(AstKindNone)
 }
 
-func NewAstWithToken(astkind AstKind, token Token) Ast {
+func NewAstWithToken(astkind AstKind, token Token) *Ast {
 	return NewAst(astkind, nil, EmptyAstArray(), token)
 }
 

+ 18 - 8
design_muesli.muesli

@@ -15,6 +15,7 @@
 but the {} pairs must match. 
 }
 
+ 
 
 # Empty lines are ignored.
 
@@ -46,9 +47,12 @@ p -7.000005
 # Lists can be created between [ ] and may be heterogenous or homogenous. 
 # The [ ] must be space separated. 
 # The type is Any[] if heterogenous,  
-p [ foo "bar" ] 
+
+# p [ foo "bar" ] 
+
 # The type is Int[]  below
-p [ 1 2 3 ] 
+
+# p [ 1 2 3 ] 
 
 
 # A sequence of a lower case letter followed by anything that is not whitespace.
@@ -57,21 +61,26 @@ p [ 1 2 3 ]
 # If the word is at the beginning of the line it is invoked as a command.
 # Muesli's basic syntax is that of the command. Spaces separate the arguments.
 # of the command. The first word is the command, the rest are the arguments. 
+
 print "hello" world 7 0.9
+
 # the previous command outputs: "hello world 7 0.9" to standard output
 
 # A command has one or more results that can be captured with a parenthesis
+
+
 print ( mul 3 ( sum 5 7 ) )
 
 
 # Commands can be grouped into blocks. The value of the block is that of it's last command.
-{ 
-    print "hello"
-    print "world"
-}
 
-# Commands can also take blocks as parameters. Don't put a newline between } and {
-# to be sure multiple blocks get passed
+# block { 
+# print "hello"
+#  print "world"
+# }
+
+# Commands can also take blocks as parameters. Don't put a newline between 
+# the open and close of the block to be sure multiple blocks get passed
 command {
     print "first block"
 } and also {
@@ -134,6 +143,7 @@ if (less a 10) {
 # embedded commands.
 # Do note that MUESLI uses dynamic scoping for ease of implementation
 
+
 #{
 
 BLOCK

+ 33 - 7
lexer.go

@@ -250,10 +250,19 @@ func (lexer *Lexer) SkipWhile(predicate func(rune) bool) (bool, error) {
 	return result, err
 }
 
+func isEOX(r rune) bool {
+	return r == '\n' || r == '.'
+}
+
+
 func isSpace(r rune) bool {
 	return r == ' ' || r == '\t' || r == '\v' || r == '\r'
 }
 
+func isSpaceOrEOX(r rune) bool {
+	return r == ' ' || r == '\t' || r == '\v' || r == '\r' || r == '\n' || r == '.'
+}
+
 func isComment(r rune) bool {
 	return r == '#'
 }
@@ -447,9 +456,8 @@ func (lexer *Lexer) LexString() Token {
 	if err != nil {
 		return lexer.MakeErrorfToken("when parsing string: %s", err)
 	}
-
-	_, err = lexer.Skip() // skip last "
-	if err != nil {
+    
+    if err != nil {
 		return lexer.handleError(err)
 	}
 
@@ -535,7 +543,7 @@ func (lexer *Lexer) LexSymbol() Token {
 	}
 
 	_, err = lexer.NextWhile(func(r rune) bool {
-		return !unicode.IsSpace(r)
+		return !isSpaceOrEOX(r)
 	})
 
 	if err != nil {
@@ -555,7 +563,7 @@ func (lexer *Lexer) LexBuiltin() Token {
 	}
 
 	_, err = lexer.NextWhile(func(r rune) bool {
-		return !unicode.IsSpace(r)
+		return !isSpaceOrEOX(r)
 	})
 
 	if err != nil {
@@ -590,6 +598,25 @@ func (lexer *Lexer) skipSpaceAndCommentAndPeek() (rune, error) {
 	return r, err
 }
 
+func (lexer *Lexer) LexEOX() Token {
+    lexer.Next()
+    _, err := lexer.skipSpaceAndCommentAndPeek()
+	if err != nil {
+		return lexer.handleError(err)
+	}
+    
+    _, err = lexer.NextWhile(func(r rune) bool {
+        return isSpaceOrEOX(r) || r == '\n' || r == '.'
+    })
+
+    if err != nil {
+            return lexer.handleError(err)
+    }
+    
+	return lexer.MakeToken(TokenKindEOX)
+}
+
+
 func (lexer *Lexer) lex() Token {
 	r, err := lexer.skipSpaceAndCommentAndPeek()
 	lexer.LogDebug(" After skip: >%c< >%v<\n", r, err)
@@ -603,8 +630,7 @@ func (lexer *Lexer) lex() Token {
 	}
 
 	if r == '\n' || r == '.' {
-		lexer.Next()
-		return lexer.MakeToken(TokenKindEOX)
+	    return lexer.LexEOX()
 	}
 
 	if r == '"' {

+ 162 - 73
parser.go

@@ -16,22 +16,22 @@ import (
 )
 
 /* Grammar:
-
 Desrired syntax (verified LL(1) on smlweb.cpsc.ucalgary.ca)
 
 PROGRAM -> STATEMENTS.
+CLOSED -> BLOCK | LIST | PARENTHESIS .
 STATEMENTS -> STATEMENT STATEMENTS | .
-STATEMENT -> EXPRESSION eos | BLOCK .
-WORDOPS -> WORDOP WORDOPS | .
-EXPRESSION -> SETTER | GETTER | COMMAND | VALUE.
-COMMAND -> WORDVALUE PARAMETERS.
+STATEMENT -> CLOSED | EXPRESSION eos | eos .
+COMMAND -> word PARAMETERS.
 PARAMETERS -> PARAMETER PARAMETERS | .
-PARAMETER -> WORDVALUE | PARENTHESIS | GETTER | ARRARY | BLOCK .
-PARENTHESIS -> '(' EXPRESSION ')' .
-BLOCK -> '{' STATEMENTS '}' .
+PARAMETER -> WORDVALUE | GETTER | SETTER | CLOSED .
+EXPRESSION -> COMMAND | GETTER | SETTER | VALUE.
+PARENTHESIS -> closeparen EXPRESSION openparen .
+BLOCK -> openblock STATEMENTS closeblock .
+LIST -> openlist PARAMETERS closelist .
+VALUE -> string | int | float | symbol | type .
 WORDVALUE -> word | VALUE.
-VALUE -> string | integer | float | symbol | boolean | nil.
-SETTER -> set word PARAMETERS .
+SETTER -> set word PARAMETER .
 GETTER -> get word .
 
  *
@@ -65,46 +65,73 @@ func (parser *Parser) Accept(kinds ...TokenKind) Token {
 	if parser.current.IsNone() {
 		parser.Advance()
 	}
-
+    
 	for _, kind := range kinds {
 		if kind == parser.current.TokenKind {
 			accepted := parser.current
 			parser.Advance()
+            parser.LogDebug("Accept: Accepted token: %s\n", accepted.String())
 			return accepted
 		}
 	}
+    
+    if parser.current.TokenKind == TokenKindEOF {
+        parser.LogDebug("Unexpected EOF\n")
+        return parser.Lexer.MakeErrorfToken("Unexpected EOF in Accept")
+    }
+    
+    parser.LogDebug("Accept: No Token: no %s in %v.", parser.current.TokenKind, kinds)
+
 	return NoToken()
 }
 
-func (parser *Parser) ParseMany(kind AstKind, parent *Ast, parsefunc func(*Parser) Ast) Ast {
-	children := make([]Ast, 0)
-	for sub := parsefunc(parser); !sub.IsNone() && !sub.IsError(); sub = parsefunc(parser) {
+func (parser *Parser) ParseMany(kind AstKind, parent *Ast, parsefunc func(*Parser) *Ast) *Ast {
+	children := EmptyAstArray()
+	for sub := parsefunc(parser); parser.current.TokenKind != TokenKindEOF && 
+            !sub.IsNone() && !sub.IsError(); sub = parsefunc(parser) {
 		children = append(children, sub)
 	}
-	return NewAst(kind, parent, children, NoToken())
+    if kind == AstKindFlatten {
+        if parent == nil {
+            panic("Why nil?")
+        } 
+        parent.AppendChildren(children...)
+        return parent
+    } else {
+        return NewAst(kind, parent, children, NoToken())
+    }
 }
 
-func (parser *Parser) NewAstError(message string, args ...interface{}) Ast {
+func (parser *Parser) NewAstError(message string, args ...interface{}) *Ast {
 	sv := StringValue(fmt.Sprintf(message+" at token "+parser.current.String(), args))
 	pos := parser.current.Position
 	tok := NewToken(TokenKindError, sv, pos)
 	return NewAst(AstKindError, nil, EmptyAstArray(), tok)
 }
 
-func (parser *Parser) ParseAny(astkind AstKind, parsefuncs ...(func(*Parser) Ast)) Ast {
-	ast := NewEmptyAst(astkind)
+func (parser *Parser) ParseAny(astkind AstKind, parsefuncs ...(func(*Parser) *Ast)) *Ast {
+	var ast * Ast
+    if astkind != AstKindFlatten {  
+        ast = NewEmptyAst(astkind)
+    }
 	for _, parsefunc := range parsefuncs {
-		parser.LogDebug("ParseAny: trying: %s", GetFunctionName(parsefunc))
+		parser.LogDebug("ParseAny: %s: trying: %s", astkind, GetFunctionName(parsefunc))
 		sub := parsefunc(parser)
 		if !sub.IsNone() {
-			ast.AppendChild(sub)
+            if astkind == AstKindFlatten {  
+                return sub
+            } else if sub.IsFlatten() {
+                return ast
+            } else {
+                ast.AppendChild(sub)
+            }
 			return ast
 		}
 	}
 	return NewAstNone()
 }
 
-func (parser *Parser) ParseRequireAny(astkind AstKind, parsefuncs ...(func(*Parser) Ast)) Ast {
+func (parser *Parser) ParseRequireAny(astkind AstKind, parsefuncs ...(func(*Parser) *Ast)) *Ast {
 	ast := parser.ParseAny(astkind, parsefuncs...)
 	if ast.IsNone() {
 		err := parser.NewAstError("Unexpected token in %v", parsefuncs)
@@ -113,51 +140,67 @@ func (parser *Parser) ParseRequireAny(astkind AstKind, parsefuncs ...(func(*Pars
 	return ast
 }
 
-func (parser *Parser) ParseValue() Ast {
+// Also  handles none or error vales of the token
+
+func (parser *Parser) NewAst(kind AstKind, parent * Ast, children []*Ast, value Token) *Ast{
+    if value.IsNone() {
+        return NewAstNone()
+    }
+    if value.IsError() {
+        return NewAst(AstKindError, parent, children, value)
+    }
+    return NewAst(kind, parent, children, value)
+}
+
+func (parser *Parser) ParseValue() *Ast {
+    parser.LogDebug("ParseValue: %s\n", parser.current.String())
+
 	value := parser.Accept(TokenKindInteger, TokenKindString,
 		TokenKindBoolean, TokenKindNil, TokenKindFloat, TokenKindSymbol)
-	if value.IsNone() {
-		return NewAstNone()
-	}
-	return NewAst(AstKindValue, nil, EmptyAstArray(), value)
+	return parser.NewAst(AstKindValue, nil, EmptyAstArray(), value)
 }
 
-func (parser *Parser) ParseWordValue() Ast {
+func (parser *Parser) ParseWordValue() *Ast {
+    parser.LogDebug("ParseWordValue: %s\n", parser.current.String())
+
 	value := parser.Accept(TokenKindInteger, TokenKindString,
-		TokenKindBoolean, TokenKindFloat, TokenKindSymbol,
+		TokenKindBoolean, TokenKindNil, TokenKindFloat, TokenKindSymbol,
 		TokenKindType, TokenKindWord)
-	if value.IsNone() {
-		return NewAstNone()
-	}
-	return NewAst(AstKindWordValue, nil, EmptyAstArray(), value)
+	return parser.NewAst(AstKindWordValue, nil, EmptyAstArray(), value)
 }
 
-func (parser *Parser) ParseArgument() Ast {
+func (parser *Parser) ParseArgument() *Ast {
+    parser.LogDebug("ParseArgument: %s\n", parser.current.String())
+
 	return parser.ParseAny(AstKindArgument,
-		(*Parser).ParseWordValue,
 		(*Parser).ParseGet,
 		(*Parser).ParseSet,
-		(*Parser).ParseParenthesis,
-		(*Parser).ParseList,
-		(*Parser).ParseBlock)
+		(*Parser).ParseClosed,
+        (*Parser).ParseWordValue)
 }
 
-func (parser *Parser) ParseArguments() Ast {
-	return parser.ParseMany(AstKindArguments, nil, (*Parser).ParseArgument)
+func (parser *Parser) ParseArguments() *Ast {
+    parser.LogDebug("ParseArgument: %s\n", parser.current.String())	
+    return parser.ParseMany(AstKindArguments, nil, (*Parser).ParseArgument)
 }
 
-func (parser *Parser) ParseList() Ast {
+func (parser *Parser) ParseList() *Ast {
+    parser.LogDebug("ParseList: %s\n", parser.current.String())
+
 	op := parser.Accept(TokenKindOpenList)
 	if op.IsNone() {
 		return NewAstNone()
 	}
+    if op.IsError() {
+        return parser.NewAstError("Unexpected value.")
+    }
 
 	ast := NewAstWithToken(AstKindList, op)
 	args := parser.ParseArguments()
 	if AstIsError(args) {
 		return args
 	}
-	if cp := parser.Accept(TokenKindCloseList); cp.IsNone() {
+	if cp := parser.Accept(TokenKindCloseList); cp.IsNone() || cp.IsError() {
 		return parser.NewAstError("expected closing brackets")
 	}
 
@@ -165,12 +208,18 @@ func (parser *Parser) ParseList() Ast {
 	return ast
 }
 
-func (parser *Parser) ParseParenthesis() Ast {
+func (parser *Parser) ParseParenthesis() *Ast {
+    parser.LogDebug("ParseParenthesis: %s\n", parser.current.String())
+
 	op := parser.Accept(TokenKindOpenParen)
 
 	if op.IsNone() {
 		return NewAstNone()
 	}
+    if op.IsError() {
+        return parser.NewAstError("Unexpected value.")
+    }
+
 
 	ast := NewAstWithToken(AstKindParenthesis, op)
 	expr := parser.ParseExpression()
@@ -180,7 +229,7 @@ func (parser *Parser) ParseParenthesis() Ast {
 	if AstIsError(expr) {
 		return expr
 	}
-	if cp := parser.Accept(TokenKindCloseParen); cp.IsNone() {
+	if cp := parser.Accept(TokenKindCloseParen); cp.IsNone() || cp.IsError() {
 		return parser.NewAstError("expected closing parenthesis")
 	}
 
@@ -188,11 +237,16 @@ func (parser *Parser) ParseParenthesis() Ast {
 	return ast
 }
 
-func (parser *Parser) ParseBlock() Ast {
+func (parser *Parser) ParseBlock() *Ast {
+    parser.LogDebug("ParseBlock: %s\n", parser.current.String())
+
 	op := parser.Accept(TokenKindOpenBlock)
 	if op.IsNone() {
 		return NewAstNone()
 	}
+    if op.IsError() {
+        return parser.NewAstError("Unexpected value.")
+    }
 
 	ast := NewAstWithToken(AstKindBlock, op)
 	stats := parser.ParseStatements()
@@ -202,7 +256,7 @@ func (parser *Parser) ParseBlock() Ast {
 	if AstIsError(stats) {
 		return stats
 	}
-	if cp := parser.Accept(TokenKindCloseBlock); cp.IsNone() {
+	if cp := parser.Accept(TokenKindCloseBlock); cp.IsNone() || cp.IsError() {
 		return parser.NewAstError("expected closing block")
 	}
 
@@ -211,7 +265,9 @@ func (parser *Parser) ParseBlock() Ast {
 }
 
 /* Parses the target of a set or get expression */
-func (parser *Parser) ParseTarget() Ast {
+func (parser *Parser) ParseTarget() *Ast {
+    parser.LogDebug("ParseTarget: %s\n", parser.current.String())
+
 	target := parser.Accept(TokenKindWord, TokenKindType, TokenKindSymbol)
 	ast := NewAstWithToken(AstKindTarget, target)
 
@@ -226,7 +282,9 @@ func (parser *Parser) ParseTarget() Ast {
 	return ast
 }
 
-func (parser *Parser) ParseSet() Ast {
+func (parser *Parser) ParseSet() *Ast {
+    parser.LogDebug("ParseSet: %s\n", parser.current.String())
+    
 	set := parser.Accept(TokenKindSet)
 	if set.IsNone() {
 		return NewAstNone()
@@ -244,8 +302,10 @@ func (parser *Parser) ParseSet() Ast {
 	return ast
 }
 
-func (parser *Parser) ParseGet() Ast {
-	get := parser.Accept(TokenKindGet)
+func (parser *Parser) ParseGet() *Ast {
+    parser.LogDebug("ParseGet: %s\n", parser.current.String())
+
+    get := parser.Accept(TokenKindGet)
 	if get.IsNone() {
 		return NewAstNone()
 	}
@@ -255,7 +315,9 @@ func (parser *Parser) ParseGet() Ast {
 	return ast
 }
 
-func (parser *Parser) ParseCommand() Ast {
+func (parser *Parser) ParseCommand() *Ast {
+    parser.LogDebug("ParseCommand: %s\n", parser.current.String())
+
 	word := parser.Accept(TokenKindWord, TokenKindType)
 	if word.IsNone() {
 		return NewAstNone()
@@ -266,48 +328,75 @@ func (parser *Parser) ParseCommand() Ast {
 	return command
 }
 
-func (parser *Parser) ParseExpression() Ast {
-	exp := parser.ParseRequireAny(AstKindExpression, (*Parser).ParseSet,
-		(*Parser).ParseGet, (*Parser).ParseCommand, (*Parser).ParseValue )
+func (parser *Parser) ParseClosed() *Ast {
+    parser.LogDebug("ParseClosed: %s\n", parser.current.String())
+	exp := parser.ParseAny(AstKindClosed, (*Parser).ParseParenthesis, 
+        (*Parser).ParseBlock, (*Parser).ParseList)
 	return exp
 }
 
-func (parser *Parser) ParseEmptyStatement() Ast {
-	eox := parser.Accept(TokenKindEOX)
-	if eox.IsNone() {
-		return NewAstNone()
+func (parser *Parser) ParseExpression() *Ast {
+    parser.LogDebug("ParseExpression: %s\n", parser.current.String())
+	exp := parser.ParseRequireAny(AstKindExpression, (*Parser).ParseCommand, 
+        (*Parser).ParseSet,
+		(*Parser).ParseGet, (*Parser).ParseValue )
+	return exp
+}
+
+func (parser *Parser) ParseExpressionStatement() *Ast {
+    parser.LogDebug("ParseExpressionStatement: %s\n", parser.current.String())
+	expr := parser.ParseExpression()
+    if expr.IsNone() {
+        return NewAstNone()
+    }
+    
+    if eox := parser.Accept(TokenKindEOX); eox.IsNone() {
+		return parser.NewAstError("expected end of statement")
 	}
-	ast := NewAstWithToken(AstKindEnd, eox)
-	return ast
+    
+	return NewAstNone()
 }
 
-func (parser *Parser) ParseStatement() Ast {
-	ast := parser.ParseRequireAny(AstKindStatement,
-		(*Parser).ParseBlock,
-		(*Parser).ParseSet,
-		(*Parser).ParseGet,
-		(*Parser).ParseCommand,
-		(*Parser).ParseParenthesis)
+
+func (parser *Parser) ParseEmptyStatement() *Ast {
+    parser.LogDebug("ParseEmptyStatement: %s\n", parser.current.String())
 	if eox := parser.Accept(TokenKindEOX); eox.IsNone() {
 		return parser.NewAstError("expected end of statement")
 	}
+    return NewAstWithToken(AstKindStatement, parser.current)
+  
+}
+
+func (parser *Parser) ParseStatement() *Ast {
+    parser.LogDebug("ParseStatement: %s\n", parser.current.String())
+    
+	ast := parser.ParseAny(AstKindStatement,
+        (*Parser).ParseClosed,
+        (*Parser).ParseExpressionStatement,
+        (*Parser).ParseEmptyStatement)
 	return ast
 }
 
-func (parser *Parser) ParseStatements() Ast {
-	return parser.ParseMany(AstKindStatements, nil, (*Parser).ParseStatement)
+func (parser *Parser) ParseStatements() *Ast {
+    parser.LogDebug("ParseStatements: %s\n", parser.current.String())
+    return parser.ParseMany(AstKindStatements, nil, (*Parser).ParseStatement)
 }
 
-func (parser *Parser) ParseProgram() Ast {
-	eof := parser.Accept(TokenKindEOF)
-	aeof := NewAstWithToken(AstKindEnd, eof)
+func (parser *Parser) ParseProgram() *Ast {
+    parser.LogDebug("ParseProgram: %s\n", parser.current.String())
+
 	stats := parser.ParseStatements()
 	// Be lenient with missing EOF for now...
-	children := []Ast{stats, aeof}
+	eof := parser.Accept(TokenKindEOF)
+	aeof := NewAstWithToken(AstKindEnd, eof)
+    if eof.IsNone() {
+        aeof = parser.NewAstError("Expceted EOF, have: %s", parser.current.String())
+    }
+    children := []*Ast{stats, aeof}
 	return NewAst(AstKindProgram, nil, children, NoToken())
 }
 
-func (parser *Parser) Parse() Ast {
+func (parser *Parser) Parse() *Ast {
 	ast := parser.ParseProgram()
 	return ast
 }

+ 18 - 3
parser_test.go

@@ -5,7 +5,7 @@ import (
 	"testing"
 )
 
-func HelperFailOnErrors(ast Ast, expected int, test *testing.T) {
+func HelperFailOnErrors(ast * Ast, expected int, test *testing.T) {
 	if ast.IsNone() {
 		test.Errorf("Parse failed, %d parse errors expected", expected)
 	}
@@ -20,7 +20,7 @@ func HelperFailOnErrors(ast Ast, expected int, test *testing.T) {
 }
 
 func HelperParseAndFailOnErrors(prog string, expected int,
-	parsefunc func(*Parser) Ast, test *testing.T) {
+	parsefunc func(*Parser) *Ast, test *testing.T) {
 	parser := NewParserFromString(prog)
 	parser.SetLogger(&testLogger{})
 	ast := parsefunc(parser)
@@ -48,7 +48,21 @@ func TestParenthesis(test *testing.T) {
 	// HelperParseAndFailOnErrors(`add 5 10 `, 0, (*Parser).ParseCommand, test)
 }
 
-func TestParseLexerDesignFile(test *testing.T) {
+func TestClosed(test *testing.T) {
+	HelperParseAndFailOnErrors(`( add 5 10 ) `, 0, (*Parser).ParseStatement, test)
+	// HelperParseAndFailOnErrors(`( add 5 10 ) `, 0, (*Parser).ParseParenthesis, test)
+	// HelperParseAndFailOnErrors(`add 5 10 `, 0, (*Parser).ParseCommand, test)
+}
+
+func TestClosedWithError(test *testing.T) {
+	HelperParseAndFailOnErrors(`( add 5 10 ) ) `, 0, (*Parser).ParseStatement, test)
+	// HelperParseAndFailOnErrors(`( add 5 10 ) `, 0, (*Parser).ParseParenthesis, test)
+	// HelperParseAndFailOnErrors(`add 5 10 `, 0, (*Parser).ParseCommand, test)
+}
+
+
+func TestParseDesignFile(test *testing.T) {
+    
 	parser, err := NewParserFromFilename("design_muesli.muesli")
 	if err != nil { 
         test.Errorf("Error parsingfile : %s", err)
@@ -57,5 +71,6 @@ func TestParseLexerDesignFile(test *testing.T) {
     parser.SetLogger(&testLogger{})
     ast := parser.Parse()
     ast.Display()
+    
 }
 

+ 5 - 1
token.go

@@ -45,7 +45,7 @@ var TokenKindNames map[TokenKind]string = map[TokenKind]string{
 	TokenKindSymbol:     "Symbol",
 	TokenKindString:     "String",
 	TokenKindBoolean:    "Boolean",
-    TokenKindNil:        "?il",
+    TokenKindNil:        "Nil",
 	TokenKindWord:       "Word",
 	TokenKindType:       "Type",
 	TokenKindGet:        "Get",
@@ -116,3 +116,7 @@ func NoToken() Token {
 func (token Token) IsNone() bool {
 	return token.TokenKind == TokenKindNone
 }
+
+func (token Token) IsError() bool {
+	return token.TokenKind == TokenKindError
+}