├── .gitignore ├── README.md ├── deprecated ├── base.h └── dynamic.c ├── examples ├── body.jhe ├── body10.jhe ├── body11.jhe ├── body12.jhe ├── body13.jhe ├── body2.jhe ├── body3.jhe ├── body4.jhe ├── body5.jhe ├── body6.jhe ├── body7.jhe ├── body8.jhe └── body9.jhe ├── jlc.js ├── package.json └── src ├── basicTypes.js ├── buildFunctions.js ├── functionDefinitions.js ├── helpers ├── chars.js ├── findClassName.js ├── func.js ├── helpers.js ├── interpreterControl.js ├── set.js ├── textControl.js ├── tree.js └── variables.js ├── interpreter.js ├── jedlang.h ├── parser.js └── parser_module.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | test.* 3 | node_modules/ 4 | node_modules/* 5 | *.out 6 | output.c 7 | printTree.js 8 | fib.js -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JedLang 2 | ======= 3 | 4 | JedLang is a crazy lisp-like languge that I made up for fun. While it is not very readable, it is intended to be very terse and easy to use. It compiles to C. 5 | 6 | Use 7 | --- 8 | Clone this repository and cd into the directory. Write a JedLang file and give it a .jhe extension. Compilation requires the use of the GCC compiler, but another can be substituted in src/interpreter.js. To compile and run use the following pattern: 9 | 10 | ```shell 11 | node jlc.js path/to/filename output_filename 12 | ``` 13 | The above command will create both filename.out and output.c, and it assumes you do not include the extension with the filename. Running the code is just like running any other .out file, it is just compiled c code: 14 | ```shell 15 | ./output_filename.out 16 | ``` 17 | 18 | Documentation 19 | ============ 20 | 21 | Lispy Math 22 | ---------- 23 | ```lisp 24 | (+ 3 2) 25 | (/ 4 2) 26 | (- 4 (/4 2)) 27 | ``` 28 | 29 | Output 30 | ------ 31 | ```lisp 32 | (@ (+3 2)) //=> 5 33 | (@ "Hello, world.") //=> Hello, world. 34 | ``` 35 | 36 | Functions 37 | --------- 38 | 39 | Core functions: 40 | \+ (X, Y) -> returns sum 41 | \- (X, Y) -> returns difference 42 | \* (X, Y) -> returns product 43 | / (X, Y) -> divides X and Y 44 | @ (X) -> prints value of X to console 45 | ^ (X, Y) -> prepends X onto Y, where Y is an array 46 | _ (X, Y) -> returns member of set Y at index X 47 | \> (X, Y) -> returns true if X is greater than Y 48 | < (X, Y) -> returns true if X is less than Y 49 | = (X, Y) -> returns true if X equals Y 50 | ! (X, Y) -> returns true if X doesn't equal Y 51 | ? (X, Y, Z) -> returns Y if X is true, otherwise returns Z 52 | | (X) -> returns X 53 | . (X) -> returns length of X, where X is an array or a set 54 | 55 | Define a custom function with def. The def command goes like this: 56 | 57 | ```lisp 58 | (def ) 59 | ``` 60 | Make sure to use X Y or Z for you argument names, they correspond to the first, second and third arguments of a function invocation. 61 | 62 | There is another kind of custom function that uses core functions. There is reduce (REDC), array (ARRY), filter (FLTR) and each (EACH). 63 | 64 | They are used like this: 65 | 66 | ```lisp 67 | (def REDC ) // takes an array as input 68 | (def ARRY ) // takes a number of iterations and (X) element to iterate 69 | (def FLTR ) // takes a boolean function and a set (X) to iterate over 70 | (def EACH ) // takes an array or set (X) as input 71 | ``` 72 | The iterator in REDC can take a lowercase letter to stand in for the element at the current index during iteration. The other functions use X to stand for the arguments used to invoke the function. Here is a set of examples to demonstrate function definitions, not that definitions should always come at the top of a file, they are arranged here differently for purposes of demonstration. For working examples look in the examples directory of this repo. 73 | 74 | ```lisp 75 | (def sum REDC (+ e)) 76 | (@ (sum [1,2,3,4])) //=> 10 77 | (def len REDC (+ 1)) 78 | (@ (len [1,2,3,4])) //=> 4 79 | 80 | (def count ARRY (+ X 1)) 81 | (@ (count 4 0)) //=> [1,2,3,4] 82 | 83 | (def avg X (/ sum len)) 84 | (@ (avg (count 4 0))) //=> 2.5 85 | 86 | (def tot X (^ (sum X) X)) 87 | (@ (tot [1,2,3,4])) //=> [10,1,2,3,4] 88 | (def all X (^ (avg X) (tot X))) 89 | (@(all [1,2,3,4])) //=> [2.5,10,1,2,3,4] 90 | ``` 91 | 92 | Filter can only be used on sets: 93 | ```lisp 94 | (set plant1 {"healthy", 31}) 95 | (set plant2 {"healthy", 9}) 96 | (set plant3 {"unhealthy", 13}) 97 | (set plants {plant1, plant2, plant3}) 98 | (def healthy FLTR (= (_ 0 X) "healthy")) //=> returns a set of {plant1, plant2} 99 | ``` 100 | Each can be used with both arrays and sets: 101 | ```lisp 102 | (set jim {"James" 23}) 103 | (set bob {"Bob" 21}) 104 | (set dan {"Dan" 25}) 105 | (set employees {jim bob dan}) 106 | (def incr EACH (+ X 1)) 107 | (def see EACH (@ (_ 0 X))) 108 | 109 | (see employees) //=> James Bob Dan 110 | (@(incr [1,2,3,4,5,6])) //=> [2, 3, 4, 5, 6, 7] 111 | ``` 112 | Booleans 113 | -------- 114 | There are functions that output booleans: 115 | ```lisp 116 | (@ (> 4 3)) //=> True 117 | (@ (< 1 0)) //=> False 118 | (@ (= 1 1)) //=> True 119 | ``` 120 | The equality operator checks arrays and sets to see if the all members are equal: 121 | ```lisp 122 | (set james {"James" "Edwards"}) 123 | (set jim {"James" "Bergson"}) 124 | 125 | (@ (= [1,2,4,3] [1,2,3,4])) //=> False 126 | (@ (= james jim)) //=> False 127 | ``` 128 | 129 | The conditional function takes a boolean function as its first argument: 130 | ```lisp 131 | (@ (? (> (avg [1,2,3,4]) 1) 10 0)) //=> 10 132 | 133 | (def wow X Y (? (> X Y) (@ "wham") (@ "whoozle"))) 134 | (wow 4 3) //=> "wham" 135 | ``` 136 | The conditional function can return functions, as in the two print functions above, or values like in the implementation of fibonnaci below: 137 | 138 | ```lisp 139 | (def low X (? (> X 0) 1 0)) 140 | (def fib X (? (< X 3) (low X) (+ (fib (- X 1)) (fib (- X 2))))) 141 | ``` 142 | Sets 143 | ---- 144 | 145 | Sets are not sets in the mathematical sense, they are just groupings of mixed type values. Sets can have set members: 146 | 147 | ```lisp 148 | (set james {"James", 31, "Developer"}) 149 | (set mary {"Mary", 29, "Architect"}) 150 | (set john {"John", 25, "Intern"}) 151 | (set employees {james, mary, john}) 152 | 153 | (def fst X (_ 0 X)) 154 | (def lst X (_ (- (. X) 1) X)) 155 | (def job X Y (@ (lst (_ X Y)))) 156 | 157 | (@ (_ 0 (fst employees))) //=> "James" 158 | (job (- (. employees) 1) employees) //=> "Intern" 159 | ``` 160 | 161 | Keyword let 162 | ----------- 163 | 164 | In Jedlang, let is used to create a set by passing a set into one or more functions. The following example should serve to illustrate this usage: 165 | ```lisp 166 | (set values {11, 12}) 167 | (set numbers {41, 44}) 168 | (def add_one EACH (+ 1 X)) 169 | (def inner EACH (add_one X)) 170 | (set vals {values, numbers}) 171 | (let plus_one (inner vals)) // plus_one is now the result of passing vals into inner 172 | (@ (_ 0 ( _ 0 plus_one))) //=> 12 173 | ``` 174 | 175 | Classes 176 | ------- 177 | Classes are basically just functions that return sets. You can think of them as set partials. When you define a class, you can use X, Y and Z for arguments and any other value, including sets, for elements of the return set that will be the same for each set returned by the class function. Here is the pattern: 178 | 179 | ```lisp 180 | (def CLSS { }) // define a class function 181 | (set ( )) // use class function to instantiate a set 182 | ``` 183 | 184 | The following is an example taken directly from example file #10 in the examples directory, another example may be found in example file #9. 185 | ```lisp 186 | // camellia is a plant with genus camellia and species X 187 | (def cmlia CLSS { "camellia", X}) 188 | 189 | // teacea is a plant of family Teaceae and genus/species pair X 190 | (def teaceae CLSS { "Teaceae", X}) 191 | 192 | // make a tea object, i.e. { "camellia", "sinensis" } 193 | (set tea (cmlia "sinensis")) 194 | 195 | // make a full tea object { "Teaceae", { "camellia", "sinensis" }} 196 | (set tea_full (teaceae tea)) 197 | (@ (_ 0 tea_full)) //=> "Teacea" 198 | ``` 199 | Class Constrained Functions 200 | --------------------------- 201 | Jedlang offers the ability to define functions with class constrictions. For now, it only supports one class per function. To define a class restricted function, simply use the name of a class anywhere in the function definition. If there are other arguments to that function, the class object will be assumed to be the last argument to the function. 202 | ```lisp 203 | (def plant CLSS { X, Y }) 204 | (def genus (_ 0 plant)) // a function that only takes a "plant" object 205 | (set tea (plant "Camelia" "Sinensis")) 206 | (genus tea) //=> "Camelia" 207 | ``` 208 | -------------------------------------------------------------------------------- /deprecated/base.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define TRUTHY "True" 5 | #define FALSY "False" 6 | 7 | int add(int, int); 8 | int sub(int, int); 9 | int mult(int, int); 10 | int div(int, int); 11 | int showInt(int); 12 | int showChar(char*); 13 | struct Array append(int, struct Array); 14 | char greater(int, int); 15 | char less(int, int); 16 | 17 | struct Array { 18 | int *body; 19 | int len; 20 | }; 21 | 22 | 23 | // BOOLEANS 24 | 25 | int showBool(char b){ 26 | char tc = 't'; 27 | int val = strcmp(&b, &tc); 28 | val == 0 ? printf("%s\n", TRUTHY) : printf("%s\n", FALSY); 29 | return 0; 30 | }; 31 | 32 | int istrue(char c){ 33 | char tc = 't'; 34 | int result; 35 | if(c == tc){ 36 | result = 1; 37 | } else { 38 | result = 0; 39 | } 40 | return result; 41 | }; 42 | 43 | char greater(int a, int b){ 44 | char result; 45 | if(a > b){ 46 | result = 't'; 47 | } else { 48 | result = 'f'; 49 | } 50 | return result; 51 | }; 52 | 53 | char less(int a, int b){ 54 | char result; 55 | if(a < b){ 56 | result = 't'; 57 | } else { 58 | result = 'f'; 59 | } 60 | return result; 61 | }; 62 | 63 | int condition(char boolean, int a, int b){ 64 | int result; 65 | int compare = strcmp(&boolean, "t"); 66 | if(compare == 0){ 67 | result = a; 68 | } else { 69 | result = b; 70 | } 71 | return result; 72 | } 73 | 74 | // MATH 75 | 76 | int add(int x, int y){ 77 | int r; 78 | r = x + y; 79 | return r; 80 | }; 81 | 82 | int sub(int x, int y){ 83 | int r; 84 | r = x - y; 85 | return r; 86 | }; 87 | 88 | int mult(int x, int y){ 89 | int r; 90 | r = x * y; 91 | return r; 92 | }; 93 | 94 | int div(int x, int y){ 95 | int r; 96 | r = x / y; 97 | return r; 98 | }; 99 | 100 | int showInt(int n){ 101 | printf("%d\n", n); 102 | return 0; 103 | }; 104 | 105 | // ARRAYS 106 | 107 | int showArray(struct Array a){ 108 | printf("["); 109 | for(int i = 0; i < a.len; ++i){ 110 | if(i < (a.len-1)){ 111 | printf("%d, ", a.body[i]); 112 | } else { 113 | printf("%d", a.body[i]); 114 | } 115 | } 116 | printf("]\n"); 117 | return 0; 118 | }; 119 | 120 | struct Array append(int num, struct Array a){ 121 | a.len = a.len + 1; 122 | for(int n = (a.len-1); n >= 0; --n){ 123 | if(n == 0){ 124 | a.body[0] = num; 125 | } else { 126 | a.body[n] = a.body[n-1]; 127 | } 128 | } 129 | return a; 130 | }; 131 | 132 | int showChar(char *h){ 133 | printf("%s\n", h); 134 | return 0; 135 | }; 136 | -------------------------------------------------------------------------------- /deprecated/dynamic.c: -------------------------------------------------------------------------------- 1 | # include 2 | # include 3 | 4 | union Data { 5 | int i; 6 | float f; 7 | char *s; 8 | int *ia; 9 | union Data *ua; 10 | }; 11 | 12 | struct Object { 13 | char type; 14 | int length; 15 | union Data dat; 16 | }; 17 | 18 | struct Object show(struct Object obj){ 19 | if(obj.type == 's'){ 20 | printf("%s\n", obj.dat.s); 21 | } 22 | else if(obj.type == 'i'){ 23 | printf("%d\n", obj.dat.i); 24 | } 25 | else if(obj.type == 'f'){ 26 | printf("%f\n", obj.dat.f); 27 | } 28 | else if(obj.type == 'b'){ 29 | char result[10]; 30 | strcpy(result, obj.dat.i == 0 ? "False" : "True"); 31 | printf("%s\n", result); 32 | } 33 | else if(obj.type == 'a'){ 34 | printf("["); 35 | for(int i = 0; i < obj.length; ++i){ 36 | if(i < (obj.length-1)){ 37 | printf("%d, ", obj.dat.ia[i]); 38 | } else { 39 | printf("%d", obj.dat.ia[i]); 40 | } 41 | } 42 | printf("]\n"); 43 | } 44 | return obj; 45 | }; 46 | struct Object createInt(int num){ 47 | union Data d; 48 | d.i = num; 49 | struct Object obj = {'i',0,d}; 50 | return obj; 51 | }; 52 | struct Object createFloat(float num){ 53 | union Data d; 54 | d.f = num; 55 | struct Object obj = {'f',0,d}; 56 | return obj; 57 | }; 58 | struct Object createString(char *str){ 59 | union Data d; 60 | d.s = str; 61 | struct Object obj = {'s',0,d}; 62 | return obj; 63 | }; 64 | 65 | struct Object createArray(int *ia){ 66 | union Data d; 67 | d.ia = ia; 68 | struct Object obj = {'a',1,d}; 69 | return obj; 70 | }; 71 | 72 | struct Object getInt(struct Object obj){ 73 | union Data d; 74 | if(obj.type == 'i'){ 75 | return createInt(obj.dat.i); 76 | } 77 | else { 78 | return createInt(obj.dat.ia[0]); 79 | } 80 | }; 81 | 82 | struct Object getFloat(struct Object obj){ 83 | union Data d; 84 | if(obj.type == 'f'){ 85 | return createFloat(obj.dat.f); 86 | } 87 | else { 88 | return createFloat(obj.dat.ia[0]); 89 | } 90 | }; 91 | 92 | 93 | 94 | struct Object add(struct Object a, struct Object b){ 95 | if(a.type == 'i'){ 96 | a.dat.i = a.dat.i + b.dat.i; 97 | } else { 98 | a.dat.f = a.dat.f + b.dat.f; 99 | } 100 | return a; 101 | }; 102 | 103 | struct Object sub(struct Object a, struct Object b){ 104 | if(a.type == 'i'){ 105 | a.dat.i = a.dat.i - b.dat.i; 106 | } else { 107 | a.dat.f = a.dat.f - b.dat.f; 108 | } 109 | return a; 110 | }; 111 | 112 | struct Object mult(struct Object a, struct Object b){ 113 | if(a.type == 'i'){ 114 | a.dat.i = a.dat.i * b.dat.i; 115 | } else { 116 | a.dat.f = a.dat.f * b.dat.f; 117 | } 118 | return a; 119 | }; 120 | 121 | struct Object div(struct Object a, struct Object b){ 122 | if(a.type == 'i'){ 123 | a.dat.i = a.dat.i / b.dat.i; 124 | } else { 125 | a.dat.f = a.dat.f / b.dat.f; 126 | } 127 | return a; 128 | }; 129 | 130 | struct Object greater(struct Object a, struct Object b){ 131 | union Data dt; 132 | struct Object obj = {'i',0, dt}; 133 | 134 | if(a.type == 'i'){ 135 | obj.dat.i = a.dat.i > b.dat.i ? 1 : 0; 136 | } else { 137 | obj.dat.f = a.dat.f > b.dat.f ? 1 : 0; 138 | } 139 | obj.type = 'b'; 140 | return obj; 141 | }; 142 | 143 | struct Object less(struct Object a, struct Object b){ 144 | union Data dt; 145 | struct Object obj = {'i',0, dt}; 146 | 147 | if(a.type == 'i'){ 148 | obj.dat.i = a.dat.i < b.dat.i ? 1 : 0; 149 | } else { 150 | obj.dat.f = a.dat.f < b.dat.f ? 1 : 0; 151 | } 152 | obj.type = 'b'; 153 | return obj; 154 | }; 155 | 156 | struct Object identity(struct Object a){ 157 | return a; 158 | }; 159 | 160 | struct Object append(struct Object a, struct Object b){ 161 | int arr[b.length+1]; 162 | for(int i = 0; i < b.length+1; i++){ 163 | if(i < b.length){ 164 | arr[i] = b.dat.ia[i]; 165 | } else { 166 | arr[i] = a.dat.i; 167 | } 168 | } 169 | b.dat.ia = arr; 170 | b.length = b.length + 1; 171 | return b; 172 | }; 173 | 174 | struct Object prepend(struct Object a, struct Object b){ 175 | b.length = b.length+1; 176 | int frst = a.dat.i; 177 | int temp, insert; 178 | for(int i = 0; i < b.length; i++){ 179 | if(i == 0){ 180 | temp = b.dat.ia[0]; 181 | b.dat.ia[0] = frst; 182 | } else { 183 | insert = temp; 184 | temp = b.dat.ia[i]; 185 | b.dat.ia[i] = insert; 186 | } 187 | } 188 | b.type = 'a'; 189 | return b; 190 | }; 191 | 192 | int main(){ 193 | // char hey[50]; 194 | // strcpy(hey, "Hello! I love everything about the world!"); 195 | // union Data d; 196 | // d.s = hey; 197 | // struct Object obj = {'s',0, d}; 198 | // show(&obj); 199 | 200 | // setInt(&obj, 8); 201 | // show(&obj); 202 | 203 | // setFloat(&obj, 12.12); 204 | // show(&obj); 205 | 206 | // setString(&obj, &hey[0]); 207 | // show(&obj); 208 | 209 | // //test adding integers 210 | // union Data dt; 211 | // dt.i = 4; 212 | // struct Object obj_b = {'i',0, dt}; 213 | // show(add(&obj, &obj_b)); 214 | 215 | // //test compare integers 216 | // union Data d; 217 | // d.i = 7; 218 | // struct Object obj = {'i',0,d}; 219 | // union Data dt; 220 | // dt.i = 10; 221 | // struct Object obj_b = {'i',0,dt}; 222 | // show(greater(&obj, &obj_b)); 223 | 224 | // //test show array and append 225 | // union Data d; 226 | // int arry[5] = { 1, 2, 3, 4, 5 }; 227 | // d.ia = arry; 228 | // struct Object obj = {'a', 5, d}; 229 | // union Data dt; 230 | // dt.i = 10; 231 | // struct Object obj_a = {'i',0, dt}; 232 | // show(append(&obj_a, &obj)); 233 | 234 | // struct size 235 | union Data dat; 236 | struct Object obj = {'i',1,dat}; 237 | printf("%lu\n", sizeof(obj)); 238 | 239 | // array of structs 240 | union Data da; 241 | da.i = 1; 242 | union Data db; 243 | db.i = 2; 244 | union Data dat_arr[2] = {da, db}; 245 | union Data dc; 246 | dc.ua = dat_arr; 247 | struct Object obj_a = {'o',2, dc}; 248 | printf("%d\n", obj_a.dat.ua[0].i); 249 | printf("%d\n", obj_a.dat.ua[1].i); 250 | return 0; 251 | }; -------------------------------------------------------------------------------- /examples/body.jhe: -------------------------------------------------------------------------------- 1 | (def incr EACH (+ X 1)) 2 | (@(incr [1,2,3,4,5,6]))) -------------------------------------------------------------------------------- /examples/body10.jhe: -------------------------------------------------------------------------------- 1 | (def plant CLSS { X, Y }) 2 | (def binom CLSS { X, Y }) 3 | (def teaceae CLSS { "Teaceae", X }) 4 | (set tea_binom (binom "camellia" "sinensis") 5 | (set tea_plant (teaceae tea_binom)) 6 | (def family (_ 0 plant)) 7 | (family tea_plant) -------------------------------------------------------------------------------- /examples/body11.jhe: -------------------------------------------------------------------------------- 1 | (def fst X (_ 0 X)) 2 | (def snd X (_ 1 X)) 3 | (set values {11, 12} ) 4 | (set numbers {41, 44} ) 5 | (set vals {values, numbers}) 6 | (def add_one EACH (+ 1 X)) 7 | (def inner EACH (add_one X)) 8 | (let big (inner vals)) 9 | (@ (fst (fst big))) 10 | (@ (snd (fst big))) 11 | (@ (fst (snd big))) 12 | (@ (snd (snd big))) -------------------------------------------------------------------------------- /examples/body12.jhe: -------------------------------------------------------------------------------- 1 | (def plant CLSS { X, Y }) 2 | (def point CLSS { X, Y }) 3 | (def genus (_ 0 plant)) 4 | (def half EACH (/ 2 X)) 5 | (def mid (half point)) 6 | (def x_coord (_ 0 point)) 7 | (def y_coord (_ 1 point)) 8 | 9 | (set tea (plant "Camelia" "Sinensis")) 10 | (set point_a (point 3 7)) 11 | (@(genus tea)) 12 | (@(x_coord point_a)) 13 | (@(y_coord point_a)) -------------------------------------------------------------------------------- /examples/body13.jhe: -------------------------------------------------------------------------------- 1 | (def point CLSS { X, Y }) 2 | (def incrx X (+ X (_ 0 point))) 3 | (set point_a (point 3 4)) 4 | (@ (incrx 3 point_a)) 5 | -------------------------------------------------------------------------------- /examples/body2.jhe: -------------------------------------------------------------------------------- 1 | (def sum EACH (+ e) NULL 0) 2 | (def len EACH (+ 1) NULL 0) 3 | (def avg X (/ (sum X) (len X))) 4 | (@(avg [1,2,3,4])) -------------------------------------------------------------------------------- /examples/body3.jhe: -------------------------------------------------------------------------------- 1 | (def sum REDC (+ e)) 2 | (def len REDC (+ 1)) 3 | (def avg X (/ (sum X) (len X))) 4 | 5 | (def tot X (^ (sum X) X)) 6 | (def all X (^ (avg X) (tot X))) 7 | 8 | (@ (all [1,2,3,4])) -------------------------------------------------------------------------------- /examples/body4.jhe: -------------------------------------------------------------------------------- 1 | (def len REDC (+ 1)) 2 | (def sum REDC (+ e)) 3 | (def avg X (/ (sum X) (len X))) 4 | (def count ARRY (+ X 1)) 5 | (@(avg (count 4 1))) 6 | (@(+(avg (count 4 1)) 3)) 7 | -------------------------------------------------------------------------------- /examples/body5.jhe: -------------------------------------------------------------------------------- 1 | (def mlt REDC (* e)) 2 | (def count ARRY (+ X 1)) 3 | (def fac X (mlt (count X 1))) 4 | (@ (fac 24)) -------------------------------------------------------------------------------- /examples/body6.jhe: -------------------------------------------------------------------------------- 1 | (set james {"James", 31, "Developer"}) 2 | (set mary {"Mary", 29, "Architect"}) 3 | (set john {"John", 25, "Intern"}) 4 | (set employees {james, mary, john}) 5 | 6 | (def fst X (_ 0 X)) 7 | (def lst X (_ (- (. X) 1) X)) 8 | (def job X Y (@ (lst (_ X Y)))) 9 | (job (- (. employees) 1) employees) -------------------------------------------------------------------------------- /examples/body7.jhe: -------------------------------------------------------------------------------- 1 | (set james {"James", 31, "Developer"}) 2 | (set mary {"Mary", 29, "Architect"}) 3 | (set john {"John", 25, "Intern"}) 4 | (set dave {"Dave", 35, "Singer"}) 5 | 6 | (set employees {james, mary, john, dave}) 7 | (def fst X (_ 0 X)) 8 | (def snd X (_ 1 X)) 9 | (def addone EACH (+ 1 (fst X))) 10 | (@ (snd (fst (addone employees)))) -------------------------------------------------------------------------------- /examples/body8.jhe: -------------------------------------------------------------------------------- 1 | ((set james {"James", 31, "Developer"}) 2 | (set mary {"Mary", 29, "Architect"}) 3 | (@ (= james james)) 4 | (@ (= james mary)) 5 | (@ (! james james)) 6 | (@ (! james mary)) 7 | (@ (! 5 4)) 8 | (@ "Array") 9 | (@ (! [1,2,3] [3,2,3])) 10 | (@ "String") 11 | (@ (! "Hey" "Yo"))) -------------------------------------------------------------------------------- /examples/body9.jhe: -------------------------------------------------------------------------------- 1 | (def fst X (_ 0 X)) 2 | (def snd X (_ 1 X)) 3 | (def thd X (_ 2 X)) 4 | (def job_pay X (@ (snd (thd X)))) 5 | (def name X (@ (fst X))) 6 | (def age X (@ (snd X))) 7 | (set soft_eng {"software engineer", "pay level 3"}) 8 | (def employee CLSS { X, Y, soft_eng}) 9 | (set james (employee "james" 31)) 10 | (job_pay james) 11 | (name james) 12 | (age james) -------------------------------------------------------------------------------- /jlc.js: -------------------------------------------------------------------------------- 1 | // node modules 2 | var fs = require('fs'); 3 | var program = require('commander'); 4 | 5 | // core parser and interpreter 6 | var parser = require('./src/parser.js'); 7 | var interpreter = require('./src/interpreter.js'); 8 | 9 | // controllers for parsing and interpreting 10 | var controller = require('./src/helpers/interpreterControl.js')(); 11 | var textControl = require('./src/helpers/textControl.js')(); 12 | 13 | program.parse(process.argv); 14 | 15 | // get text of jedlang file and place on parsing controller 16 | var body = fs.readFileSync('./'+program.args[0]+'.jhe').toString(); 17 | textControl.body = body; 18 | 19 | var fileName = program.args[0].split('/'); 20 | fileName = fileName[fileName.length-1]; 21 | 22 | // parse into ast, mutating interpreting controller custom funcdefs 23 | var stack = parser(textControl, [], controller.defs); 24 | // write to C file and compile 25 | interpreter(stack, fileName, controller); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jedlang", 3 | "version": "0.1.2", 4 | "description": "A functional style language that compiles to C", 5 | "repository": "https://github.com/incrediblesound/JedLang", 6 | "main": "parser.js", 7 | "scripts": { 8 | "test": "" 9 | }, 10 | "author": "James H Edwards", 11 | "license": "MIT", 12 | "dependencies": { 13 | "commander": "^2.7.1", 14 | "lodash": "^3.6.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/basicTypes.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | makeIntObject: makeIntObject, 3 | makeStringObject: makeStringObject, 4 | makeArrayObject: makeArrayObject 5 | } 6 | 7 | function makeIntObject(num, controller){ 8 | var structName = controller.variables.newVariable(); 9 | var unionName = controller.variables.newVariable(); 10 | controller.in_scope += 'union Data '+unionName+';\n'+unionName+'.i = '+num+';\n'; 11 | controller.in_scope += 'struct Object '+structName+' = {\'i\',0,'+unionName+'};\n'; 12 | controller.in_scope_len.current = controller.in_scope.length; 13 | return structName; 14 | }; 15 | 16 | function makeStringObject(str, controller){ 17 | var structName = controller.variables.newVariable(); 18 | var unionName = controller.variables.newVariable(); 19 | var charName = controller.variables.newVariable(); 20 | controller.in_scope += 'char *'+charName+';\n'; 21 | controller.in_scope += ''+charName+' = (char *) malloc(sizeof(char) * '+(str.length-1)+');\n'; 22 | controller.in_scope += 'strcpy('+charName+', '+str+');\n'; 23 | controller.in_scope += 'union Data '+unionName+';\n'+unionName+'.s = '+charName+';\n'; 24 | controller.in_scope += 'struct Object '+structName+' = {\'s\','+(str.length-1)+','+unionName+'};\n'; 25 | controller.in_scope_len.current = controller.in_scope.length; 26 | return structName; 27 | }; 28 | 29 | function makeArrayObject(arr, controller){ 30 | var structName = controller.variables.newVariable(); 31 | var unionName = controller.variables.newVariable(); 32 | var arrName = controller.variables.newVariable(); 33 | controller.in_scope += 'int '+arrName+'['+arr.length+'] = {'+arr.toString()+'};\n'; 34 | controller.in_scope += 'union Data '+unionName+';\n'+unionName+'.ia = '+arrName+';\n'; 35 | controller.in_scope += 'struct Object '+structName+' = {\'a\','+arr.length+','+unionName+'};\n'; 36 | controller.in_scope_len.current = controller.in_scope.length; 37 | return structName; 38 | } -------------------------------------------------------------------------------- /src/buildFunctions.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var sys = require('./helpers/func.js'); 3 | var chars = require('./helpers/chars.js'); 4 | var basicTypes = require('./basicTypes.js'); 5 | var funcs = chars.funcs(); 6 | var letters = chars.letters(); 7 | var LETTERS = chars.LETTERS(); 8 | var VARIABLES = chars.VARIABLES(); 9 | var ERRORS = chars.ERRORS(); 10 | 11 | module.exports = buildFunctions = function(tree, result, argNames, context, controller){ 12 | var treeType = tree.get('type'); 13 | var treeValue = tree.get('value'); 14 | var treeName = tree.get('name'); 15 | 16 | if(treeType === 'value' && LETTERS.contains( treeValue )){ 17 | result += ''+argNames[controller.arg_map[ treeValue ]]; 18 | } 19 | else if(treeType === 'value'){ 20 | result += basicTypes.makeIntObject(treeValue, controller); 21 | } 22 | else if(treeType === 'string'){ 23 | result += basicTypes.makeStringObject(treeValue, controller); 24 | } 25 | else if(treeType === 'array'){ 26 | result += basicTypes.makeArrayObject(treeValue, controller); 27 | } 28 | else if(treeType === 'custom' && controller.defined[ treeValue ] !== undefined){ 29 | var definition = controller.defined[ treeValue ]; 30 | 31 | if(definition.type === 'function' || 32 | definition.type === 'class'){ 33 | 34 | if(definition.type === 'class' || tree.get('switch') === 'let'){ 35 | // if the function is a class, we need to save the result in a set object 36 | var objectName = controller.variables.newVariable(); 37 | result += 'struct Object '+objectName+' = '; 38 | controller.defined[treeName] = {name: objectName, type: 'set', clss: _.result(controller.defined[treeValue], 'label')}; 39 | } 40 | result += controller.defined[ treeValue ].name + '('; 41 | for(var i = 0; i < tree.size(); i++){ 42 | result = buildFunctions(tree.children[i], result, argNames, tree, controller); 43 | if(i !== tree.children.length-1){ 44 | result += ','; 45 | } 46 | } 47 | result += ')'; 48 | } else { 49 | var parentFunc = controller.defined[context.get('value')]; 50 | 51 | if(!!parentFunc && !!parentFunc.restriction){ 52 | if(parentFunc.restriction.contains(definition.clss)){ 53 | result += controller.defined[tree.get('value')].name; 54 | } else { 55 | ERRORS.add('\nERROR: Set of class '+definition.clss+' not compatible with function '+context.get('value')+'\n') 56 | } 57 | 58 | } else { 59 | result += controller.defined[treeValue].name; 60 | } 61 | } 62 | } 63 | else if(treeType === 'function' && tree.data.value !== '?'){ 64 | result += sys.map[treeValue]; 65 | for(var i = 0; i < tree.size(); i++){ 66 | result = buildFunctions(tree.children[i], result, argNames, tree, controller); 67 | if(i !== tree.size()-1){ 68 | result += ','; 69 | } 70 | } 71 | result += ')'; 72 | } 73 | else if(treeValue === '?'){ 74 | var argsText = (argNames !== undefined) ? helpers.argNameText(argNames, false) : ''; 75 | var argsTextInner = (argNames !== undefined) ? helpers.argNameText(argNames, true) : ''; 76 | var arg_one = tree.children[1], arg_two = tree.children[2]; 77 | var condition = tree.children[0]; 78 | var arg_one_name = controller.variables.newVariable(), arg_two_name = controller.variables.newVariable(); 79 | var wrapper_name = controller.variables.newVariable(); 80 | var isShow; 81 | var head = ''; 82 | 83 | var arg_one_func_body = buildFunctions(arg_one,'',argNames, null, controller); 84 | 85 | var arg_two_func_body = buildFunctions(arg_two,'',argNames, null, controller); 86 | 87 | controller.declarations += helpers.makeDeclaration(wrapper_name, argNames.length); 88 | 89 | var func_body = buildFunctions(condition,'',argNames, null, controller); 90 | 91 | head += 'struct Object '+wrapper_name+'('+argsText+'){\n'+IN_SCOPE+ 92 | 'struct Object truthval = '+func_body+';\nstruct Object result;\n'+ 93 | 'if(truthval.dat.i == 1){\nresult = '+arg_one_func_body+';\n'+ 94 | '} else {\nresult='+arg_two_func_body+';\n} return result;\n};\n'; 95 | 96 | controller.in_scope = ''; 97 | tail = ''+wrapper_name+'('+argsTextInner+')'; 98 | 99 | controller.pre_main += head; 100 | result += tail; 101 | } 102 | return result; 103 | }; -------------------------------------------------------------------------------- /src/functionDefinitions.js: -------------------------------------------------------------------------------- 1 | var helpers = require('./helpers/helpers.js'); 2 | var textControlFactory = require('./helpers/textControl.js'); 3 | var findClassName = require('./helpers/findClassName.js'); 4 | var parser = require('./parser_module.js'); 5 | var chars = require('./helpers/chars.js'); 6 | var buildFunctions = require('./buildFunctions.js'); 7 | var Set = require('./helpers/set.js').Set; 8 | var basicTypes = require('./basicTypes.js'); 9 | var Tree = require('./helpers/tree.js').Tree; 10 | 11 | var funcs = chars.funcs(); 12 | var LETTERS = chars.LETTERS(); 13 | var letters = chars.letters(); 14 | 15 | module.exports = createFuncDefs = function(stack, controller){ 16 | while(stack.length && (stack[0].get('type') === 'funcdef' || 17 | stack[0].get('type') === 'setdef')){ 18 | var tree = stack.shift(); 19 | if(tree.get('type') === 'setdef'){ 20 | if(!tree.children.length){ 21 | writeSetObject(tree, controller); 22 | } else { 23 | writeClassObject(tree, controller); 24 | } 25 | } 26 | else if(tree.get('action') === 'REDC'){ 27 | writeREDCFunc(tree, controller); 28 | } 29 | else if(tree.get('action') === 'ARRY'){ 30 | writeARRYFunc(tree, controller); 31 | } 32 | else if(tree.get('action') === 'FLTR'){ 33 | writeFLTRFunc(tree, controller); 34 | } 35 | else if(tree.get('action') === 'EACH'){ 36 | writeEACHFunc(tree, controller); 37 | } 38 | else if(tree.get('action') === 'CLSS'){ 39 | writeCLASSFunc(tree, controller); 40 | } 41 | else { 42 | var textControl = textControlFactory(); 43 | textControl.body = tree.data.iterator; 44 | var result = parser(textControl, [], controller.defs)[0]; 45 | writeCustomFuncs(result, tree, controller); 46 | } 47 | } 48 | return; 49 | }; 50 | 51 | function writeSetObject(tree, controller){ 52 | controller.setPreviousLength(); 53 | var members = tree.get('value'); 54 | var name = tree.get('name'); 55 | var memberNames = [], name; 56 | for(var i = 0, l = members.length; i < l; i++){ 57 | var member = members[i]; 58 | 59 | if(helpers.getType(member) === 'number'){ 60 | memberNames.push(basicTypes.makeIntObject(member, controller)); 61 | 62 | } else { 63 | 64 | member = helpers.trim(member); 65 | if(controller.defined[member] && controller.defined[member].type === 'set'){ 66 | memberNames.push(controller.defined[member].name); 67 | 68 | } else { 69 | memberNames.push(basicTypes.makeStringObject(member, controller)); 70 | } 71 | } 72 | } 73 | if(members.length !== 1){ 74 | var objectArrName = controller.variables.newVariable(); 75 | var unionName = controller.variables.newVariable(); 76 | 77 | controller.in_scope += 'struct Object *'+objectArrName+';\n'; 78 | controller.in_scope += ''+objectArrName+ 79 | ' = (struct Object *) malloc(sizeof(struct Object) * '+ 80 | members.length+');\n'; 81 | 82 | for(var i = 0; i < members.length; i++){ 83 | controller.in_scope += objectArrName+'['+i+'] = '+memberNames[i]+';\n'; 84 | } 85 | controller.in_scope += 'union Data '+unionName+';\n'+unionName+'.oa = '+objectArrName+';\n'; 86 | var objectName = controller.variables.newVariable(); 87 | controller.in_scope += 'struct Object '+objectName+' = {\'o\','+members.length+','+unionName+'};\n'; 88 | controller.declarations += 'struct Object '+objectName+';\n'; 89 | } else { 90 | var objectName = memberNames[0]; 91 | } 92 | controller.defined[name] = {name: objectName, type: 'set'}; 93 | controller.setCurrentLength(); 94 | controller.defined[name].definition = controller.getScopeChunk(); 95 | }; 96 | 97 | function writeClassObject(tree, controller){ 98 | var objectName = controller.variables.newVariable(); 99 | var definition = buildFunctions(tree.children[0],'')+';\n'; 100 | controller.in_scope += 'struct Object '+objectName + ' = '+definition; 101 | controller.defined[tree.get('name')] = {name: objectName, type: 'set'}; 102 | controller.setCurrentLength(); 103 | } 104 | 105 | function writeCLASSFunc(tree, controller){ 106 | var iterator = tree.get('iterator'); 107 | var funcName = controller.variables.newVariable(); 108 | controller.defined[tree.get('name')] = {name: funcName, type: 'class', label: tree.get('name')}; 109 | var arg, funcs = []; 110 | var funcBody = 'struct Object '+funcName+'('; 111 | for(var i = 0; i < iterator.length; i++){ 112 | arg = iterator[i]; 113 | if(LETTERS.contains(arg)){ 114 | funcBody += 'struct Object '+arg; 115 | if(i !== iterator.length-1 && LETTERS.contains(iterator[i+1])){ 116 | funcBody+=', '; 117 | } 118 | } else { 119 | var tree = new Tree(); 120 | tree.set('name', arg); 121 | tree.set('value', [arg]); 122 | writeSetObject(tree); 123 | } 124 | } 125 | funcBody += '){\n'; 126 | for(var k = 0; k < iterator.length; k++){ 127 | if(controller.defined[iterator[k]] !== undefined){ 128 | funcBody += controller.defined[iterator[k]].definition; 129 | iterator[k] = controller.defined[iterator[k]].name; 130 | } 131 | } 132 | funcBody += ';\n'; 133 | funcBody += 'struct Object *obj_arr;\n' 134 | funcBody += 'obj_arr = (struct Object *) malloc(sizeof(struct Object) * '+iterator.length+');\n'; 135 | for(var i = 0; i < iterator.length; i++){ 136 | funcBody += 'obj_arr['+i+'] = '+iterator[i]+';\n'; 137 | } 138 | funcBody += 'union Data arr_union; arr_union.oa = obj_arr;\n'; 139 | funcBody += 'struct Object jed_obj = {\'o\','+iterator.length+',arr_union};\n'; 140 | funcBody += 'return jed_obj;\n}\n'; 141 | 142 | controller.pre_main += funcBody; 143 | } 144 | 145 | function writeCustomFuncs(tree, definition, controller){ 146 | controller.setPreviousLength(); 147 | var args = definition.data.arguments; 148 | var name = definition.data.name; 149 | var funcBody = '', argNames = []; 150 | var funcName = controller.variables.newVariable(); 151 | controller.declarations += helpers.makeDeclaration(funcName, args.length); 152 | var head = 'struct Object '+funcName+'('; 153 | 154 | for(var i = 0; i < args.length; i++){ 155 | argNames.push(controller.variables.newVariable()); 156 | head += 'struct Object '+argNames[i]; 157 | if(i !== args.length-1){ 158 | head += ', '; 159 | } else { head += '){\n';} 160 | } 161 | 162 | var classRestriction = findClassName(tree, args, args.length, controller); 163 | 164 | controller.defined[name] = { 165 | name: funcName, 166 | arguments: argNames, 167 | type:'function', 168 | restriction: classRestriction.length ? new Set(classRestriction) : null 169 | }; 170 | 171 | var result = controller.variables.newVariable(); 172 | funcBody += 'struct Object '+result+' = '+buildFunctions(tree, '', argNames, null, controller)+';\n'; 173 | funcBody += 'return '+result+';\n};\n'; 174 | controller.pre_main += 175 | head + 176 | controller.getScopeChunk() + 177 | funcBody; 178 | controller.removeScopeChunk(); 179 | }; 180 | 181 | function writeREDCFunc(tree, controller){ 182 | controller.setPreviousLength(); 183 | // make iterator function 184 | var funcData = tree.get('iterator').replace(/\(|\)/g,'').split(' '); 185 | var funcName = funcData[0], funcElement = funcData[1]; 186 | var func = new Tree(); 187 | func.set('type','function'); func.set('value',funcName); 188 | var child = func.insert(); child.set('type','value'); child.set('value','X'); 189 | var placeholder = false; 190 | if(letters.contains(funcElement)){ 191 | child = func.insert(); child.set('type','value'); child.set('value','Y'); 192 | } else { 193 | placeholder = true; 194 | child = func.insert(); child.set('type','value'); child.set('value',funcElement); 195 | } 196 | var name = tree.get('name'); 197 | var funcBody = '', head = '', argNames = []; 198 | var funcName = controller.variables.newVariable(); 199 | head += 'struct Object '+funcName+'(struct Object array){\n'; 200 | funcBody += placeholder ? helpers.makeObjectInstance(funcElement) : 'struct Object jed_obj = getInt(array);\n'; 201 | funcBody += 'int i=1;\nfor(i; i','<','^','_','@','?','|','.','=','!','$']); 15 | }, 16 | special_funcs: function(){ 17 | return new Set(['ARRY','REDC','FLTR','EACH','CLSS']); 18 | }, 19 | patterns: function(){ 20 | return new Set(['(',')','[',']','"']); 21 | }, 22 | custom: function(){ 23 | return new Set([]); 24 | }, 25 | anyChar: function(){ 26 | return new Set(characterFunctions.numbers().append(characterFunctions.patterns()).append(characterFunctions.funcs()).append(characterFunctions.letters()).append(characterFunctions.LETTERS()).data); 27 | }, 28 | VARIABLES: function(){ 29 | return new Set(['X','Y','Z']); 30 | }, 31 | ERRORS: function(){ 32 | return new Set(); 33 | } 34 | } 35 | 36 | module.exports = characterFunctions; -------------------------------------------------------------------------------- /src/helpers/findClassName.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var chars = require('./chars.js'); 3 | 4 | var VARIABLES = chars.VARIABLES(); 5 | 6 | module.exports = findClassName = function(tree, args, idx, controller){ 7 | idx = idx || 0; 8 | args = args || []; 9 | var result = [], temp; 10 | if(controller.defined[tree.get('value')] !== undefined && controller.defined[tree.get('value')].type === 'class'){ 11 | result.push(tree.get('value')); 12 | tree.set('value', VARIABLES.get(idx)); 13 | tree.set('type', 'value'); 14 | args.push(VARIABLES.get(idx)); 15 | idx++ 16 | } else { 17 | for(var i = 0; i < tree.children.length; i++){ 18 | temp = findClassName(tree.children[i], args, idx, controller); 19 | if(temp.length > 0){ 20 | result.push(temp); 21 | } 22 | } 23 | } 24 | return _.flatten(result); 25 | } -------------------------------------------------------------------------------- /src/helpers/func.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | map: { 3 | '+': 'add(', 4 | '-': 'sub(', 5 | '*': 'mult(', 6 | '/': 'divide(', 7 | '@': 'show(', 8 | '^': 'prepend(', 9 | '_': 'member(', 10 | '>': 'greater(', 11 | '<': 'less(', 12 | '?': 'condition(', 13 | '|': 'identity(', 14 | '.': 'length(', 15 | '=': 'equal(', 16 | '!': 'not_equal(', 17 | } 18 | }; -------------------------------------------------------------------------------- /src/helpers/helpers.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | argNameText: argNameText, 3 | makeDeclaration: makeDeclaration, 4 | makeObjectInstance: makeObjectInstance, 5 | getType: getType, 6 | stringToArray: stringToArray, 7 | printList: printList, 8 | trim: trim 9 | } 10 | 11 | function argNameText(array, inner){ 12 | var result = ''; 13 | for(var i =0; i < array.length; i++){ 14 | result += (!inner ? 'struct Object ': '')+array[i]; 15 | if(i < array.length-1){ 16 | result += ','; 17 | } 18 | } 19 | return result; 20 | }; 21 | 22 | function makeDeclaration(name, num){ 23 | var result = 'struct Object '; 24 | result += name+'('; 25 | while(num > 0){ 26 | num--; 27 | result += 'struct Object'; 28 | if(num > 0){ 29 | result += ', '; 30 | } 31 | } 32 | result += ');\n'; 33 | return result; 34 | }; 35 | 36 | function makeObjectInstance(value){ 37 | if(parseInt(value) === parseInt(value)){ 38 | return 'struct Object jed_obj = createInt('+value+');\n'; 39 | } 40 | else if(typeof value === 'string'){ 41 | var result = 'char str['+(value.length+1)+'];\n'+ 42 | 'strcpy(str, '+value+');\nstruct Object jed_obj = createString('+value+');\n'; 43 | return result; 44 | } 45 | }; 46 | 47 | function getType(val){ 48 | if(parseInt(val) === parseInt(val)){ 49 | return 'number'; 50 | } 51 | else { 52 | return typeof val; 53 | } 54 | } 55 | 56 | function trim(str){ 57 | if(str[0] === ' '){ 58 | str = str.substring(1, str.length); 59 | } 60 | if(str[str.length-1] === ' '){ 61 | str = str.substring(0, str.length-1); 62 | } 63 | if(str[0] === ' ' || str[str.length-1] === ' '){ 64 | return trim(str); 65 | } 66 | return str; 67 | } 68 | 69 | function stringToArray(str){ 70 | str = str.replace(/\"/g,''); 71 | var result = ''; 72 | for(var i = 0; i < str.length; i++){ 73 | result += '\''+str[i]+'\''; 74 | result += ', '; 75 | } 76 | result += '0'; 77 | return result; 78 | } 79 | 80 | function printList(arr){ 81 | var result = ''; 82 | for(var i = 0; i < arr.length; i++){ 83 | result += arr[i]; 84 | if(i < arr.length-1){ 85 | result += ', '; 86 | } 87 | } 88 | return result; 89 | } -------------------------------------------------------------------------------- /src/helpers/interpreterControl.js: -------------------------------------------------------------------------------- 1 | var chars = require('./chars'); 2 | var variables = require('./variables.js')(); 3 | module.exports = function(){ 4 | return { 5 | defined: {}, 6 | arg_map: { 7 | 'X': 0, 8 | 'Y': 1, 9 | 'Z': 2 10 | }, 11 | declarations: '', 12 | pre_main: '', 13 | in_scope: '', 14 | in_scope_len: {prev: 0, current: 0}, 15 | defs: chars.custom(), 16 | variables: variables, 17 | getScopeChunk: function(){ 18 | return this.in_scope.substring(this.in_scope_len.prev, this.in_scope_len.current); 19 | }, 20 | removeScopeChunk: function(){ 21 | this.in_scope = this.in_scope.substring(0, this.in_scope_len.prev); 22 | this.in_scope_len.prev = this.in_scope.length; 23 | this.in_scope_len.current = this.in_scope.length; 24 | }, 25 | setPreviousLength: function(){ 26 | this.in_scope_len.prev = this.in_scope.length; 27 | }, 28 | setCurrentLength: function(){ 29 | this.in_scope_len.current = this.in_scope.length; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/helpers/set.js: -------------------------------------------------------------------------------- 1 | var Set = function(array){ 2 | this.data = array || []; 3 | }; 4 | Set.prototype.contains = function(item){ 5 | return (this.data && this.data.length) ? (this.data.indexOf(item) > -1) : false; 6 | }; 7 | Set.prototype.get = function(idx){ 8 | return this.data[idx]; 9 | }; 10 | Set.prototype.setData = function(array){ 11 | this.data = array; 12 | }; 13 | Set.prototype.append = function(set){ 14 | return new Set(this.data.concat(set.data)); 15 | }; 16 | Set.prototype.add = function(item){ 17 | this.data.push(item); 18 | }; 19 | Set.prototype.rnd = function(){ 20 | var index = Math.floor(Math.random()*this.data.length); 21 | return this.get(index); 22 | } 23 | Set.prototype.isEmpty = function(){ 24 | return this.data.length === 0; 25 | } 26 | 27 | Set.prototype.print = function(){ 28 | for(var i = 0; i < this.data.length; i++){ 29 | console.log(this.data[i]) 30 | } 31 | } 32 | 33 | module.exports = { 34 | Set: Set, 35 | } -------------------------------------------------------------------------------- /src/helpers/textControl.js: -------------------------------------------------------------------------------- 1 | var chars = require('./chars.js'); 2 | 3 | var letters = chars.letters(); 4 | var LETTERS = chars.LETTERS(); 5 | var anyChar = chars.anyChar(); 6 | 7 | module.exports = function(){ 8 | return { 9 | scope: null, 10 | i: 0, 11 | body: null, 12 | advance: function(num){ 13 | this.i += num; 14 | return this.idx(); 15 | }, 16 | chunk: function(ahead){ 17 | return this.body.slice(this.i, this.i+ahead); 18 | }, 19 | decr: function(){ 20 | this.i -= 1; 21 | }, 22 | get_list: function(){ 23 | this.incr(); 24 | var content = ''; 25 | while(this.idx() !== ']'){ 26 | content += this.idx(); 27 | this.incr(); 28 | } 29 | return content.split(','); 30 | }, 31 | get_text: function(){ 32 | this.incr(); 33 | var result = ""; 34 | while(this.idx() !== '"'){ 35 | result += this.idx(); 36 | this.incr(); 37 | } 38 | return '\"'+result+'\"'; 39 | }, 40 | incr: function(){ 41 | this.i += 1; 42 | }, 43 | idx: function(){ 44 | return this.body[this.i]; 45 | }, 46 | next: function(){ 47 | while(this.idx() === ' ' || /\r\n|\n|\r/.test(this.idx())){ 48 | this.incr(); 49 | } 50 | return this.idx(); 51 | }, 52 | next_word: function(){ 53 | var name = ''; 54 | var k = this.i; 55 | while(letters.contains(this.body[k]) || this.body[k] === '_'){ 56 | name += this.body[k]; 57 | ++k; 58 | } 59 | return name; 60 | }, 61 | next_paren: function(){ 62 | while(this.idx() !== '('){ 63 | this.incr(); 64 | } 65 | }, 66 | take: function(num){ 67 | var temp = this.i; 68 | this.i += num; 69 | return this.body.slice(temp, this.i); 70 | }, 71 | take_args: function(){ 72 | var args = []; 73 | this.next(); 74 | while(LETTERS.contains(this.idx()) || this.idx() === ' '){ 75 | if(LETTERS.contains(this.idx())){ 76 | args.push(this.idx()); 77 | } 78 | this.incr(); 79 | } 80 | return args; 81 | }, 82 | take_brackets: function(){ 83 | this.next(); 84 | this.incr(); 85 | var string = ''; 86 | while(this.idx() !== '}'){ 87 | string += this.idx(); 88 | this.incr(); 89 | } 90 | this.incr(); 91 | return string.split(','); 92 | }, 93 | take_classdef: function(){ 94 | var name = ''; 95 | this.incr(); 96 | while(this.idx() !== '}'){ 97 | name += this.idx(); 98 | this.incr(); 99 | } 100 | this.incr(); 101 | name = name.replace(/\s/g,''); 102 | return name.split(','); 103 | }, 104 | take_func: function(){ 105 | this.next(); 106 | if(this.idx() === '{'){ 107 | return this.take_classdef(); 108 | } 109 | var open = 1; 110 | var name = "("; 111 | this.incr(); 112 | while(open > 0){ 113 | if(this.idx() === '('){ 114 | open += 1; 115 | } 116 | else if(this.idx() === ')'){ 117 | open -= 1; 118 | } 119 | name += this.idx(); 120 | this.incr(); 121 | } 122 | return name; 123 | }, 124 | take_name: function(){ 125 | var name = ''; 126 | this.next(); 127 | while(letters.contains(this.idx()) || this.idx() === '_'){ 128 | name += this.idx(); 129 | this.incr(); 130 | } 131 | return name; 132 | }, 133 | take_next: function(){ 134 | var name = ''; 135 | this.next(); 136 | while(anyChar.contains(this.idx()) && this.idx() !== ')'){ 137 | name += this.idx(); 138 | this.incr(); 139 | } 140 | return name; 141 | }, 142 | }; 143 | } -------------------------------------------------------------------------------- /src/helpers/tree.js: -------------------------------------------------------------------------------- 1 | var Tree = function(parent){ 2 | this.data = {}; 3 | this.children = []; 4 | this.parent = parent || null; 5 | } 6 | 7 | Tree.prototype.insert = function(child){ 8 | child = child || new Tree(this); 9 | this.children.push( child ); 10 | return child; 11 | } 12 | 13 | Tree.prototype.set = function(prop, value){ 14 | this.data[prop] = value; 15 | } 16 | 17 | Tree.prototype.get = function(prop){ 18 | return this.data[prop]; 19 | } 20 | 21 | Tree.prototype.size = function(){ 22 | return this.children.length; 23 | } 24 | 25 | module.exports = { 26 | Tree: Tree 27 | } -------------------------------------------------------------------------------- /src/helpers/variables.js: -------------------------------------------------------------------------------- 1 | var chars = require('./chars.js'); 2 | var letters = chars.letters(); 3 | 4 | module.exports = function(){ 5 | return { 6 | vars: {}, 7 | newVariable: function(){ 8 | var result = ''; 9 | for(var i = 0; i < 8; i++){ 10 | result += letters.rnd(); 11 | } 12 | if(this.vars[result] !== undefined){ 13 | return this.newVariable(); 14 | } else { 15 | return result; 16 | } 17 | } 18 | }; 19 | } -------------------------------------------------------------------------------- /src/interpreter.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var exec = require('child_process').exec; 3 | var _ = require('lodash'); 4 | var sys = require('./helpers/func.js'); 5 | var Set = require('./helpers/set.js').Set; 6 | var Tree = require('./helpers/tree.js').Tree; 7 | var createFuncDefs = require('./functionDefinitions.js'); 8 | var helpers = require('./helpers/helpers.js'); 9 | var chars = require('./helpers/chars'); 10 | var buildFunctions = require('./buildFunctions.js'); 11 | 12 | var funcs = chars.funcs(); 13 | var letters = chars.letters(); 14 | var LETTERS = chars.LETTERS(); 15 | var VARIABLES = chars.VARIABLES(); 16 | var ERRORS = chars.ERRORS(); 17 | 18 | 19 | module.exports = function(stack, name, controller){ 20 | var command; 21 | var result = ''; 22 | createFuncDefs(stack, controller); 23 | while(stack.length){ 24 | command = stack.shift(); 25 | result = buildFunctions(command, result, null, null, controller); 26 | result += ';\n'; 27 | }; 28 | if(ERRORS.isEmpty()){ 29 | result = '#include \"jedlang.h\"\n\n'+ 30 | controller.declarations+'\n'+ 31 | controller.pre_main+'\nint main(){\n'+ 32 | controller.in_scope+'\n'+result + '\n};\n'; 33 | 34 | fs.writeFileSync('./src/output.c', result); 35 | exec('gcc ./src/output.c -o '+name+'.out', function(err){ 36 | if(err) console.log(err); 37 | // exec('rm -rf output.c'); 38 | return; 39 | }); 40 | } else { 41 | ERRORS.print(); 42 | } 43 | }; 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/jedlang.h: -------------------------------------------------------------------------------- 1 | # include 2 | # include 3 | # include 4 | 5 | union Data { 6 | int i; 7 | float f; 8 | char *s; 9 | int *ia; 10 | struct Object *oa; 11 | }; 12 | 13 | struct Object { 14 | char type; 15 | int length; 16 | union Data dat; 17 | }; 18 | 19 | struct Object show(struct Object obj){ 20 | if(obj.type == 's'){ 21 | printf("%s\n", obj.dat.s); 22 | } 23 | else if(obj.type == 'i'){ 24 | printf("%d\n", obj.dat.i); 25 | } 26 | else if(obj.type == 'f'){ 27 | printf("%f\n", obj.dat.f); 28 | } 29 | else if(obj.type == 'b'){ 30 | char result[10]; 31 | strcpy(result, obj.dat.i == 0 ? "False" : "True"); 32 | printf("%s\n", result); 33 | } 34 | else if(obj.type == 'a'){ 35 | printf("["); 36 | int i = 0; 37 | for(i; i < obj.length; ++i){ 38 | if(i < (obj.length-1)){ 39 | printf("%d, ", obj.dat.ia[i]); 40 | } else { 41 | printf("%d", obj.dat.ia[i]); 42 | } 43 | } 44 | printf("]\n"); 45 | } 46 | else if(obj.type == 'd'){ 47 | printf("%s\n","{"); 48 | int i = 0; 49 | for(i; i < obj.length; ++i){ 50 | if(i < (obj.length-1)){ 51 | show(obj.dat.oa[i]); 52 | } else { 53 | show(obj.dat.oa[i]); 54 | } 55 | } 56 | printf("%s\n","}"); 57 | } 58 | return obj; 59 | }; 60 | 61 | 62 | struct Object createInt(int num){ 63 | union Data d; 64 | d.i = num; 65 | struct Object obj = {'i',0,d}; 66 | return obj; 67 | }; 68 | struct Object createFloat(float num){ 69 | union Data d; 70 | d.f = num; 71 | struct Object obj = {'f',0,d}; 72 | return obj; 73 | }; 74 | struct Object createString(char *str){ 75 | union Data d; 76 | d.s = str; 77 | struct Object obj = {'s',0,d}; 78 | return obj; 79 | }; 80 | 81 | struct Object createArray(int *ia){ 82 | union Data d; 83 | d.ia = ia; 84 | struct Object obj = {'a',1,d}; 85 | return obj; 86 | }; 87 | 88 | struct Object getInt(struct Object obj){ 89 | union Data d; 90 | if(obj.type == 'i'){ 91 | return createInt(obj.dat.i); 92 | } 93 | else { 94 | return createInt(obj.dat.ia[0]); 95 | } 96 | }; 97 | 98 | struct Object getFloat(struct Object obj){ 99 | union Data d; 100 | if(obj.type == 'f'){ 101 | return createFloat(obj.dat.f); 102 | } 103 | else { 104 | return createFloat(obj.dat.ia[0]); 105 | } 106 | }; 107 | 108 | struct Object member(struct Object num, struct Object b){ 109 | int ni = num.dat.i; 110 | return b.dat.oa[ni]; 111 | }; 112 | 113 | struct Object length(struct Object a){ 114 | union Data dat; 115 | dat.i = a.length; 116 | struct Object obj = {'i',0,dat}; 117 | return obj; 118 | }; 119 | 120 | struct Object add(struct Object a, struct Object b){ 121 | if(a.type == 'i'){ 122 | a.dat.i = a.dat.i + b.dat.i; 123 | } else { 124 | a.dat.f = a.dat.f + b.dat.f; 125 | } 126 | return a; 127 | }; 128 | 129 | struct Object sub(struct Object a, struct Object b){ 130 | if(a.type == 'i'){ 131 | a.dat.i = a.dat.i - b.dat.i; 132 | } else { 133 | a.dat.f = a.dat.f - b.dat.f; 134 | } 135 | return a; 136 | }; 137 | 138 | struct Object mult(struct Object a, struct Object b){ 139 | if(a.type == 'i'){ 140 | a.dat.i = a.dat.i * b.dat.i; 141 | } else { 142 | a.dat.f = a.dat.f * b.dat.f; 143 | } 144 | return a; 145 | }; 146 | 147 | struct Object divide(struct Object a, struct Object b){ 148 | if(a.type == 'i'){ 149 | a.dat.i = a.dat.i / b.dat.i; 150 | } else { 151 | a.dat.f = a.dat.f / b.dat.f; 152 | } 153 | return a; 154 | }; 155 | 156 | struct Object greater(struct Object a, struct Object b){ 157 | union Data dt; 158 | struct Object obj = {'b',0, dt}; 159 | 160 | if(a.type == 'i'){ 161 | obj.dat.i = a.dat.i > b.dat.i ? 1 : 0; 162 | } else { 163 | obj.dat.f = a.dat.f > b.dat.f ? 1 : 0; 164 | } 165 | return obj; 166 | }; 167 | 168 | struct Object equal(struct Object a, struct Object b){ 169 | union Data dt; 170 | struct Object obj = {'b',0, dt}; 171 | int isTrue; 172 | if(a.type == 'i'){ 173 | obj.dat.i = a.dat.i == b.dat.i ? 1 : 0; 174 | } 175 | else if(a.type == 'f'){ 176 | obj.dat.i = a.dat.f == b.dat.f ? 1 : 0; 177 | } 178 | else if(a.type == 's'){ 179 | obj.dat.i = (strcmp(a.dat.s, b.dat.s) == 0) ? 1 : 0; 180 | } 181 | else if (a.type == 'o'){ 182 | isTrue = 1; 183 | int i = 0; 184 | for(i; i < a.length; i++){ 185 | struct Object temp = equal(a.dat.oa[i], b.dat.oa[i]); 186 | isTrue = (temp.dat.i == 1 && isTrue == 1) ? 1 : 0; 187 | } 188 | obj.dat.i = isTrue; 189 | } 190 | else if (a.type == 'a'){ 191 | isTrue = 1; 192 | int i = 0; 193 | for(i; i < a.length; i++){ 194 | isTrue = (a.dat.ia[i] == b.dat.ia[i] && isTrue == 1) ? 1 : 0; 195 | } 196 | obj.dat.i = isTrue; 197 | } 198 | return obj; 199 | }; 200 | 201 | struct Object not_equal(struct Object a, struct Object b){ 202 | union Data dt; 203 | struct Object obj = {'b',0, dt}; 204 | int isTrue; 205 | if(a.type == 'i'){ 206 | obj.dat.i = a.dat.i != b.dat.i ? 1 : 0; 207 | } 208 | else if(a.type == 'f'){ 209 | obj.dat.i = a.dat.f != b.dat.f ? 1 : 0; 210 | } 211 | else if(a.type == 's'){ 212 | obj.dat.i = (strcmp(a.dat.s, b.dat.s) != 0) ? 1 : 0; 213 | } 214 | else if (a.type == 'o'){ 215 | isTrue = 1; 216 | int i = 0; 217 | for(i; i < a.length; i++){ 218 | struct Object temp = not_equal(a.dat.oa[i], b.dat.oa[i]); 219 | isTrue = (temp.dat.i == 1 && isTrue == 1) ? 1 : 0; 220 | } 221 | obj.dat.i = isTrue; 222 | } 223 | else if (a.type == 'a'){ 224 | isTrue = 0; 225 | int i = 0; 226 | for(i; i < a.length; i++){ 227 | isTrue = (a.dat.ia[i] == b.dat.ia[i] && isTrue == 0) ? 0 : 1; 228 | } 229 | obj.dat.i = isTrue; 230 | } 231 | return obj; 232 | }; 233 | 234 | struct Object less(struct Object a, struct Object b){ 235 | union Data dt; 236 | struct Object obj = {'b',0, dt}; 237 | 238 | if(a.type == 'i'){ 239 | obj.dat.i = a.dat.i < b.dat.i ? 1 : 0; 240 | } else { 241 | obj.dat.f = a.dat.f < b.dat.f ? 1 : 0; 242 | } 243 | return obj; 244 | }; 245 | 246 | struct Object identity(struct Object a){ 247 | return a; 248 | }; 249 | 250 | struct Object set_append(struct Object a, struct Object b){ 251 | struct Object arr[b.length+1]; 252 | int i = 0; 253 | for(i; i < b.length+1; i++){ 254 | if(i < b.length){ 255 | arr[i] = b.dat.oa[i]; 256 | } else { 257 | arr[i] = a; 258 | } 259 | } 260 | b.dat.oa = arr; 261 | b.length = b.length + 1; 262 | return b; 263 | }; 264 | 265 | struct Object append(struct Object a, struct Object b){ 266 | if(a.type == 'o'){ 267 | return set_append(a, b); 268 | } else { 269 | int arr[b.length+1]; 270 | int i = 0; 271 | for(i; i < b.length+1; i++){ 272 | if(i < b.length){ 273 | arr[i] = b.dat.ia[i]; 274 | } else { 275 | arr[i] = a.dat.i; 276 | } 277 | } 278 | b.dat.ia = arr; 279 | b.length = b.length + 1; 280 | return b; 281 | } 282 | }; 283 | 284 | 285 | struct Object prepend(struct Object a, struct Object b){ 286 | b.length = b.length+1; 287 | int frst = a.dat.i; 288 | int temp, insert; 289 | int i = 0; 290 | for(i; i < b.length; i++){ 291 | if(i == 0){ 292 | temp = b.dat.ia[0]; 293 | b.dat.ia[0] = frst; 294 | } else { 295 | insert = temp; 296 | temp = b.dat.ia[i]; 297 | b.dat.ia[i] = insert; 298 | } 299 | } 300 | b.type = 'a'; 301 | return b; 302 | }; 303 | -------------------------------------------------------------------------------- /src/parser.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var Tree = require('./helpers/tree.js').Tree; 3 | var builder = require('./interpreter.js'); 4 | var chars = require('./helpers/chars.js'); 5 | 6 | var anyChar = chars.anyChar(); 7 | var numbers = chars.numbers(); 8 | var funcs = chars.funcs(); 9 | var special_funcs = chars.special_funcs(); 10 | 11 | var custom_types = {}; 12 | 13 | module.exports = parser = function(textControl, stack, custom){ 14 | var l = textControl.body.length, 15 | current, 16 | valNode; 17 | 18 | while(textControl.i < l) { 19 | var name; 20 | 21 | current = textControl.next(); 22 | if(anyChar.contains(current)){ 23 | if(current === '(' && textControl.chunk(4) !== '(def' && textControl.chunk(4) !== '(set'){ 24 | if(textControl.scope === null){ 25 | textControl.scope = new Tree(); 26 | } else { 27 | textControl.scope = textControl.scope.insert(); 28 | } 29 | } 30 | else if(funcs.contains(current)){ 31 | textControl.scope.set('type','function'); 32 | textControl.scope.set('value', current); 33 | } 34 | else if(custom.contains(textControl.next_word())){ 35 | name = textControl.next_word(); 36 | textControl.advance(name.length-1); 37 | if(textControl.scope.get('type') !== undefined && custom_types[name] !== 'funcdef'){ 38 | valNode = textControl.scope.insert(); 39 | valNode.set('type','custom'); 40 | valNode.set('value', name); 41 | } else { 42 | textControl.scope.set('type','custom'); 43 | textControl.scope.set('value', name); 44 | } 45 | } 46 | else if(numbers.contains(current)){ 47 | var num = ''; 48 | while(numbers.contains(textControl.idx())){ 49 | num = num + textControl.idx(); 50 | textControl.incr(); 51 | } 52 | textControl.decr(); 53 | valNode = textControl.scope.insert(); 54 | valNode.set('type','value'); 55 | valNode.set('value', num); 56 | } 57 | else if(current === '"'){ 58 | var text = textControl.get_text(); 59 | valNode = textControl.scope.insert(); 60 | valNode.set('type','string'); 61 | valNode.set('value', text); 62 | } 63 | else if(current === '['){ 64 | var list = textControl.get_list(); 65 | valNode = textControl.scope.insert(); 66 | valNode.set('type','array'); 67 | valNode.set('value', list); 68 | } 69 | else if(current === ')'){ 70 | if(!!textControl.scope){ 71 | if(textControl.scope.get('type') === 'custom' && textControl.chunk(2) === '))' && 72 | textControl.scope.get('name') !== undefined){ 73 | textControl.incr(); 74 | } 75 | if(textControl.scope.parent === null){ 76 | stack.push(textControl.scope); 77 | } 78 | textControl.scope = textControl.scope.parent; 79 | } 80 | } 81 | else if(textControl.chunk(3) === 'def'){ 82 | current = textControl.advance(4); 83 | name = textControl.take_name(); 84 | custom.add(name); 85 | custom_types[name] = 'funcdef'; 86 | current = textControl.idx(); 87 | var defn = new Tree(); 88 | defn.set('type','funcdef'); 89 | defn.set('name', name); 90 | textControl.incr(); 91 | var special = textControl.chunk(4); 92 | if(textControl.idx() !== ')' && special_funcs.contains(special)){ 93 | textControl.advance(4); 94 | defn.set('action',special); 95 | defn.set('iterator', textControl.take_func()); 96 | textControl.next(); 97 | if(textControl.idx() !== ')' && textControl.chunk(4) === 'NULL'){ 98 | textControl.advance(4); 99 | defn.set('null', textControl.take_next()); 100 | textControl.next(); 101 | } 102 | } else { 103 | defn.set('arguments', textControl.take_args()); 104 | defn.set('iterator', textControl.take_func()); 105 | textControl.next(); 106 | } 107 | if(textControl.idx() === ')'){ 108 | stack.push(defn); 109 | } 110 | } 111 | else if(textControl.chunk(3) === 'set' || textControl.chunk(3) === 'let'){ 112 | var isLet = textControl.chunk(3) === 'let'; 113 | current = textControl.advance(4); 114 | name = textControl.take_name(); 115 | custom.add(name); 116 | custom_types[name] = 'setdef'; 117 | current = textControl.idx(); 118 | var defset = new Tree(); 119 | defset.set('type','setdef'); 120 | defset.set('name', name); 121 | if(textControl.chunk(3).indexOf('(') !== -1){ 122 | if(textControl.scope === null){ 123 | textControl.scope = defset; 124 | } else { 125 | textControl.scope.set('type','setdef'); 126 | textControl.scope.set('name', name); 127 | } 128 | if(isLet){ 129 | textControl.scope.set('switch', 'let') 130 | } 131 | textControl.next_paren(); 132 | 133 | } else { 134 | var content = textControl.take_brackets(); 135 | defset.set('value', content); 136 | stack.push(defset); 137 | } 138 | } 139 | } 140 | textControl.incr(); 141 | } 142 | return stack; 143 | } 144 | -------------------------------------------------------------------------------- /src/parser_module.js: -------------------------------------------------------------------------------- 1 | var Tree = require('./helpers/tree.js').Tree; 2 | var Set = require('./helpers/set.js').Set; 3 | var chars = require('./helpers/chars.js'); 4 | 5 | var anyChar = chars.anyChar(); 6 | var custom = chars.custom(); 7 | var numbers = chars.numbers(); 8 | var funcs = chars.funcs(); 9 | var letters = chars.letters(); 10 | var LETTERS = chars.LETTERS(); 11 | 12 | module.exports = function(textControl, stack, defs){ 13 | //import custom function names from initial parsing step 14 | if(defs !== undefined){ 15 | custom.setData(defs.data); 16 | } 17 | while(textControl.i < textControl.body.length) { 18 | var name, current; 19 | 20 | current = textControl.next(); 21 | if(anyChar.contains(current)){ 22 | if(current === '(' && textControl.chunk(4) !== '(def' && textControl.chunk(4) !== '(set'){ 23 | if(textControl.scope === null){ 24 | textControl.scope = new Tree(); 25 | } else { 26 | textControl.scope = textControl.scope.insert(); 27 | } 28 | } 29 | else if(funcs.contains(current)){ 30 | textControl.scope.set('type','function'); 31 | textControl.scope.set('value', current); 32 | } 33 | else if(custom.contains(textControl.next_word())){ 34 | name = textControl.next_word(); 35 | textControl.advance(name.length-1); 36 | if(textControl.scope.get('type') !== undefined){ 37 | valNode = textControl.scope.insert(); 38 | valNode.set('type','custom'); 39 | valNode.set('value',name); 40 | } else { 41 | textControl.scope.set('type','custom'); 42 | textControl.scope.set('value', name); 43 | } 44 | } 45 | else if(LETTERS.contains(current)){ 46 | var val = textControl.idx(); 47 | valNode = textControl.scope.insert(); 48 | valNode.set('type','value'); 49 | valNode.set('value', val); 50 | } 51 | else if(letters.contains(current)){ 52 | var val = textControl.idx(); 53 | valNode = textControl.scope.insert(); 54 | valNode.set('type','value'); 55 | valNode.set('value', val); 56 | } 57 | else if(numbers.contains(current)){ 58 | var num = ''; 59 | while(numbers.contains(textControl.idx())){ 60 | num = num + textControl.idx(); 61 | textControl.incr(); 62 | } 63 | textControl.decr(); 64 | valNode = textControl.scope.insert(); 65 | valNode.set('type','value'); 66 | valNode.set('value', num); 67 | } 68 | else if(current === '"'){ 69 | var text = textControl.get_text(); 70 | valNode = textControl.scope.insert(); 71 | valNode.set('type','string'); 72 | valNode.set('value', text); 73 | } 74 | else if(current === '['){ 75 | var list = textControl.get_list(); 76 | valNode = textControl.scope.insert(); 77 | valNode.set('type','array'); 78 | valNode.set('value', list); 79 | } 80 | else if(current === ')'){ 81 | if(textControl.scope.parent === null){ 82 | stack.push(textControl.scope); 83 | } 84 | textControl.scope = textControl.scope.parent; 85 | } 86 | else if(textControl.chunk(3) === 'def'){ 87 | current = textControl.advance(4); 88 | name = textControl.take_name(); 89 | custom.add(name); 90 | current = textControl.idx(); 91 | var defn = new Tree(); 92 | defn.set('type','funcdef'); 93 | defn.set('name', name); 94 | textControl.incr(); 95 | var special = textControl.chunk(4); 96 | if(textControl.idx() !== ')' && special_funcs.contains(special)){ 97 | textControl.advance(4); 98 | defn.set('action',special); 99 | defn.set('iterator', textControl.take_func()); 100 | textControl.next(); 101 | if(textControl.idx() !== ')' && textControl.chunk(4) === 'NULL'){ 102 | textControl.advance(4); 103 | defn.set('null', textControl.take_next()); 104 | textControl.next(); 105 | } 106 | } else { 107 | defn.set('action', textControl.take_next()); 108 | defn.set('iterator', textControl.take_func()); 109 | textControl.next(); 110 | } 111 | if(textControl.idx() === ')'){ 112 | stack.push(defn); 113 | } 114 | } 115 | else if(textControl.chunk(3) === 'set'){ 116 | current = textControl.advance(4); 117 | name = textControl.take_name(); 118 | custom.add(name); 119 | current = textControl.idx(); 120 | var defset = new Tree(); 121 | defset.set('type','setdef'); 122 | defset.set('name', name); 123 | var content = textControl.take_brackets(); 124 | defset.set('value', content); 125 | stack.push(defset); 126 | } 127 | } 128 | textControl.incr(); 129 | } 130 | return stack; 131 | }; --------------------------------------------------------------------------------