parser: add comments and [...]; main: add file mode
This commit is contained in:
@@ -27,7 +27,6 @@
|
||||
- `each`
|
||||
- `while`
|
||||
- `repeat`
|
||||
- `[...]`
|
||||
- `:`
|
||||
- `~`
|
||||
- `keep`
|
||||
|
48
main.go
48
main.go
@@ -2,7 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/chzyer/readline"
|
||||
@@ -11,7 +13,7 @@ import (
|
||||
"github.com/hellerve/argos/parser"
|
||||
)
|
||||
|
||||
func main() {
|
||||
func runRepl() {
|
||||
rl, err := readline.New("argos> ")
|
||||
|
||||
if err != nil {
|
||||
@@ -22,13 +24,13 @@ func main() {
|
||||
|
||||
e := eval.ParentEnv()
|
||||
for {
|
||||
prompt, err := rl.Readline()
|
||||
input, err := rl.Readline()
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
parsed, err, unconsumed := parser.Parse(prompt)
|
||||
parsed, err, unconsumed := parser.Parse(input)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
@@ -52,3 +54,43 @@ func main() {
|
||||
fmt.Println(evald.Pretty())
|
||||
}
|
||||
}
|
||||
|
||||
func runFile(path string) {
|
||||
e := eval.ParentEnv()
|
||||
input, err := ioutil.ReadFile(path)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
parsed, err, unconsumed := parser.Parse(string(input))
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(unconsumed) != 0 {
|
||||
fmt.Println("Unconsumed input:", strings.Join(unconsumed, " "))
|
||||
return
|
||||
}
|
||||
|
||||
evald, err := eval.Eval(parsed, e)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(evald.Pretty())
|
||||
}
|
||||
|
||||
func main() {
|
||||
args := os.Args
|
||||
if len(args) == 1 {
|
||||
runRepl()
|
||||
} else {
|
||||
runFile(os.Args[1])
|
||||
}
|
||||
}
|
||||
|
@@ -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