Skip to content

Commit dba9b72

Browse files
committed
Hacking; added basic tests and if/let/fn special forms
1 parent 740dd9b commit dba9b72

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+16695
-253
lines changed

Makefile

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.PHONY: bootstrap build-parser watch
22

3+
GRAMMARFILE=grammar.peg
34
PARSERFILE=lang/parser.go
45
SAMPLEFILE=samples/sample1.clj
56

@@ -9,12 +10,15 @@ bootstrap:
910
go get -u github.com/cespare/reflex
1011

1112
watch:
12-
reflex --inverse-glob=$(PARSERFILE) -- $(MAKE) test-parser
13+
reflex --inverse-glob=$(PARSERFILE) -- $(MAKE) test
1314

14-
build-parser:
15-
echo "package lang" > $(PARSERFILE)
16-
pigeon <grammar.peg | gofmt >>$(PARSERFILE)
15+
$(PARSERFILE): $(GRAMMARFILE)
16+
@echo "== Rebuilding parser"
17+
echo "package lang" > $@
18+
pigeon <$< | gofmt >>$@
1719

18-
test-parser: build-parser
19-
go run main.go $(SAMPLEFILE)
20+
build-parser: $(PARSERFILE)
2021

22+
test: $(PARSERFILE)
23+
@echo "== Running unit tests"
24+
go test ./...

glide.lock

+4-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

glide.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ package: github.com/davehughes/lparse
22
import:
33
- package: github.com/pkg/errors
44
version: ^0.8.0
5+
- package: github.com/stretchr/testify
6+
version: ^1.1.4

grammar.peg

+53-28
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ Input <- forms:Form* EOF {
99
}
1010

1111
Form <- _ form:( LineComment / List / Lambda / Vector / Set / Map /
12-
QuotedForm / Numeric / Symbol / Keyword / String
12+
QuotedForm / AtomDeref / Numeric / Symbol / Keyword / String
1313
) _ {
14-
fmt.Printf("Form: %v\n", form)
15-
return string(c.text), nil
14+
// fmt.Printf("Form: %v\n", form)
15+
return form, nil
1616
}
1717

1818
EOF = !.
@@ -24,46 +24,56 @@ LineComment <- _? ';' comment:[^\r\n]* {
2424
Position: Position{Line: c.pos.line, Column: c.pos.col, Offset: c.pos.offset},
2525
Value: fmt.Sprint(comment),
2626
}, nil
27-
/* return showComponent("commented-line", c.text) */
2827
}
2928

3029
List <- '(' forms:Form* ')' {
31-
return &Collection{
30+
return &List{
3231
Position: Position{Line: c.pos.line, Column: c.pos.col, Offset: c.pos.offset},
33-
Type: CollectionList,
34-
Items: forms.([]interface{}),
32+
Forms: forms.([]interface{}),
3533
}, nil
3634
}
3735

3836
Vector <- '[' forms:Form* ']' {
39-
return &Collection{
37+
return &Vector{
4038
Position: Position{Line: c.pos.line, Column: c.pos.col, Offset: c.pos.offset},
41-
Type: CollectionVector,
42-
Items: forms.([]interface{}),
39+
Forms: forms.([]interface{}),
4340
}, nil
4441
}
4542

4643
Map <- '{' forms:Form* '}' {
47-
return &Collection{
44+
numForms := len(forms.([]interface{}))
45+
if numForms % 2 != 0 {
46+
return nil, ErrOddNumberOfMapForms
47+
}
48+
return &Map{
4849
Position: Position{Line: c.pos.line, Column: c.pos.col, Offset: c.pos.offset},
49-
Type: CollectionMap,
50-
Items: forms.([]interface{}),
50+
Forms: forms.([]interface{}),
5151
}, nil
5252
}
5353

54-
Set <- '#' '{' forms:Form '}' {
55-
return &Collection{
54+
Set <- '#' '{' forms:Form* '}' {
55+
return &Set{
5656
Position: Position{Line: c.pos.line, Column: c.pos.col, Offset: c.pos.offset},
57-
Type: CollectionSet,
58-
Items: forms.([]interface{}),
57+
Forms: forms.([]interface{}),
5958
}, nil
6059
}
6160

6261
Lambda <- '#' '(' forms:Form* ')' {
63-
return &Collection{
62+
return &Lambda{
63+
Position: Position{Line: c.pos.line, Column: c.pos.col, Offset: c.pos.offset},
64+
Forms: forms.([]interface{}),
65+
}, nil
66+
}
67+
68+
AtomDeref <- "@" form:Form {
69+
return &List{
6470
Position: Position{Line: c.pos.line, Column: c.pos.col, Offset: c.pos.offset},
65-
Type: CollectionLambda,
66-
Items: forms.([]interface{}),
71+
Forms: []interface{}{
72+
&Symbol{
73+
Name: "deref",
74+
},
75+
form,
76+
},
6777
}, nil
6878
}
6979

@@ -72,29 +82,44 @@ Keyword <- ( NamespacedKeyword / BareKeyword)
7282
NamespacedKeyword <- ':' ':' sym:Symbol {
7383
return &Keyword{
7484
Position: Position{Line: c.pos.line, Column: c.pos.col, Offset: c.pos.offset},
75-
Name: fmt.Sprint(sym),
85+
Name: (sym.(*Symbol)).Name,
7686
Namespace: "TODO: namespaced",
7787
}, nil
7888
}
7989

8090
BareKeyword <- ':' sym:Symbol {
8191
return &Keyword{
8292
Position: Position{Line: c.pos.line, Column: c.pos.col, Offset: c.pos.offset},
83-
Name: fmt.Sprint(sym),
93+
Name: (sym.(*Symbol)).Name,
8494
}, nil
8595
}
8696

8797
Symbol <- [a-z0-9-+*?!&^%#?<>%/\\]i+ {
88-
return &Symbol{
89-
Position: Position{Line: c.pos.line, Column: c.pos.col, Offset: c.pos.offset},
90-
Name: string(c.text),
91-
}, nil
98+
pos := Position{Line: c.pos.line, Column: c.pos.col, Offset: c.pos.offset}
99+
switch string(c.text) {
100+
case "nil":
101+
return &Nil{Position: pos}, nil
102+
case "true":
103+
return &True{Position: pos}, nil
104+
case "false":
105+
return &False{Position: pos}, nil
106+
default:
107+
return &Symbol{
108+
Position: pos,
109+
Name: string(c.text),
110+
}, nil
111+
}
92112
}
93113

94114
QuotedForm <- ( "'" ) form:Form {
95-
return &QuotedForm{
115+
return &List{
96116
Position: Position{Line: c.pos.line, Column: c.pos.col, Offset: c.pos.offset},
97-
Form: form,
117+
Forms: []interface{}{
118+
&Symbol{
119+
Name: "quote",
120+
},
121+
form,
122+
},
98123
}, nil
99124
}
100125

lang/ast.go

+21-15
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,19 @@ type Keyword struct {
1414
Namespace string
1515
}
1616

17+
func (s Keyword) String() string {
18+
return fmt.Sprintf("(keyword %v)", s.Name)
19+
}
20+
1721
type Symbol struct {
1822
Position
1923
Name string
2024
}
2125

26+
func (s Symbol) String() string {
27+
return fmt.Sprintf("(symbol %v)", s.Name)
28+
}
29+
2230
type String struct {
2331
Position
2432
Value string
@@ -39,22 +47,17 @@ type Position struct {
3947
Offset int
4048
}
4149

42-
type CollectionType int
43-
44-
const (
45-
CollectionList CollectionType = iota
46-
CollectionVector
47-
CollectionMap
48-
CollectionSet
49-
CollectionLambda
50-
)
51-
52-
type Collection struct {
50+
type Container struct {
5351
Position
54-
Type CollectionType
55-
Items []interface{}
52+
Forms []interface{}
5653
}
5754

55+
type List Container
56+
type Vector Container
57+
type Map Container
58+
type Set Container
59+
type Lambda Container
60+
5861
type Integer struct {
5962
Position
6063
ParsedValue string
@@ -67,7 +70,10 @@ type Float struct {
6770
Value float64
6871
}
6972

70-
type QuotedForm struct {
73+
type ReservedWord struct {
7174
Position
72-
Form interface{}
7375
}
76+
77+
type Nil ReservedWord
78+
type True ReservedWord
79+
type False ReservedWord

lang/errors.go

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package lang
2+
3+
import "github.com/pkg/errors"
4+
5+
var (
6+
ErrNotImplemented = errors.New("Not implemented")
7+
ErrOddNumberOfMapForms = errors.New("Map literal must contain an even number of forms")
8+
ErrIfTooFewArgs = errors.New("Too few args to if")
9+
ErrIfTooManyArgs = errors.New("Too many args to if")
10+
ErrUnresolvedSymbol = errors.New("Unable to resolve symbol")
11+
ErrOddNumberOfBindingForms = errors.New("Binding vector must have an even number of forms")
12+
ErrUnrecognizedBindingForm = errors.New("Unrecognized binding form")
13+
)

0 commit comments

Comments
 (0)