parser: add comments and [...]; main: add file mode
This commit is contained in:
@@ -2,6 +2,7 @@ package parser
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -18,8 +19,18 @@ func withoutEmpty(input []string) []string {
|
||||
return r
|
||||
}
|
||||
|
||||
var comments = regexp.MustCompile(";.*")
|
||||
var whitespace = regexp.MustCompile("\\s")
|
||||
|
||||
func explode(s string, start string, end string) string {
|
||||
return strings.Replace(strings.Replace(s, start, " "+start+" ", -1), end, " "+end+" ", -1)
|
||||
}
|
||||
|
||||
func tokenize(input string) []string {
|
||||
return withoutEmpty(strings.Split(strings.Replace(strings.Replace(input, "(", " ( ", -1), ")", " ) ", -1), " "))
|
||||
withoutComments := string(comments.ReplaceAll([]byte(input), []byte("")))
|
||||
explodedParens := explode(withoutComments, "(", ")")
|
||||
explodedBrackets := explode(explodedParens, "[", "]")
|
||||
return withoutEmpty(whitespace.Split(explodedBrackets, -1))
|
||||
}
|
||||
|
||||
func parseValue(input []string) (*ast.AST, error, []string) {
|
||||
@@ -53,9 +64,16 @@ func parseValue(input []string) (*ast.AST, error, []string) {
|
||||
return &res, nil, input[1:]
|
||||
}
|
||||
|
||||
func makeFn(bodyStatements []ast.AST) ast.AST {
|
||||
body := ast.AST{ast.List, bodyStatements}
|
||||
args := ast.AST{ast.List, []ast.AST{ast.AST{ast.Symbol, "_"}}}
|
||||
|
||||
return ast.AST{ast.List, []ast.AST{ast.AST{ast.Symbol, "fn"}, args, body}}
|
||||
}
|
||||
|
||||
func parseToken(input []string) (*ast.AST, error, []string) {
|
||||
if len(input) == 0 {
|
||||
return nil, errors.New("Unmatched '('"), input
|
||||
return nil, errors.New("Unmatched '(' or '['"), input
|
||||
}
|
||||
|
||||
if input[0][0] == '\'' {
|
||||
@@ -94,6 +112,25 @@ func parseToken(input []string) (*ast.AST, error, []string) {
|
||||
case ")": {
|
||||
return nil, errors.New("Unmatched ')'"), input
|
||||
}
|
||||
case "[": {
|
||||
var l []ast.AST
|
||||
input = input[1:]
|
||||
for input[0] != "]" {
|
||||
elem, err, newInput := parseToken(input)
|
||||
|
||||
if err != nil {
|
||||
return nil, err, input
|
||||
}
|
||||
|
||||
l = append(l, *elem)
|
||||
input = newInput
|
||||
}
|
||||
res := makeFn(l)
|
||||
return &res, nil, input[1:]
|
||||
}
|
||||
case "]": {
|
||||
return nil, errors.New("Unmatched ']'"), input
|
||||
}
|
||||
}
|
||||
return parseValue(input)
|
||||
}
|
||||
|
Reference in New Issue
Block a user