Browse Source

Add lambdas

master
Dylan Baker 5 years ago
parent
commit
bffecce670
2 changed files with 41 additions and 11 deletions
  1. 15
    6
      src/parser.js
  2. 26
    5
      test/parserTest.js

+ 15
- 6
src/parser.js View File

@@ -53,12 +53,15 @@ module.exports = class Parser {
53 53
 
54 54
     if (this.tokenStream.peek().value === 'define') {
55 55
       this.tokenStream.eat(tokenTypes.IDENTIFIER)
56
-
57 56
       node = this.functionDefinition()
57
+    } else if (this.tokenStream.peek().value === 'lambda') {
58
+      this.tokenStream.eat(tokenTypes.IDENTIFIER)
59
+      node = this.functionDefinition(true)
58 60
     } else {
59 61
       node = new AST.Application()
60 62
 
61
-      node.functionName = this.identifier()
63
+      node.function = this.expr()
64
+
62 65
       node.args = []
63 66
 
64 67
       while (this.tokenStream.peek().type !== tokenTypes.CPAREN) {
@@ -84,10 +87,16 @@ module.exports = class Parser {
84 87
     })
85 88
   }
86 89
 
87
-  functionDefinition() {
88
-    let name = new AST.Identifier({
89
-      name: this.tokenStream.eat(tokenTypes.IDENTIFIER).value,
90
-    })
90
+  functionDefinition(anonymous = false) {
91
+    let name
92
+
93
+    if (anonymous) {
94
+      name = false
95
+    } else {
96
+      name = new AST.Identifier({
97
+        name: this.tokenStream.eat(tokenTypes.IDENTIFIER).value,
98
+      })
99
+    }
91 100
 
92 101
     let parameters = []
93 102
 

+ 26
- 5
test/parserTest.js View File

@@ -13,19 +13,19 @@ test('parses token stream into a tree', t => {
13 13
 
14 14
   t.deepEqual(tree, [
15 15
     new AST.Application({
16
-      functionName: new AST.Identifier({ name: 'div' }),
16
+      function: new AST.Identifier({ name: 'div' }),
17 17
       args: [
18 18
         new AST.Attribute({
19 19
           name: 'class',
20 20
           value: new AST.String({ value: 'foobar' }),
21 21
         }),
22 22
         new AST.Application({
23
-          functionName: new AST.Identifier({ name: 'p' }),
23
+          function: new AST.Identifier({ name: 'p' }),
24 24
           args: [
25 25
             new AST.Attribute({
26 26
               name: 'class',
27 27
               value: new AST.Application({
28
-                functionName: new AST.Identifier({ name: 'cond' }),
28
+                function: new AST.Identifier({ name: 'cond' }),
29 29
                 args: [
30 30
                   new AST.Boolean({ value: true }),
31 31
                   new AST.String({ value: 'primary' }),
@@ -46,7 +46,7 @@ test('allow empty strings', t => {
46 46
 
47 47
   t.deepEqual(tree, [
48 48
     new AST.Application({
49
-      functionName: new AST.Identifier({ name: 'p' }),
49
+      function: new AST.Identifier({ name: 'p' }),
50 50
       args: [new AST.String({ value: '' })],
51 51
     }),
52 52
   ])
@@ -61,9 +61,30 @@ test('parses calls to define into a function definition', t => {
61 61
       name: new AST.Identifier({ name: 'plusOne' }),
62 62
       parameters: [new AST.Identifier({ name: 'n' })],
63 63
       body: new AST.Application({
64
-        functionName: new AST.Identifier({ name: '+' }),
64
+        function: new AST.Identifier({ name: '+' }),
65 65
         args: [new AST.Identifier({ name: 'n' }), new AST.Number({ value: 1 })],
66 66
       }),
67 67
     }),
68 68
   ])
69 69
 })
70
+
71
+test('parse lambdas and expressions in function position', t => {
72
+  t.plan(1)
73
+  const tree = helpers.parse('((lambda (n) (+ n 1)) 5)')
74
+
75
+  t.deepEqual(tree, [
76
+    new AST.Application({
77
+      function: new AST.FunctionDefinition({
78
+        name: false,
79
+        parameters: [new AST.Identifier({ name: 'n' })],
80
+        body: new AST.Application({
81
+          function: new AST.Identifier({ name: '+' }),
82
+          args: [new AST.Identifier({ name: 'n' }), new AST.Number({ value: 1 })],
83
+        }),
84
+      }),
85
+      args: [
86
+        new AST.Number({ value: 5 })
87
+      ]
88
+    })
89
+  ])
90
+})

Loading…
Cancel
Save