Quellcode durchsuchen

Add strings and preprocessor directives

Matt Coles vor 9 Jahren
Ursprung
Commit
4a33498b85
3 geänderte Dateien mit 61 neuen und 2 gelöschten Zeilen
  1. 4 0
      README.md
  2. 51 1
      compiler.js
  3. 6 1
      example.mc

+ 4 - 0
README.md

@@ -6,6 +6,10 @@ Currently supports a few built-ins, `add`, `subtract`, `assign`, `def` and `log`
6 6
 they should be from `example.mc`. A `;` denotes that the rest of the line (until the compiler sees `\n`) as a comment and 
7 7
 means that it will not be compiled.
8 8
 
9
+In addition to the regular include(coming soon), there is also a preprocessing directive called `` `source <filename> `` which can be used 
10
+to just directly insert the contents of `<filename>` into the file. Instead of wasting the compilers energy checking for circular
11
+sources, you have two options, to not be so stupid or wait for the call stack to overflow.
12
+
9 13
 The compiler runs like `node compiler.js file.mc` where `file.mc` is the file you wish to compile, and this will produce an
10 14
 `output.js` which requires `stdlib.js` to be in the same directory when running for now at least.
11 15
 

+ 51 - 1
compiler.js

@@ -1,5 +1,17 @@
1 1
 const fs = require('fs')
2 2
 
3
+var preprocess = function (input) {
4
+  let inputArr = input.split('\n')
5
+  for (i = 0; i < inputArr.length; i++) {
6
+    line = inputArr[i]
7
+    if (line.startsWith('`source')) {
8
+      line = fs.readFileSync(line.split(' ')[1], { encoding: 'utf-8' })
9
+      inputArr[i] = preprocess(line)
10
+    }
11
+  }
12
+  return inputArr.join('\n')
13
+}
14
+
3 15
 var tokenizer = function (input) {
4 16
   let pos = 0
5 17
   let tokens = []
@@ -30,6 +42,24 @@ var tokenizer = function (input) {
30 42
       }
31 43
       continue
32 44
     }
45
+    let stringChars = /['"]/
46
+    if (stringChars.test(char)) {
47
+      let myDelim = char
48
+      let stringString = ''
49
+      char = input[++pos]
50
+      while (char !== myDelim) {
51
+        if (char !== '\n') {
52
+          stringString += char
53
+        }
54
+        char = input[++pos]
55
+      }
56
+      pos++
57
+      tokens.push({
58
+        type: 'string',
59
+        value: stringString
60
+      })
61
+      continue
62
+    }
33 63
     let numbers = /[0-9]/
34 64
     if (numbers.test(char)) {
35 65
       let numberString = ''
@@ -110,6 +140,14 @@ var parser = function (input) {
110 140
       }
111 141
     }
112 142
 
143
+    if (token.type === 'string') {
144
+      pos++
145
+      return {
146
+        type: 'StringLiteral',
147
+        value: token.value
148
+      }
149
+    }
150
+
113 151
     if (token.type === 'paren' && token.value == '(') {
114 152
       token = input[++pos]
115 153
       if (token.type !== 'name') {
@@ -171,6 +209,8 @@ var traverser = function (ast, visitor) {
171 209
         break
172 210
       case 'NumberLiteral':
173 211
         break
212
+      case 'StringLiteral':
213
+        break
174 214
       case 'DollarVar':
175 215
         break
176 216
       default:
@@ -200,6 +240,12 @@ var transformer = function (ast) {
200 240
         value: node.value
201 241
       })
202 242
     },
243
+    StringLiteral: function (node, parent) {
244
+      parent._context.push({
245
+        type: 'StringLiteral',
246
+        value: node.value
247
+      })
248
+    },
203 249
     VariableReference: function (node, parent) {
204 250
       parent._context.push({
205 251
         type: 'VariableReference',
@@ -277,6 +323,9 @@ var generator = function (node) {
277 323
     case 'NumberLiteral':
278 324
       return '{value: ' + node.value + '}'
279 325
       break
326
+    case 'StringLiteral':
327
+      return '{ value: \'' + node.value + '\' }'
328
+      break
280 329
     default:
281 330
       throw {
282 331
         name: 'Compiler Error',
@@ -290,7 +339,8 @@ var generator = function (node) {
290 339
 
291 340
 // const myInput = '(assign twelve 12) (assign myvar (add twelve (subtract 6 2))) (log myvar)'
292 341
 const myInput = fs.readFileSync(process.argv[2], { encoding: 'utf-8' })
293
-const myTokens = tokenizer(myInput)
342
+const preProcessedInput = preprocess(myInput)
343
+const myTokens = tokenizer(preProcessedInput)
294 344
 const parsedTree = parser(myTokens)
295 345
 const transformedTree = transformer(parsedTree)
296 346
 //console.log(JSON.stringify(transformedTree,null,2))

+ 6 - 1
example.mc

@@ -18,8 +18,13 @@
18 18
 (myF) ; Calling an argument-less function
19 19
 (log 0)
20 20
 (log 0)
21
-(log 1)
22 21
 (log 0)
23 22
 (log 0)
24 23
 (log 0)
25 24
 (argTest 43 scopelol) ; Custom functions with arguments are called like any other
25
+(log "We got a string!")
26
+(argTest "You can call functions with strings!" "Yay!")
27
+(log "It supports multiline stri
28
+ngs without stupid escape 
29
+
30
+characters")