├── .gitignore ├── .travis.yml ├── Makefile ├── README.md ├── example ├── class.ore ├── counter.ore ├── err.ore ├── fib.ore ├── fizzbuzz.ore ├── foo.ore ├── regexp.ore ├── variadic.ore └── while.ore ├── khash.h ├── klist.h ├── kstring.c ├── kstring.h ├── misc └── vim │ ├── ftdetect │ └── ore.vim │ ├── ftplugin │ └── ore │ │ └── comment.vim │ └── syntax │ └── ore.vim ├── mpc.c ├── mpc.h ├── ore.c ├── ore.h ├── slre.c ├── slre.h └── t ├── 01-let.ore ├── 02-op.ore ├── 03-func.ore ├── 04-len.ore ├── 05-for.ore ├── 06-regexp.ore ├── 08-if.ore ├── lib └── tester.ore ├── test.bat └── test.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | *.o 3 | *.exe 4 | tags 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | script: "make all test" 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SRCS = \ 2 | mpc.c \ 3 | kstring.c \ 4 | slre.c \ 5 | ore.c 6 | 7 | OBJS = $(subst .c,.o,$(SRCS)) 8 | 9 | CFLAGS = -g -Wall -Werror 10 | LIBS = -lm 11 | TARGET = ore 12 | ifeq ($(OS),Windows_NT) 13 | TARGET := ${TARGET}.exe 14 | endif 15 | ifeq (yes, $(ORE_DEBUG)) 16 | CFLAGS := ${CFLAGS} -DDEBUG 17 | endif 18 | 19 | all : $(TARGET) 20 | 21 | $(TARGET) : $(OBJS) mpc.h khash.h klist.h kstring.h slre.h ore.h 22 | gcc -o $@ $(OBJS) $(LIBS) 23 | 24 | .c.o : 25 | gcc -c $(CFLAGS) -I. $< -o $@ 26 | 27 | clean : 28 | rm -f *.o $(TARGET) 29 | 30 | test : 31 | sh -c ./t/test.sh 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # orelang 2 | 3 | [![Build Status](https://travis-ci.org/mattn/orelang.svg?branch=master)](https://travis-ci.org/mattn/orelang) 4 | 5 | 俺言語 6 | 7 | 8 | * [プログラミング言語の作り方](http://mattn.kaoriya.net/software/build_your_own_programming_language.htm) ![](http://b.hatena.ne.jp/entry/image/http://mattn.kaoriya.net/software/build_your_own_programming_language.htm) 9 | * [プログラミング言語の作り方(2)](http://mattn.kaoriya.net/software/build_your_own_programming_language2.htm) ![](http://b.hatena.ne.jp/entry/image/http://mattn.kaoriya.net/software/build_your_own_programming_language2.htm) 10 | * [プログラミング言語の作り方(3)](http://mattn.kaoriya.net/software/build_your_own_programming_language3.htm) ![](http://b.hatena.ne.jp/entry/image/http://mattn.kaoriya.net/software/build_your_own_programming_language3.htm) 11 | * [プログラミング言語の作り方(4)](http://mattn.kaoriya.net/software/build_your_own_programming_language4.htm) ![](http://b.hatena.ne.jp/entry/image/http://mattn.kaoriya.net/software/build_your_own_programming_language4.htm) 12 | * [プログラミング言語の作り方(5)](http://mattn.kaoriya.net/software/build_your_own_programming_language5.htm) ![](http://b.hatena.ne.jp/entry/image/http://mattn.kaoriya.net/software/build_your_own_programming_language5.htm) 13 | 14 | # Usage 15 | 16 | ``` 17 | # calculation 18 | var a = 1; 19 | a = a * 2 + 1; 20 | var b = "hello"; 21 | 22 | # display 23 | println(b, a + 1); 24 | ``` 25 | 26 | # License 27 | 28 | Public Domain 29 | 30 | # Author 31 | 32 | Yasuhiro Matsumoto (a.k.a. mattn) 33 | -------------------------------------------------------------------------------- /example/class.ore: -------------------------------------------------------------------------------- 1 | #!ore 2 | class Foo { 3 | var a = 0; 4 | func __initialize__(x, y) { 5 | this.a = x + y; 6 | } 7 | func __terminate__() { 8 | println("terminate"); 9 | } 10 | func sing() { 11 | this.say("foo"); 12 | } 13 | func say(s) { 14 | println(s, a); 15 | } 16 | } 17 | 18 | var a = new Foo(1, 2); 19 | a.sing(); 20 | println(a.a); 21 | -------------------------------------------------------------------------------- /example/counter.ore: -------------------------------------------------------------------------------- 1 | #!ore 2 | var count = (func() { 3 | var a = 0; 4 | return func() { 5 | a = a + 1; 6 | return a; 7 | }; 8 | })(); 9 | 10 | println("count", count()); 11 | println("count", count()); 12 | -------------------------------------------------------------------------------- /example/err.ore: -------------------------------------------------------------------------------- 1 | #!ore 2 | a = 1; 3 | a[0] = 23; 4 | println("Should not be passed"); 5 | -------------------------------------------------------------------------------- /example/fib.ore: -------------------------------------------------------------------------------- 1 | #!ore 2 | func fib(n) { 3 | if (n < 2) { 4 | return n; 5 | } 6 | return fib(n-2) + fib(n-1); 7 | } 8 | 9 | println(fib(29)); 10 | -------------------------------------------------------------------------------- /example/fizzbuzz.ore: -------------------------------------------------------------------------------- 1 | #!ore 2 | 3 | for (a in range(1, 100)) { 4 | if ((a % 15) == 0) { 5 | println("FizzBuzz"); 6 | } else if ((a % 3) == 0) { 7 | println("Fizz"); 8 | } else if ((a % 5) == 0) { 9 | println("Buzz"); 10 | } else { 11 | println(a); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/foo.ore: -------------------------------------------------------------------------------- 1 | #!ore 2 | # 計算 3 | a = 1.0; 4 | a = a * 2 + 1; 5 | b = "hello"; 6 | println(b, a + 1); 7 | 8 | # 関数宣言 9 | func foo() { 10 | println(1); 11 | } 12 | 13 | # 関数呼出 14 | foo(); 15 | 16 | # λ関数 17 | c = func(){ 18 | println("lambda"); 19 | }; 20 | println(len("foo")); 21 | 22 | # λ関数呼出 23 | c(); 24 | -------------------------------------------------------------------------------- /example/regexp.ore: -------------------------------------------------------------------------------- 1 | #!ore 2 | var r = /^([\\+-]?)([\\d]+)$/; 3 | m = "+27" =~ r; 4 | if (m) { 5 | puts("matched", m); # [+,27] 6 | } 7 | -------------------------------------------------------------------------------- /example/variadic.ore: -------------------------------------------------------------------------------- 1 | #!ore 2 | func foo(x...) { 3 | println(x); 4 | } 5 | foo(1, 2, 3); 6 | -------------------------------------------------------------------------------- /example/while.ore: -------------------------------------------------------------------------------- 1 | #!ore 2 | var a = 5; 3 | while (a) { 4 | println(a); 5 | a = a - 1; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /khash.h: -------------------------------------------------------------------------------- 1 | /* The MIT License 2 | 3 | Copyright (c) 2008, 2009, 2011 by Attractive Chaos 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | */ 25 | 26 | /* 27 | An example: 28 | 29 | #include "khash.h" 30 | KHASH_MAP_INIT_INT(32, char) 31 | int main() { 32 | int ret, is_missing; 33 | khiter_t k; 34 | khash_t(32) *h = kh_init(32); 35 | k = kh_put(32, h, 5, &ret); 36 | kh_value(h, k) = 10; 37 | k = kh_get(32, h, 10); 38 | is_missing = (k == kh_end(h)); 39 | k = kh_get(32, h, 5); 40 | kh_del(32, h, k); 41 | for (k = kh_begin(h); k != kh_end(h); ++k) 42 | if (kh_exist(h, k)) kh_value(h, k) = 1; 43 | kh_destroy(32, h); 44 | return 0; 45 | } 46 | */ 47 | 48 | /* 49 | 2013-05-02 (0.2.8): 50 | 51 | * Use quadratic probing. When the capacity is power of 2, stepping function 52 | i*(i+1)/2 guarantees to traverse each bucket. It is better than double 53 | hashing on cache performance and is more robust than linear probing. 54 | 55 | In theory, double hashing should be more robust than quadratic probing. 56 | However, my implementation is probably not for large hash tables, because 57 | the second hash function is closely tied to the first hash function, 58 | which reduce the effectiveness of double hashing. 59 | 60 | Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php 61 | 62 | 2011-12-29 (0.2.7): 63 | 64 | * Minor code clean up; no actual effect. 65 | 66 | 2011-09-16 (0.2.6): 67 | 68 | * The capacity is a power of 2. This seems to dramatically improve the 69 | speed for simple keys. Thank Zilong Tan for the suggestion. Reference: 70 | 71 | - http://code.google.com/p/ulib/ 72 | - http://nothings.org/computer/judy/ 73 | 74 | * Allow to optionally use linear probing which usually has better 75 | performance for random input. Double hashing is still the default as it 76 | is more robust to certain non-random input. 77 | 78 | * Added Wang's integer hash function (not used by default). This hash 79 | function is more robust to certain non-random input. 80 | 81 | 2011-02-14 (0.2.5): 82 | 83 | * Allow to declare global functions. 84 | 85 | 2009-09-26 (0.2.4): 86 | 87 | * Improve portability 88 | 89 | 2008-09-19 (0.2.3): 90 | 91 | * Corrected the example 92 | * Improved interfaces 93 | 94 | 2008-09-11 (0.2.2): 95 | 96 | * Improved speed a little in kh_put() 97 | 98 | 2008-09-10 (0.2.1): 99 | 100 | * Added kh_clear() 101 | * Fixed a compiling error 102 | 103 | 2008-09-02 (0.2.0): 104 | 105 | * Changed to token concatenation which increases flexibility. 106 | 107 | 2008-08-31 (0.1.2): 108 | 109 | * Fixed a bug in kh_get(), which has not been tested previously. 110 | 111 | 2008-08-31 (0.1.1): 112 | 113 | * Added destructor 114 | */ 115 | 116 | 117 | #ifndef __AC_KHASH_H 118 | #define __AC_KHASH_H 119 | 120 | /*! 121 | @header 122 | 123 | Generic hash table library. 124 | */ 125 | 126 | #define AC_VERSION_KHASH_H "0.2.8" 127 | 128 | #include 129 | #include 130 | #include 131 | 132 | /* compiler specific configuration */ 133 | 134 | #if UINT_MAX == 0xffffffffu 135 | typedef unsigned int khint32_t; 136 | #elif ULONG_MAX == 0xffffffffu 137 | typedef unsigned long khint32_t; 138 | #endif 139 | 140 | #if ULONG_MAX == ULLONG_MAX 141 | typedef unsigned long khint64_t; 142 | #else 143 | typedef unsigned long long khint64_t; 144 | #endif 145 | 146 | #ifdef _MSC_VER 147 | #define kh_inline __inline 148 | #else 149 | #define kh_inline inline 150 | #endif 151 | 152 | typedef khint32_t khint_t; 153 | typedef khint_t khiter_t; 154 | 155 | #define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2) 156 | #define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1) 157 | #define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3) 158 | #define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1))) 159 | #define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1))) 160 | #define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1))) 161 | #define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1)) 162 | 163 | #define __ac_fsize(m) ((m) < 16? 1 : (m)>>4) 164 | 165 | #ifndef kroundup32 166 | #define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) 167 | #endif 168 | 169 | #ifndef kcalloc 170 | #define kcalloc(N,Z) calloc(N,Z) 171 | #endif 172 | #ifndef kmalloc 173 | #define kmalloc(Z) malloc(Z) 174 | #endif 175 | #ifndef krealloc 176 | #define krealloc(P,Z) realloc(P,Z) 177 | #endif 178 | #ifndef kfree 179 | #define kfree(P) free(P) 180 | #endif 181 | 182 | static const double __ac_HASH_UPPER = 0.77; 183 | 184 | #define __KHASH_TYPE(name, khkey_t, khval_t) \ 185 | typedef struct { \ 186 | khint_t n_buckets, size, n_occupied, upper_bound; \ 187 | khint32_t *flags; \ 188 | khkey_t *keys; \ 189 | khval_t *vals; \ 190 | } kh_##name##_t; 191 | 192 | #define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \ 193 | extern kh_##name##_t *kh_init_##name(void); \ 194 | extern void kh_destroy_##name(kh_##name##_t *h); \ 195 | extern void kh_clear_##name(kh_##name##_t *h); \ 196 | extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \ 197 | extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \ 198 | extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \ 199 | extern void kh_del_##name(kh_##name##_t *h, khint_t x); 200 | 201 | #define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ 202 | SCOPE kh_##name##_t *kh_init_##name(void) { \ 203 | return (kh_##name##_t*)kcalloc(1, sizeof(kh_##name##_t)); \ 204 | } \ 205 | SCOPE void kh_destroy_##name(kh_##name##_t *h) \ 206 | { \ 207 | if (h) { \ 208 | kfree((void *)h->keys); kfree(h->flags); \ 209 | kfree((void *)h->vals); \ 210 | kfree(h); \ 211 | } \ 212 | } \ 213 | SCOPE void kh_clear_##name(kh_##name##_t *h) \ 214 | { \ 215 | if (h && h->flags) { \ 216 | memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \ 217 | h->size = h->n_occupied = 0; \ 218 | } \ 219 | } \ 220 | SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ 221 | { \ 222 | if (h->n_buckets) { \ 223 | khint_t k, i, last, mask, step = 0; \ 224 | mask = h->n_buckets - 1; \ 225 | k = __hash_func(key); i = k & mask; \ 226 | last = i; \ 227 | while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ 228 | i = (i + (++step)) & mask; \ 229 | if (i == last) return h->n_buckets; \ 230 | } \ 231 | return __ac_iseither(h->flags, i)? h->n_buckets : i; \ 232 | } else return 0; \ 233 | } \ 234 | SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ 235 | { /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \ 236 | khint32_t *new_flags = 0; \ 237 | khint_t j = 1; \ 238 | { \ 239 | kroundup32(new_n_buckets); \ 240 | if (new_n_buckets < 4) new_n_buckets = 4; \ 241 | if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \ 242 | else { /* hash table size to be changed (shrink or expand); rehash */ \ 243 | new_flags = (khint32_t*)kmalloc(__ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ 244 | if (!new_flags) return -1; \ 245 | memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ 246 | if (h->n_buckets < new_n_buckets) { /* expand */ \ 247 | khkey_t *new_keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ 248 | if (!new_keys) return -1; \ 249 | h->keys = new_keys; \ 250 | if (kh_is_map) { \ 251 | khval_t *new_vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \ 252 | if (!new_vals) return -1; \ 253 | h->vals = new_vals; \ 254 | } \ 255 | } /* otherwise shrink */ \ 256 | } \ 257 | } \ 258 | if (j) { /* rehashing is needed */ \ 259 | for (j = 0; j != h->n_buckets; ++j) { \ 260 | if (__ac_iseither(h->flags, j) == 0) { \ 261 | khkey_t key = h->keys[j]; \ 262 | khval_t val; \ 263 | khint_t new_mask; \ 264 | new_mask = new_n_buckets - 1; \ 265 | if (kh_is_map) val = h->vals[j]; \ 266 | __ac_set_isdel_true(h->flags, j); \ 267 | while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \ 268 | khint_t k, i, step = 0; \ 269 | k = __hash_func(key); \ 270 | i = k & new_mask; \ 271 | while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \ 272 | __ac_set_isempty_false(new_flags, i); \ 273 | if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \ 274 | { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \ 275 | if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \ 276 | __ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \ 277 | } else { /* write the element and jump out of the loop */ \ 278 | h->keys[i] = key; \ 279 | if (kh_is_map) h->vals[i] = val; \ 280 | break; \ 281 | } \ 282 | } \ 283 | } \ 284 | } \ 285 | if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \ 286 | h->keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ 287 | if (kh_is_map) h->vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \ 288 | } \ 289 | kfree(h->flags); /* free the working space */ \ 290 | h->flags = new_flags; \ 291 | h->n_buckets = new_n_buckets; \ 292 | h->n_occupied = h->size; \ 293 | h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \ 294 | } \ 295 | return 0; \ 296 | } \ 297 | SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ 298 | { \ 299 | khint_t x; \ 300 | if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \ 301 | if (h->n_buckets > (h->size<<1)) { \ 302 | if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \ 303 | *ret = -1; return h->n_buckets; \ 304 | } \ 305 | } else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \ 306 | *ret = -1; return h->n_buckets; \ 307 | } \ 308 | } /* TODO: to implement automatically shrinking; resize() already support shrinking */ \ 309 | { \ 310 | khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \ 311 | x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \ 312 | if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \ 313 | else { \ 314 | last = i; \ 315 | while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ 316 | if (__ac_isdel(h->flags, i)) site = i; \ 317 | i = (i + (++step)) & mask; \ 318 | if (i == last) { x = site; break; } \ 319 | } \ 320 | if (x == h->n_buckets) { \ 321 | if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \ 322 | else x = i; \ 323 | } \ 324 | } \ 325 | } \ 326 | if (__ac_isempty(h->flags, x)) { /* not present at all */ \ 327 | h->keys[x] = key; \ 328 | __ac_set_isboth_false(h->flags, x); \ 329 | ++h->size; ++h->n_occupied; \ 330 | *ret = 1; \ 331 | } else if (__ac_isdel(h->flags, x)) { /* deleted */ \ 332 | h->keys[x] = key; \ 333 | __ac_set_isboth_false(h->flags, x); \ 334 | ++h->size; \ 335 | *ret = 2; \ 336 | } else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \ 337 | return x; \ 338 | } \ 339 | SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ 340 | { \ 341 | if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \ 342 | __ac_set_isdel_true(h->flags, x); \ 343 | --h->size; \ 344 | } \ 345 | } 346 | 347 | #define KHASH_DECLARE(name, khkey_t, khval_t) \ 348 | __KHASH_TYPE(name, khkey_t, khval_t) \ 349 | __KHASH_PROTOTYPES(name, khkey_t, khval_t) 350 | 351 | #define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ 352 | __KHASH_TYPE(name, khkey_t, khval_t) \ 353 | __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) 354 | 355 | #define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ 356 | KHASH_INIT2(name, static kh_inline, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) 357 | 358 | /* --- BEGIN OF HASH FUNCTIONS --- */ 359 | 360 | /*! @function 361 | @abstract Integer hash function 362 | @param key The integer [khint32_t] 363 | @return The hash value [khint_t] 364 | */ 365 | #define kh_int_hash_func(key) (khint32_t)(key) 366 | /*! @function 367 | @abstract Integer comparison function 368 | */ 369 | #define kh_int_hash_equal(a, b) ((a) == (b)) 370 | /*! @function 371 | @abstract 64-bit integer hash function 372 | @param key The integer [khint64_t] 373 | @return The hash value [khint_t] 374 | */ 375 | #define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11) 376 | /*! @function 377 | @abstract 64-bit integer comparison function 378 | */ 379 | #define kh_int64_hash_equal(a, b) ((a) == (b)) 380 | /*! @function 381 | @abstract const char* hash function 382 | @param s Pointer to a null terminated string 383 | @return The hash value 384 | */ 385 | static kh_inline khint_t __ac_X31_hash_string(const char *s) 386 | { 387 | khint_t h = (khint_t)*s; 388 | if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s; 389 | return h; 390 | } 391 | /*! @function 392 | @abstract Another interface to const char* hash function 393 | @param key Pointer to a null terminated string [const char*] 394 | @return The hash value [khint_t] 395 | */ 396 | #define kh_str_hash_func(key) __ac_X31_hash_string(key) 397 | /*! @function 398 | @abstract Const char* comparison function 399 | */ 400 | #define kh_str_hash_equal(a, b) (strcmp(a, b) == 0) 401 | 402 | static kh_inline khint_t __ac_Wang_hash(khint_t key) 403 | { 404 | key += ~(key << 15); 405 | key ^= (key >> 10); 406 | key += (key << 3); 407 | key ^= (key >> 6); 408 | key += ~(key << 11); 409 | key ^= (key >> 16); 410 | return key; 411 | } 412 | #define kh_int_hash_func2(k) __ac_Wang_hash((khint_t)key) 413 | 414 | /* --- END OF HASH FUNCTIONS --- */ 415 | 416 | /* Other convenient macros... */ 417 | 418 | /*! 419 | @abstract Type of the hash table. 420 | @param name Name of the hash table [symbol] 421 | */ 422 | #define khash_t(name) kh_##name##_t 423 | 424 | /*! @function 425 | @abstract Initiate a hash table. 426 | @param name Name of the hash table [symbol] 427 | @return Pointer to the hash table [khash_t(name)*] 428 | */ 429 | #define kh_init(name) kh_init_##name() 430 | 431 | /*! @function 432 | @abstract Destroy a hash table. 433 | @param name Name of the hash table [symbol] 434 | @param h Pointer to the hash table [khash_t(name)*] 435 | */ 436 | #define kh_destroy(name, h) kh_destroy_##name(h) 437 | 438 | /*! @function 439 | @abstract Reset a hash table without deallocating memory. 440 | @param name Name of the hash table [symbol] 441 | @param h Pointer to the hash table [khash_t(name)*] 442 | */ 443 | #define kh_clear(name, h) kh_clear_##name(h) 444 | 445 | /*! @function 446 | @abstract Resize a hash table. 447 | @param name Name of the hash table [symbol] 448 | @param h Pointer to the hash table [khash_t(name)*] 449 | @param s New size [khint_t] 450 | */ 451 | #define kh_resize(name, h, s) kh_resize_##name(h, s) 452 | 453 | /*! @function 454 | @abstract Insert a key to the hash table. 455 | @param name Name of the hash table [symbol] 456 | @param h Pointer to the hash table [khash_t(name)*] 457 | @param k Key [type of keys] 458 | @param r Extra return code: -1 if the operation failed; 459 | 0 if the key is present in the hash table; 460 | 1 if the bucket is empty (never used); 2 if the element in 461 | the bucket has been deleted [int*] 462 | @return Iterator to the inserted element [khint_t] 463 | */ 464 | #define kh_put(name, h, k, r) kh_put_##name(h, k, r) 465 | 466 | /*! @function 467 | @abstract Retrieve a key from the hash table. 468 | @param name Name of the hash table [symbol] 469 | @param h Pointer to the hash table [khash_t(name)*] 470 | @param k Key [type of keys] 471 | @return Iterator to the found element, or kh_end(h) if the element is absent [khint_t] 472 | */ 473 | #define kh_get(name, h, k) kh_get_##name(h, k) 474 | 475 | /*! @function 476 | @abstract Remove a key from the hash table. 477 | @param name Name of the hash table [symbol] 478 | @param h Pointer to the hash table [khash_t(name)*] 479 | @param k Iterator to the element to be deleted [khint_t] 480 | */ 481 | #define kh_del(name, h, k) kh_del_##name(h, k) 482 | 483 | /*! @function 484 | @abstract Test whether a bucket contains data. 485 | @param h Pointer to the hash table [khash_t(name)*] 486 | @param x Iterator to the bucket [khint_t] 487 | @return 1 if containing data; 0 otherwise [int] 488 | */ 489 | #define kh_exist(h, x) (!__ac_iseither((h)->flags, (x))) 490 | 491 | /*! @function 492 | @abstract Get key given an iterator 493 | @param h Pointer to the hash table [khash_t(name)*] 494 | @param x Iterator to the bucket [khint_t] 495 | @return Key [type of keys] 496 | */ 497 | #define kh_key(h, x) ((h)->keys[x]) 498 | 499 | /*! @function 500 | @abstract Get value given an iterator 501 | @param h Pointer to the hash table [khash_t(name)*] 502 | @param x Iterator to the bucket [khint_t] 503 | @return Value [type of values] 504 | @discussion For hash sets, calling this results in segfault. 505 | */ 506 | #define kh_val(h, x) ((h)->vals[x]) 507 | 508 | /*! @function 509 | @abstract Alias of kh_val() 510 | */ 511 | #define kh_value(h, x) ((h)->vals[x]) 512 | 513 | /*! @function 514 | @abstract Get the start iterator 515 | @param h Pointer to the hash table [khash_t(name)*] 516 | @return The start iterator [khint_t] 517 | */ 518 | #define kh_begin(h) (khint_t)(0) 519 | 520 | /*! @function 521 | @abstract Get the end iterator 522 | @param h Pointer to the hash table [khash_t(name)*] 523 | @return The end iterator [khint_t] 524 | */ 525 | #define kh_end(h) ((h)->n_buckets) 526 | 527 | /*! @function 528 | @abstract Get the number of elements in the hash table 529 | @param h Pointer to the hash table [khash_t(name)*] 530 | @return Number of elements in the hash table [khint_t] 531 | */ 532 | #define kh_size(h) ((h)->size) 533 | 534 | /*! @function 535 | @abstract Get the number of buckets in the hash table 536 | @param h Pointer to the hash table [khash_t(name)*] 537 | @return Number of buckets in the hash table [khint_t] 538 | */ 539 | #define kh_n_buckets(h) ((h)->n_buckets) 540 | 541 | /*! @function 542 | @abstract Iterate over the entries in the hash table 543 | @param h Pointer to the hash table [khash_t(name)*] 544 | @param kvar Variable to which key will be assigned 545 | @param vvar Variable to which value will be assigned 546 | @param code Block of code to execute 547 | */ 548 | #define kh_foreach(h, kvar, vvar, code) { khint_t __i; \ 549 | for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ 550 | if (!kh_exist(h,__i)) continue; \ 551 | (kvar) = kh_key(h,__i); \ 552 | (vvar) = kh_val(h,__i); \ 553 | code; \ 554 | } } 555 | 556 | /*! @function 557 | @abstract Iterate over the values in the hash table 558 | @param h Pointer to the hash table [khash_t(name)*] 559 | @param vvar Variable to which value will be assigned 560 | @param code Block of code to execute 561 | */ 562 | #define kh_foreach_value(h, vvar, code) { khint_t __i; \ 563 | for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ 564 | if (!kh_exist(h,__i)) continue; \ 565 | (vvar) = kh_val(h,__i); \ 566 | code; \ 567 | } } 568 | 569 | /* More conenient interfaces */ 570 | 571 | /*! @function 572 | @abstract Instantiate a hash set containing integer keys 573 | @param name Name of the hash table [symbol] 574 | */ 575 | #define KHASH_SET_INIT_INT(name) \ 576 | KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal) 577 | 578 | /*! @function 579 | @abstract Instantiate a hash map containing integer keys 580 | @param name Name of the hash table [symbol] 581 | @param khval_t Type of values [type] 582 | */ 583 | #define KHASH_MAP_INIT_INT(name, khval_t) \ 584 | KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal) 585 | 586 | /*! @function 587 | @abstract Instantiate a hash map containing 64-bit integer keys 588 | @param name Name of the hash table [symbol] 589 | */ 590 | #define KHASH_SET_INIT_INT64(name) \ 591 | KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal) 592 | 593 | /*! @function 594 | @abstract Instantiate a hash map containing 64-bit integer keys 595 | @param name Name of the hash table [symbol] 596 | @param khval_t Type of values [type] 597 | */ 598 | #define KHASH_MAP_INIT_INT64(name, khval_t) \ 599 | KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal) 600 | 601 | typedef const char *kh_cstr_t; 602 | /*! @function 603 | @abstract Instantiate a hash map containing const char* keys 604 | @param name Name of the hash table [symbol] 605 | */ 606 | #define KHASH_SET_INIT_STR(name) \ 607 | KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal) 608 | 609 | /*! @function 610 | @abstract Instantiate a hash map containing const char* keys 611 | @param name Name of the hash table [symbol] 612 | @param khval_t Type of values [type] 613 | */ 614 | #define KHASH_MAP_INIT_STR(name, khval_t) \ 615 | KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal) 616 | 617 | #endif /* __AC_KHASH_H */ 618 | -------------------------------------------------------------------------------- /klist.h: -------------------------------------------------------------------------------- 1 | /* The MIT License 2 | 3 | Copyright (c) 2008-2009, by Attractive Chaos 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | */ 25 | 26 | #ifndef _AC_KLIST_H 27 | #define _AC_KLIST_H 28 | 29 | #include 30 | 31 | #define KMEMPOOL_INIT(name, kmptype_t, kmpfree_f) \ 32 | typedef struct { \ 33 | size_t cnt, n, max; \ 34 | kmptype_t **buf; \ 35 | } kmp_##name##_t; \ 36 | static inline kmp_##name##_t *kmp_init_##name(void) { \ 37 | return calloc(1, sizeof(kmp_##name##_t)); \ 38 | } \ 39 | static inline void kmp_destroy_##name(kmp_##name##_t *mp) { \ 40 | size_t k; \ 41 | for (k = 0; k < mp->n; ++k) { \ 42 | kmpfree_f(mp->buf[k]); free(mp->buf[k]); \ 43 | } \ 44 | free(mp->buf); free(mp); \ 45 | } \ 46 | static inline kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \ 47 | ++mp->cnt; \ 48 | if (mp->n == 0) return calloc(1, sizeof(kmptype_t)); \ 49 | return mp->buf[--mp->n]; \ 50 | } \ 51 | static inline void kmp_free_##name(kmp_##name##_t *mp, kmptype_t *p) { \ 52 | --mp->cnt; \ 53 | if (mp->n == mp->max) { \ 54 | mp->max = mp->max? mp->max<<1 : 16; \ 55 | mp->buf = realloc(mp->buf, sizeof(kmptype_t *) * mp->max); \ 56 | } \ 57 | mp->buf[mp->n++] = p; \ 58 | } 59 | 60 | #define kmempool_t(name) kmp_##name##_t 61 | #define kmp_init(name) kmp_init_##name() 62 | #define kmp_destroy(name, mp) kmp_destroy_##name(mp) 63 | #define kmp_alloc(name, mp) kmp_alloc_##name(mp) 64 | #define kmp_free(name, mp, p) kmp_free_##name(mp, p) 65 | 66 | #define KLIST_INIT(name, kltype_t, kmpfree_t) \ 67 | struct __kl1_##name { \ 68 | kltype_t data; \ 69 | struct __kl1_##name *next; \ 70 | }; \ 71 | typedef struct __kl1_##name kl1_##name; \ 72 | KMEMPOOL_INIT(name, kl1_##name, kmpfree_t) \ 73 | typedef struct { \ 74 | kl1_##name *head, *tail; \ 75 | kmp_##name##_t *mp; \ 76 | size_t size; \ 77 | } kl_##name##_t; \ 78 | static inline kl_##name##_t *kl_init_##name(void) { \ 79 | kl_##name##_t *kl = calloc(1, sizeof(kl_##name##_t)); \ 80 | kl->mp = kmp_init(name); \ 81 | kl->head = kl->tail = kmp_alloc(name, kl->mp); \ 82 | kl->head->next = 0; \ 83 | return kl; \ 84 | } \ 85 | static inline void kl_destroy_##name(kl_##name##_t *kl) { \ 86 | kl1_##name *p; \ 87 | for (p = kl->head; p != kl->tail; p = p->next) \ 88 | kmp_free(name, kl->mp, p); \ 89 | kmp_free(name, kl->mp, p); \ 90 | kmp_destroy(name, kl->mp); \ 91 | free(kl); \ 92 | } \ 93 | static inline kltype_t *kl_pushp_##name(kl_##name##_t *kl) { \ 94 | kl1_##name *q, *p = kmp_alloc(name, kl->mp); \ 95 | q = kl->tail; p->next = 0; kl->tail->next = p; kl->tail = p; \ 96 | ++kl->size; \ 97 | return &q->data; \ 98 | } \ 99 | static inline int kl_shift_##name(kl_##name##_t *kl, kltype_t *d) { \ 100 | kl1_##name *p; \ 101 | if (kl->head->next == 0) return -1; \ 102 | --kl->size; \ 103 | p = kl->head; kl->head = kl->head->next; \ 104 | if (d) *d = p->data; \ 105 | kmp_free(name, kl->mp, p); \ 106 | return 0; \ 107 | } 108 | 109 | #define kliter_t(name) kl1_##name 110 | #define klist_t(name) kl_##name##_t 111 | #define kl_val(iter) ((iter)->data) 112 | #define kl_next(iter) ((iter)->next) 113 | #define kl_begin(kl) ((kl)->head) 114 | #define kl_end(kl) ((kl)->tail) 115 | 116 | #define kl_init(name) kl_init_##name() 117 | #define kl_destroy(name, kl) kl_destroy_##name(kl) 118 | #define kl_pushp(name, kl) kl_pushp_##name(kl) 119 | #define kl_shift(name, kl, d) kl_shift_##name(kl, d) 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /kstring.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "kstring.h" 7 | 8 | int kvsprintf(kstring_t *s, const char *fmt, va_list ap) 9 | { 10 | va_list args; 11 | int l; 12 | va_copy(args, ap); 13 | l = vsnprintf(s->s + s->l, s->m - s->l, fmt, args); // This line does not work with glibc 2.0. See `man snprintf'. 14 | va_end(args); 15 | if (l + 1 > s->m - s->l) { 16 | s->m = s->l + l + 2; 17 | kroundup32(s->m); 18 | s->s = (char*)realloc(s->s, s->m); 19 | va_copy(args, ap); 20 | l = vsnprintf(s->s + s->l, s->m - s->l, fmt, args); 21 | va_end(args); 22 | } 23 | s->l += l; 24 | return l; 25 | } 26 | 27 | int ksprintf(kstring_t *s, const char *fmt, ...) 28 | { 29 | va_list ap; 30 | int l; 31 | va_start(ap, fmt); 32 | l = kvsprintf(s, fmt, ap); 33 | va_end(ap); 34 | return l; 35 | } 36 | 37 | char *kstrtok(const char *str, const char *sep, ks_tokaux_t *aux) 38 | { 39 | const char *p, *start; 40 | if (sep) { // set up the table 41 | if (str == 0 && (aux->tab[0]&1)) return 0; // no need to set up if we have finished 42 | aux->finished = 0; 43 | if (sep[1]) { 44 | aux->sep = -1; 45 | aux->tab[0] = aux->tab[1] = aux->tab[2] = aux->tab[3] = 0; 46 | for (p = sep; *p; ++p) aux->tab[*p>>6] |= 1ull<<(*p&0x3f); 47 | } else aux->sep = sep[0]; 48 | } 49 | if (aux->finished) return 0; 50 | else if (str) aux->p = str - 1, aux->finished = 0; 51 | if (aux->sep < 0) { 52 | for (p = start = aux->p + 1; *p; ++p) 53 | if (aux->tab[*p>>6]>>(*p&0x3f)&1) break; 54 | } else { 55 | for (p = start = aux->p + 1; *p; ++p) 56 | if (*p == aux->sep) break; 57 | } 58 | aux->p = p; // end of token 59 | if (*p == 0) aux->finished = 1; // no more tokens 60 | return (char*)start; 61 | } 62 | 63 | // s MUST BE a null terminated string; l = strlen(s) 64 | int ksplit_core(char *s, int delimiter, int *_max, int **_offsets) 65 | { 66 | int i, n, max, last_char, last_start, *offsets, l; 67 | n = 0; max = *_max; offsets = *_offsets; 68 | l = strlen(s); 69 | 70 | #define __ksplit_aux do { \ 71 | if (_offsets) { \ 72 | s[i] = 0; \ 73 | if (n == max) { \ 74 | int *tmp; \ 75 | max = max? max<<1 : 2; \ 76 | if ((tmp = (int*)realloc(offsets, sizeof(int) * max))) { \ 77 | offsets = tmp; \ 78 | } else { \ 79 | free(offsets); \ 80 | *_offsets = NULL; \ 81 | return 0; \ 82 | } \ 83 | } \ 84 | offsets[n++] = last_start; \ 85 | } else ++n; \ 86 | } while (0) 87 | 88 | for (i = 0, last_char = last_start = 0; i <= l; ++i) { 89 | if (delimiter == 0) { 90 | if (isspace(s[i]) || s[i] == 0) { 91 | if (isgraph(last_char)) __ksplit_aux; // the end of a field 92 | } else { 93 | if (isspace(last_char) || last_char == 0) last_start = i; 94 | } 95 | } else { 96 | if (s[i] == delimiter || s[i] == 0) { 97 | if (last_char != 0 && last_char != delimiter) __ksplit_aux; // the end of a field 98 | } else { 99 | if (last_char == delimiter || last_char == 0) last_start = i; 100 | } 101 | } 102 | last_char = s[i]; 103 | } 104 | *_max = max; *_offsets = offsets; 105 | return n; 106 | } 107 | 108 | /********************** 109 | * Boyer-Moore search * 110 | **********************/ 111 | 112 | typedef unsigned char ubyte_t; 113 | 114 | // reference: http://www-igm.univ-mlv.fr/~lecroq/string/node14.html 115 | static int *ksBM_prep(const ubyte_t *pat, int m) 116 | { 117 | int i, *suff, *prep, *bmGs, *bmBc; 118 | prep = (int*)calloc(m + 256, sizeof(int)); 119 | bmGs = prep; bmBc = prep + m; 120 | { // preBmBc() 121 | for (i = 0; i < 256; ++i) bmBc[i] = m; 122 | for (i = 0; i < m - 1; ++i) bmBc[pat[i]] = m - i - 1; 123 | } 124 | suff = (int*)calloc(m, sizeof(int)); 125 | { // suffixes() 126 | int f = 0, g; 127 | suff[m - 1] = m; 128 | g = m - 1; 129 | for (i = m - 2; i >= 0; --i) { 130 | if (i > g && suff[i + m - 1 - f] < i - g) 131 | suff[i] = suff[i + m - 1 - f]; 132 | else { 133 | if (i < g) g = i; 134 | f = i; 135 | while (g >= 0 && pat[g] == pat[g + m - 1 - f]) --g; 136 | suff[i] = f - g; 137 | } 138 | } 139 | } 140 | { // preBmGs() 141 | int j = 0; 142 | for (i = 0; i < m; ++i) bmGs[i] = m; 143 | for (i = m - 1; i >= 0; --i) 144 | if (suff[i] == i + 1) 145 | for (; j < m - 1 - i; ++j) 146 | if (bmGs[j] == m) 147 | bmGs[j] = m - 1 - i; 148 | for (i = 0; i <= m - 2; ++i) 149 | bmGs[m - 1 - suff[i]] = m - 1 - i; 150 | } 151 | free(suff); 152 | return prep; 153 | } 154 | 155 | void *kmemmem(const void *_str, int n, const void *_pat, int m, int **_prep) 156 | { 157 | int i, j, *prep = 0, *bmGs, *bmBc; 158 | const ubyte_t *str, *pat; 159 | str = (const ubyte_t*)_str; pat = (const ubyte_t*)_pat; 160 | prep = (_prep == 0 || *_prep == 0)? ksBM_prep(pat, m) : *_prep; 161 | if (_prep && *_prep == 0) *_prep = prep; 162 | bmGs = prep; bmBc = prep + m; 163 | j = 0; 164 | while (j <= n - m) { 165 | for (i = m - 1; i >= 0 && pat[i] == str[i+j]; --i); 166 | if (i >= 0) { 167 | int max = bmBc[str[i+j]] - m + 1 + i; 168 | if (max < bmGs[i]) max = bmGs[i]; 169 | j += max; 170 | } else return (void*)(str + j); 171 | } 172 | if (_prep == 0) free(prep); 173 | return 0; 174 | } 175 | 176 | char *kstrstr(const char *str, const char *pat, int **_prep) 177 | { 178 | return (char*)kmemmem(str, strlen(str), pat, strlen(pat), _prep); 179 | } 180 | 181 | char *kstrnstr(const char *str, const char *pat, int n, int **_prep) 182 | { 183 | return (char*)kmemmem(str, n, pat, strlen(pat), _prep); 184 | } 185 | 186 | /*********************** 187 | * The main() function * 188 | ***********************/ 189 | 190 | #ifdef KSTRING_MAIN 191 | #include 192 | int main() 193 | { 194 | kstring_t *s; 195 | int *fields, n, i; 196 | ks_tokaux_t aux; 197 | char *p; 198 | s = (kstring_t*)calloc(1, sizeof(kstring_t)); 199 | // test ksprintf() 200 | ksprintf(s, " abcdefg: %d ", 100); 201 | printf("'%s'\n", s->s); 202 | // test ksplit() 203 | fields = ksplit(s, 0, &n); 204 | for (i = 0; i < n; ++i) 205 | printf("field[%d] = '%s'\n", i, s->s + fields[i]); 206 | // test kstrtok() 207 | s->l = 0; 208 | for (p = kstrtok("ab:cde:fg/hij::k", ":/", &aux); p; p = kstrtok(0, 0, &aux)) { 209 | kputsn(p, aux.p - p, s); 210 | kputc('\n', s); 211 | } 212 | printf("%s", s->s); 213 | // free 214 | free(s->s); free(s); free(fields); 215 | 216 | { 217 | static char *str = "abcdefgcdgcagtcakcdcd"; 218 | static char *pat = "cd"; 219 | char *ret, *s = str; 220 | int *prep = 0; 221 | while ((ret = kstrstr(s, pat, &prep)) != 0) { 222 | printf("match: %s\n", ret); 223 | s = ret + prep[0]; 224 | } 225 | free(prep); 226 | } 227 | return 0; 228 | } 229 | #endif 230 | -------------------------------------------------------------------------------- /kstring.h: -------------------------------------------------------------------------------- 1 | /* The MIT License 2 | 3 | Copyright (c) by Attractive Chaos 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | */ 25 | 26 | #ifndef KSTRING_H 27 | #define KSTRING_H 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #ifndef kroundup32 36 | #define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) 37 | #endif 38 | 39 | #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) 40 | #define KS_ATTR_PRINTF(fmt, arg) __attribute__((__format__ (__printf__, fmt, arg))) 41 | #else 42 | #define KS_ATTR_PRINTF(fmt, arg) 43 | #endif 44 | 45 | 46 | /* kstring_t is a simple non-opaque type whose fields are likely to be 47 | * used directly by user code (but see also ks_str() and ks_len() below). 48 | * A kstring_t object is initialised by either of 49 | * kstring_t str = { 0, 0, NULL }; 50 | * kstring_t str; ...; str.l = str.m = 0; str.s = NULL; 51 | * and either ownership of the underlying buffer should be given away before 52 | * the object disappears (i.e., the str.s pointer copied and something else 53 | * responsible for freeing it), or the kstring_t should be destroyed with 54 | * free(str.s); */ 55 | #ifndef KSTRING_T 56 | #define KSTRING_T kstring_t 57 | typedef struct __kstring_t { 58 | size_t l, m; 59 | char *s; 60 | } kstring_t; 61 | #endif 62 | 63 | typedef struct { 64 | uint64_t tab[4]; 65 | int sep, finished; 66 | const char *p; // end of the current token 67 | } ks_tokaux_t; 68 | 69 | #ifdef __cplusplus 70 | extern "C" { 71 | #endif 72 | 73 | int kvsprintf(kstring_t *s, const char *fmt, va_list ap) KS_ATTR_PRINTF(2,0); 74 | int ksprintf(kstring_t *s, const char *fmt, ...) KS_ATTR_PRINTF(2,3); 75 | int ksplit_core(char *s, int delimiter, int *_max, int **_offsets); 76 | char *kstrstr(const char *str, const char *pat, int **_prep); 77 | char *kstrnstr(const char *str, const char *pat, int n, int **_prep); 78 | void *kmemmem(const void *_str, int n, const void *_pat, int m, int **_prep); 79 | 80 | /* kstrtok() is similar to strtok_r() except that str is not 81 | * modified and both str and sep can be NULL. For efficiency, it is 82 | * actually recommended to set both to NULL in the subsequent calls 83 | * if sep is not changed. */ 84 | char *kstrtok(const char *str, const char *sep, ks_tokaux_t *aux); 85 | 86 | #ifdef __cplusplus 87 | } 88 | #endif 89 | 90 | static inline int ks_resize(kstring_t *s, size_t size) 91 | { 92 | if (s->m < size) { 93 | char *tmp; 94 | s->m = size; 95 | kroundup32(s->m); 96 | if ((tmp = (char*)realloc(s->s, s->m))) 97 | s->s = tmp; 98 | else 99 | return -1; 100 | } 101 | return 0; 102 | } 103 | 104 | static inline char *ks_str(kstring_t *s) 105 | { 106 | return s->s; 107 | } 108 | 109 | static inline size_t ks_len(kstring_t *s) 110 | { 111 | return s->l; 112 | } 113 | 114 | static inline int kputsn(const char *p, int l, kstring_t *s) 115 | { 116 | if (s->l + l + 1 >= s->m) { 117 | char *tmp; 118 | s->m = s->l + l + 2; 119 | kroundup32(s->m); 120 | if ((tmp = (char*)realloc(s->s, s->m))) 121 | s->s = tmp; 122 | else 123 | return EOF; 124 | } 125 | memcpy(s->s + s->l, p, l); 126 | s->l += l; 127 | s->s[s->l] = 0; 128 | return l; 129 | } 130 | 131 | static inline int kputs(const char *p, kstring_t *s) 132 | { 133 | return kputsn(p, strlen(p), s); 134 | } 135 | 136 | static inline int kputc(int c, kstring_t *s) 137 | { 138 | if (s->l + 1 >= s->m) { 139 | char *tmp; 140 | s->m = s->l + 2; 141 | kroundup32(s->m); 142 | if ((tmp = (char*)realloc(s->s, s->m))) 143 | s->s = tmp; 144 | else 145 | return EOF; 146 | } 147 | s->s[s->l++] = c; 148 | s->s[s->l] = 0; 149 | return c; 150 | } 151 | 152 | static inline int kputc_(int c, kstring_t *s) 153 | { 154 | if (s->l + 1 > s->m) { 155 | char *tmp; 156 | s->m = s->l + 1; 157 | kroundup32(s->m); 158 | if ((tmp = (char*)realloc(s->s, s->m))) 159 | s->s = tmp; 160 | else 161 | return EOF; 162 | } 163 | s->s[s->l++] = c; 164 | return 1; 165 | } 166 | 167 | static inline int kputsn_(const void *p, int l, kstring_t *s) 168 | { 169 | if (s->l + l > s->m) { 170 | char *tmp; 171 | s->m = s->l + l; 172 | kroundup32(s->m); 173 | if ((tmp = (char*)realloc(s->s, s->m))) 174 | s->s = tmp; 175 | else 176 | return EOF; 177 | } 178 | memcpy(s->s + s->l, p, l); 179 | s->l += l; 180 | return l; 181 | } 182 | 183 | static inline int kputw(int c, kstring_t *s) 184 | { 185 | char buf[16]; 186 | int i, l = 0; 187 | unsigned int x = c; 188 | if (c < 0) x = -x; 189 | do { buf[l++] = x%10 + '0'; x /= 10; } while (x > 0); 190 | if (c < 0) buf[l++] = '-'; 191 | if (s->l + l + 1 >= s->m) { 192 | char *tmp; 193 | s->m = s->l + l + 2; 194 | kroundup32(s->m); 195 | if ((tmp = (char*)realloc(s->s, s->m))) 196 | s->s = tmp; 197 | else 198 | return EOF; 199 | } 200 | for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i]; 201 | s->s[s->l] = 0; 202 | return 0; 203 | } 204 | 205 | static inline int kputuw(unsigned c, kstring_t *s) 206 | { 207 | char buf[16]; 208 | int l, i; 209 | unsigned x; 210 | if (c == 0) return kputc('0', s); 211 | for (l = 0, x = c; x > 0; x /= 10) buf[l++] = x%10 + '0'; 212 | if (s->l + l + 1 >= s->m) { 213 | char *tmp; 214 | s->m = s->l + l + 2; 215 | kroundup32(s->m); 216 | if ((tmp = (char*)realloc(s->s, s->m))) 217 | s->s = tmp; 218 | else 219 | return EOF; 220 | } 221 | for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i]; 222 | s->s[s->l] = 0; 223 | return 0; 224 | } 225 | 226 | static inline int kputl(long c, kstring_t *s) 227 | { 228 | char buf[32]; 229 | int i, l = 0; 230 | unsigned long x = c; 231 | if (c < 0) x = -x; 232 | do { buf[l++] = x%10 + '0'; x /= 10; } while (x > 0); 233 | if (c < 0) buf[l++] = '-'; 234 | if (s->l + l + 1 >= s->m) { 235 | char *tmp; 236 | s->m = s->l + l + 2; 237 | kroundup32(s->m); 238 | if ((tmp = (char*)realloc(s->s, s->m))) 239 | s->s = tmp; 240 | else 241 | return EOF; 242 | } 243 | for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i]; 244 | s->s[s->l] = 0; 245 | return 0; 246 | } 247 | 248 | /* 249 | * Returns 's' split by delimiter, with *n being the number of components; 250 | * NULL on failue. 251 | */ 252 | static inline int *ksplit(kstring_t *s, int delimiter, int *n) 253 | { 254 | int max = 0, *offsets = 0; 255 | *n = ksplit_core(s->s, delimiter, &max, &offsets); 256 | return offsets; 257 | } 258 | 259 | #endif 260 | -------------------------------------------------------------------------------- /misc/vim/ftdetect/ore.vim: -------------------------------------------------------------------------------- 1 | au BufNewFile,BufRead *.ore setlocal filetype=ore 2 | -------------------------------------------------------------------------------- /misc/vim/ftplugin/ore/comment.vim: -------------------------------------------------------------------------------- 1 | if exists("b:did_ftplugin") 2 | finish 3 | endif 4 | let b:did_ftplugin = 1 5 | 6 | setlocal comments=s1:# 7 | setlocal commentstring=#\ %s 8 | 9 | let b:undo_ftplugin = "setl com< cms<" 10 | 11 | " vim:ts=4:sw=4:et 12 | -------------------------------------------------------------------------------- /misc/vim/syntax/ore.vim: -------------------------------------------------------------------------------- 1 | if exists("b:current_syntax") 2 | finish 3 | endif 4 | 5 | syn case match 6 | 7 | syn keyword oreDeclaration var 8 | 9 | hi def link oreDirective Statement 10 | hi def link oreDeclaration Type 11 | 12 | syn keyword oreOperator new delete typeof 13 | 14 | syn keyword oreStatement return break continue throw 15 | syn keyword oreConditional if else switch try catch finally 16 | syn keyword oreLabel case default 17 | syn keyword oreRepeat for while 18 | 19 | hi def link oreOperator Operator 20 | hi def link oreStatement Statement 21 | hi def link oreConditional Conditional 22 | hi def link oreLabel Label 23 | hi def link oreRepeat Repeat 24 | 25 | syn match oreDeclaration /\/ 26 | syn match oreDeclaration /^func\>/ 27 | syn match oreDeclaration /\/ 28 | syn match oreDeclaration /^class\>/ 29 | 30 | syn keyword oreBuiltins keys len 31 | syn keyword oreBuiltins println printf print 32 | syn keyword oreConstants true false nil 33 | 34 | hi def link oreBuiltins Keyword 35 | hi def link oreConstants Keyword 36 | 37 | " Comments; their contents 38 | syn keyword oreTodo contained TODO FIXME XXX BUG 39 | syn cluster oreCommentGroup contains=oreTodo 40 | syn region oreComment start="#" end="$" contains=@oreCommentGroup,@Spell 41 | 42 | hi def link oreComment Comment 43 | hi def link oreTodo Todo 44 | 45 | " ore escapes 46 | syn match oreEscapeOctal display contained "\\[0-7]\{3}" 47 | syn match oreEscapeC display contained +\\[abfnrtv\\'"]+ 48 | syn match oreEscapeX display contained "\\x\x\{2}" 49 | syn match oreEscapeU display contained "\\u\x\{4}" 50 | syn match oreEscapeBigU display contained "\\U\x\{8}" 51 | syn match oreEscapeError display contained +\\[^0-7xuUabfnrtv\\'"]+ 52 | 53 | hi def link oreEscapeOctal oreSpecialString 54 | hi def link oreEscapeC oreSpecialString 55 | hi def link oreEscapeX oreSpecialString 56 | hi def link oreEscapeU oreSpecialString 57 | hi def link oreEscapeBigU oreSpecialString 58 | hi def link oreSpecialString Special 59 | hi def link oreEscapeError Error 60 | 61 | " Strings and their contents 62 | syn cluster oreStringGroup contains=oreEscapeOctal,oreEscapeC,oreEscapeX,oreEscapeU,oreEscapeBigU,oreEscapeError 63 | syn region oreString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@oreStringGroup 64 | syn region oreRawString start=+`+ end=+`+ 65 | 66 | hi def link oreString String 67 | hi def link oreRawString String 68 | 69 | " Characters; their contents 70 | syn cluster oreCharacterGroup contains=oreEscapeOctal,oreEscapeC,oreEscapeX,oreEscapeU,oreEscapeBigU 71 | syn region oreCharacter start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=@oreCharacterGroup 72 | 73 | hi def link oreCharacter Character 74 | 75 | " Regions 76 | syn region oreBlock start="{" end="}" transparent fold 77 | syn region oreParen start='(' end=')' transparent 78 | 79 | " Integers 80 | syn match oreDecimalInt "\<\d\+\([Ee]\d\+\)\?\>" 81 | syn match oreHexadecimalInt "\<0x\x\+\>" 82 | syn match oreOctalInt "\<0\o\+\>" 83 | syn match oreOctalError "\<0\o*[89]\d*\>" 84 | 85 | hi def link oreDecimalInt Integer 86 | hi def link oreHexadecimalInt Integer 87 | hi def link oreOctalInt Integer 88 | hi def link Integer Number 89 | 90 | " Floating point 91 | syn match oreFloat "\<\d\+\.\d*\([Ee][-+]\d\+\)\?\>" 92 | syn match oreFloat "\<\.\d\+\([Ee][-+]\d\+\)\?\>" 93 | syn match oreFloat "\<\d\+[Ee][-+]\d\+\>" 94 | 95 | hi def link oreFloat Float 96 | hi def link oreImaginary Number 97 | 98 | syn sync minlines=500 99 | 100 | let b:current_syntax = "ore" 101 | -------------------------------------------------------------------------------- /mpc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** mpc - Micro Parser Combinator library for C 3 | ** 4 | ** https://github.com/orangeduck/mpc 5 | ** 6 | ** Daniel Holden - contact@daniel-holden.com 7 | ** Licensed under BSD3 8 | */ 9 | 10 | #ifndef mpc_h 11 | #define mpc_h 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | /* 22 | ** State Type 23 | */ 24 | 25 | typedef struct { 26 | long pos; 27 | long row; 28 | long col; 29 | } mpc_state_t; 30 | 31 | /* 32 | ** Error Type 33 | */ 34 | 35 | typedef struct { 36 | mpc_state_t state; 37 | int expected_num; 38 | char *filename; 39 | char *failure; 40 | char **expected; 41 | char recieved; 42 | } mpc_err_t; 43 | 44 | void mpc_err_delete(mpc_err_t *e); 45 | char *mpc_err_string(mpc_err_t *e); 46 | void mpc_err_print(mpc_err_t *e); 47 | void mpc_err_print_to(mpc_err_t *e, FILE *f); 48 | 49 | /* 50 | ** Parsing 51 | */ 52 | 53 | typedef void mpc_val_t; 54 | 55 | typedef union { 56 | mpc_err_t *error; 57 | mpc_val_t *output; 58 | } mpc_result_t; 59 | 60 | struct mpc_parser_t; 61 | typedef struct mpc_parser_t mpc_parser_t; 62 | 63 | int mpc_parse(const char *filename, const char *string, mpc_parser_t *p, mpc_result_t *r); 64 | int mpc_parse_file(const char *filename, FILE *file, mpc_parser_t *p, mpc_result_t *r); 65 | int mpc_parse_pipe(const char *filename, FILE *pipe, mpc_parser_t *p, mpc_result_t *r); 66 | int mpc_parse_contents(const char *filename, mpc_parser_t *p, mpc_result_t *r); 67 | 68 | /* 69 | ** Function Types 70 | */ 71 | 72 | typedef void(*mpc_dtor_t)(mpc_val_t*); 73 | typedef mpc_val_t*(*mpc_ctor_t)(void); 74 | 75 | typedef mpc_val_t*(*mpc_apply_t)(mpc_val_t*); 76 | typedef mpc_val_t*(*mpc_apply_to_t)(mpc_val_t*,void*); 77 | typedef mpc_val_t*(*mpc_fold_t)(int,mpc_val_t**); 78 | 79 | /* 80 | ** Building a Parser 81 | */ 82 | 83 | mpc_parser_t *mpc_new(const char *name); 84 | mpc_parser_t *mpc_copy(mpc_parser_t *a); 85 | mpc_parser_t *mpc_define(mpc_parser_t *p, mpc_parser_t *a); 86 | mpc_parser_t *mpc_undefine(mpc_parser_t *p); 87 | 88 | void mpc_delete(mpc_parser_t *p); 89 | void mpc_cleanup(int n, ...); 90 | 91 | /* 92 | ** Basic Parsers 93 | */ 94 | 95 | mpc_parser_t *mpc_any(void); 96 | mpc_parser_t *mpc_char(char c); 97 | mpc_parser_t *mpc_range(char s, char e); 98 | mpc_parser_t *mpc_oneof(const char *s); 99 | mpc_parser_t *mpc_noneof(const char *s); 100 | mpc_parser_t *mpc_satisfy(int(*f)(char)); 101 | mpc_parser_t *mpc_string(const char *s); 102 | 103 | /* 104 | ** Other Parsers 105 | */ 106 | 107 | mpc_parser_t *mpc_pass(void); 108 | mpc_parser_t *mpc_fail(const char *m); 109 | mpc_parser_t *mpc_failf(const char *fmt, ...); 110 | mpc_parser_t *mpc_lift(mpc_ctor_t f); 111 | mpc_parser_t *mpc_lift_val(mpc_val_t *x); 112 | mpc_parser_t *mpc_anchor(int(*f)(char,char)); 113 | mpc_parser_t *mpc_state(void); 114 | 115 | /* 116 | ** Combinator Parsers 117 | */ 118 | 119 | mpc_parser_t *mpc_expect(mpc_parser_t *a, const char *e); 120 | mpc_parser_t *mpc_expectf(mpc_parser_t *a, const char *fmt, ...); 121 | mpc_parser_t *mpc_apply(mpc_parser_t *a, mpc_apply_t f); 122 | mpc_parser_t *mpc_apply_to(mpc_parser_t *a, mpc_apply_to_t f, void *x); 123 | 124 | mpc_parser_t *mpc_not(mpc_parser_t *a, mpc_dtor_t da); 125 | mpc_parser_t *mpc_not_lift(mpc_parser_t *a, mpc_dtor_t da, mpc_ctor_t lf); 126 | mpc_parser_t *mpc_maybe(mpc_parser_t *a); 127 | mpc_parser_t *mpc_maybe_lift(mpc_parser_t *a, mpc_ctor_t lf); 128 | 129 | mpc_parser_t *mpc_many(mpc_fold_t f, mpc_parser_t *a); 130 | mpc_parser_t *mpc_many1(mpc_fold_t f, mpc_parser_t *a); 131 | mpc_parser_t *mpc_count(int n, mpc_fold_t f, mpc_parser_t *a, mpc_dtor_t da); 132 | 133 | mpc_parser_t *mpc_or(int n, ...); 134 | mpc_parser_t *mpc_and(int n, mpc_fold_t f, ...); 135 | 136 | mpc_parser_t *mpc_predictive(mpc_parser_t *a); 137 | 138 | /* 139 | ** Common Parsers 140 | */ 141 | 142 | mpc_parser_t *mpc_eoi(void); 143 | mpc_parser_t *mpc_soi(void); 144 | 145 | mpc_parser_t *mpc_boundary(void); 146 | 147 | mpc_parser_t *mpc_whitespace(void); 148 | mpc_parser_t *mpc_whitespaces(void); 149 | mpc_parser_t *mpc_blank(void); 150 | 151 | mpc_parser_t *mpc_newline(void); 152 | mpc_parser_t *mpc_tab(void); 153 | mpc_parser_t *mpc_escape(void); 154 | 155 | mpc_parser_t *mpc_digit(void); 156 | mpc_parser_t *mpc_hexdigit(void); 157 | mpc_parser_t *mpc_octdigit(void); 158 | mpc_parser_t *mpc_digits(void); 159 | mpc_parser_t *mpc_hexdigits(void); 160 | mpc_parser_t *mpc_octdigits(void); 161 | 162 | mpc_parser_t *mpc_lower(void); 163 | mpc_parser_t *mpc_upper(void); 164 | mpc_parser_t *mpc_alpha(void); 165 | mpc_parser_t *mpc_underscore(void); 166 | mpc_parser_t *mpc_alphanum(void); 167 | 168 | mpc_parser_t *mpc_int(void); 169 | mpc_parser_t *mpc_hex(void); 170 | mpc_parser_t *mpc_oct(void); 171 | mpc_parser_t *mpc_number(void); 172 | 173 | mpc_parser_t *mpc_real(void); 174 | mpc_parser_t *mpc_float(void); 175 | 176 | mpc_parser_t *mpc_char_lit(void); 177 | mpc_parser_t *mpc_string_lit(void); 178 | mpc_parser_t *mpc_regex_lit(void); 179 | 180 | mpc_parser_t *mpc_ident(void); 181 | 182 | /* 183 | ** Useful Parsers 184 | */ 185 | 186 | mpc_parser_t *mpc_startwith(mpc_parser_t *a); 187 | mpc_parser_t *mpc_endwith(mpc_parser_t *a, mpc_dtor_t da); 188 | mpc_parser_t *mpc_whole(mpc_parser_t *a, mpc_dtor_t da); 189 | 190 | mpc_parser_t *mpc_stripl(mpc_parser_t *a); 191 | mpc_parser_t *mpc_stripr(mpc_parser_t *a); 192 | mpc_parser_t *mpc_strip(mpc_parser_t *a); 193 | mpc_parser_t *mpc_tok(mpc_parser_t *a); 194 | mpc_parser_t *mpc_sym(const char *s); 195 | mpc_parser_t *mpc_total(mpc_parser_t *a, mpc_dtor_t da); 196 | 197 | mpc_parser_t *mpc_between(mpc_parser_t *a, mpc_dtor_t ad, const char *o, const char *c); 198 | mpc_parser_t *mpc_parens(mpc_parser_t *a, mpc_dtor_t ad); 199 | mpc_parser_t *mpc_braces(mpc_parser_t *a, mpc_dtor_t ad); 200 | mpc_parser_t *mpc_brackets(mpc_parser_t *a, mpc_dtor_t ad); 201 | mpc_parser_t *mpc_squares(mpc_parser_t *a, mpc_dtor_t ad); 202 | 203 | mpc_parser_t *mpc_tok_between(mpc_parser_t *a, mpc_dtor_t ad, const char *o, const char *c); 204 | mpc_parser_t *mpc_tok_parens(mpc_parser_t *a, mpc_dtor_t ad); 205 | mpc_parser_t *mpc_tok_braces(mpc_parser_t *a, mpc_dtor_t ad); 206 | mpc_parser_t *mpc_tok_brackets(mpc_parser_t *a, mpc_dtor_t ad); 207 | mpc_parser_t *mpc_tok_squares(mpc_parser_t *a, mpc_dtor_t ad); 208 | 209 | /* 210 | ** Common Function Parameters 211 | */ 212 | 213 | void mpcf_dtor_null(mpc_val_t *x); 214 | 215 | mpc_val_t *mpcf_ctor_null(void); 216 | mpc_val_t *mpcf_ctor_str(void); 217 | 218 | mpc_val_t *mpcf_free(mpc_val_t *x); 219 | mpc_val_t *mpcf_int(mpc_val_t *x); 220 | mpc_val_t *mpcf_hex(mpc_val_t *x); 221 | mpc_val_t *mpcf_oct(mpc_val_t *x); 222 | mpc_val_t *mpcf_float(mpc_val_t *x); 223 | mpc_val_t *mpcf_strtriml(mpc_val_t *x); 224 | mpc_val_t *mpcf_strtrimr(mpc_val_t *x); 225 | mpc_val_t *mpcf_strtrim(mpc_val_t *x); 226 | 227 | mpc_val_t *mpcf_escape(mpc_val_t *x); 228 | mpc_val_t *mpcf_escape_regex(mpc_val_t *x); 229 | mpc_val_t *mpcf_escape_string_raw(mpc_val_t *x); 230 | mpc_val_t *mpcf_escape_char_raw(mpc_val_t *x); 231 | 232 | mpc_val_t *mpcf_unescape(mpc_val_t *x); 233 | mpc_val_t *mpcf_unescape_regex(mpc_val_t *x); 234 | mpc_val_t *mpcf_unescape_string_raw(mpc_val_t *x); 235 | mpc_val_t *mpcf_unescape_char_raw(mpc_val_t *x); 236 | 237 | mpc_val_t *mpcf_null(int n, mpc_val_t** xs); 238 | mpc_val_t *mpcf_fst(int n, mpc_val_t** xs); 239 | mpc_val_t *mpcf_snd(int n, mpc_val_t** xs); 240 | mpc_val_t *mpcf_trd(int n, mpc_val_t** xs); 241 | 242 | mpc_val_t *mpcf_fst_free(int n, mpc_val_t** xs); 243 | mpc_val_t *mpcf_snd_free(int n, mpc_val_t** xs); 244 | mpc_val_t *mpcf_trd_free(int n, mpc_val_t** xs); 245 | 246 | mpc_val_t *mpcf_strfold(int n, mpc_val_t** xs); 247 | mpc_val_t *mpcf_maths(int n, mpc_val_t** xs); 248 | 249 | /* 250 | ** Regular Expression Parsers 251 | */ 252 | 253 | mpc_parser_t *mpc_re(const char *re); 254 | 255 | /* 256 | ** AST 257 | */ 258 | 259 | typedef struct mpc_ast_t { 260 | char *tag; 261 | char *contents; 262 | mpc_state_t state; 263 | int children_num; 264 | struct mpc_ast_t** children; 265 | } mpc_ast_t; 266 | 267 | mpc_ast_t *mpc_ast_new(const char *tag, const char *contents); 268 | mpc_ast_t *mpc_ast_build(int n, const char *tag, ...); 269 | mpc_ast_t *mpc_ast_add_root(mpc_ast_t *a); 270 | mpc_ast_t *mpc_ast_add_child(mpc_ast_t *r, mpc_ast_t *a); 271 | mpc_ast_t *mpc_ast_add_tag(mpc_ast_t *a, const char *t); 272 | mpc_ast_t *mpc_ast_tag(mpc_ast_t *a, const char *t); 273 | mpc_ast_t *mpc_ast_state(mpc_ast_t *a, mpc_state_t s); 274 | 275 | void mpc_ast_delete(mpc_ast_t *a); 276 | void mpc_ast_print(mpc_ast_t *a); 277 | void mpc_ast_print_to(mpc_ast_t *a, FILE *fp); 278 | 279 | int mpc_ast_get_index(mpc_ast_t *ast, const char *tag); 280 | int mpc_ast_get_index_lb(mpc_ast_t *ast, const char *tag, int lb); 281 | mpc_ast_t *mpc_ast_get_child(mpc_ast_t *ast, const char *tag); 282 | mpc_ast_t *mpc_ast_get_child_lb(mpc_ast_t *ast, const char *tag, int lb); 283 | 284 | /* 285 | ** Warning: This function currently doesn't test for equality of the `state` member! 286 | */ 287 | int mpc_ast_eq(mpc_ast_t *a, mpc_ast_t *b); 288 | 289 | mpc_val_t *mpcf_fold_ast(int n, mpc_val_t **as); 290 | mpc_val_t *mpcf_str_ast(mpc_val_t *c); 291 | mpc_val_t *mpcf_state_ast(int n, mpc_val_t **xs); 292 | 293 | mpc_parser_t *mpca_tag(mpc_parser_t *a, const char *t); 294 | mpc_parser_t *mpca_add_tag(mpc_parser_t *a, const char *t); 295 | mpc_parser_t *mpca_root(mpc_parser_t *a); 296 | mpc_parser_t *mpca_state(mpc_parser_t *a); 297 | mpc_parser_t *mpca_total(mpc_parser_t *a); 298 | 299 | mpc_parser_t *mpca_not(mpc_parser_t *a); 300 | mpc_parser_t *mpca_maybe(mpc_parser_t *a); 301 | 302 | mpc_parser_t *mpca_many(mpc_parser_t *a); 303 | mpc_parser_t *mpca_many1(mpc_parser_t *a); 304 | mpc_parser_t *mpca_count(int n, mpc_parser_t *a); 305 | 306 | mpc_parser_t *mpca_or(int n, ...); 307 | mpc_parser_t *mpca_and(int n, ...); 308 | 309 | enum { 310 | MPCA_LANG_DEFAULT = 0, 311 | MPCA_LANG_PREDICTIVE = 1, 312 | MPCA_LANG_WHITESPACE_SENSITIVE = 2 313 | }; 314 | 315 | mpc_parser_t *mpca_grammar(int flags, const char *grammar, ...); 316 | 317 | mpc_err_t *mpca_lang(int flags, const char *language, ...); 318 | mpc_err_t *mpca_lang_file(int flags, FILE *f, ...); 319 | mpc_err_t *mpca_lang_pipe(int flags, FILE *f, ...); 320 | mpc_err_t *mpca_lang_contents(int flags, const char *filename, ...); 321 | 322 | /* 323 | ** Misc 324 | */ 325 | 326 | 327 | void mpc_print(mpc_parser_t *p); 328 | void mpc_optimise(mpc_parser_t *p); 329 | void mpc_stats(mpc_parser_t *p); 330 | 331 | int mpc_test_pass(mpc_parser_t *p, const char *s, const void *d, 332 | int(*tester)(const void*, const void*), 333 | mpc_dtor_t destructor, 334 | void(*printer)(const void*)); 335 | 336 | int mpc_test_fail(mpc_parser_t *p, const char *s, const void *d, 337 | int(*tester)(const void*, const void*), 338 | mpc_dtor_t destructor, 339 | void(*printer)(const void*)); 340 | 341 | 342 | 343 | #endif 344 | -------------------------------------------------------------------------------- /ore.c: -------------------------------------------------------------------------------- 1 | #include "ore.h" 2 | 3 | extern char **environ; 4 | 5 | #define STRUCTURE \ 6 | " \n" \ 7 | "number : /-?([0-9]+(\\.[0-9]*)?(e[0-9]+)?|0x[0-9a-fA-F]+)/ ; \n" \ 8 | "true : \"true\" ; \n" \ 9 | "false : \"false\" ; \n" \ 10 | "nil : \"nil\" ; \n" \ 11 | "factor : '(' ')' \n" \ 12 | " | \n" \ 13 | " | \n" \ 14 | " | \n" \ 15 | " | \n" \ 16 | " | \n" \ 17 | " | \n" \ 18 | " | \n" \ 19 | " | \n" \ 20 | " | \n" \ 21 | " | \n" \ 22 | " | ; \n" \ 23 | "string : /\"(\\\\.|[^\"])*\"/ ; \n" \ 24 | "regexp : /\\/(\\\\.|[^\\/])*\\// ; \n" \ 25 | "item : ('[' ']')+ ; \n" \ 26 | "prop : ('.' )+ ; \n" \ 27 | "cmp : " \ 28 | " (\"!=\" | \"==\" | \"<=\" | \"<\" | \">=\" | \">\" | \"=~\") " \ 29 | " ; \n" \ 30 | "call : '(' ? (',' )* ')' ; \n" \ 31 | "anoncall : '(' ? (',' )* ')' ; \n" \ 32 | "methodcall : '(' ? (',' )* ')' ; \n" \ 33 | "array : '[' ? (',' )* ']' ; \n" \ 34 | "pair : ':' ; \n" \ 35 | "hash : '{' ? (',' )* '}' ; \n" \ 36 | "ident : /[a-zA-Z_][a-zA-Z0-9_]*/ ; \n" \ 37 | "term : ( | | | | " \ 38 | " | | " \ 39 | " | (('*' | '/' | '%' | '+' | '-') )* ) ; \n" \ 40 | "lexp : (('+' | '-') )* ; \n" \ 41 | "let_o : (\"=\" | \"+=\" | \"-=\" | \"*=\" | \"/=\") ; \n" \ 42 | "let_v : ';' ; \n" \ 43 | "let_a : ';' ; \n" \ 44 | "let_p : ';' ; \n" \ 45 | "else_if : \"else\" \"if\" '(' ')' '{' '}' ; \n" \ 46 | "else : \"else\" '{' '}' ; \n" \ 47 | "if_stmt : \"if\" '(' ')' '{' '}' ; \n" \ 48 | "if : * ? ; \n" \ 49 | "while : \"while\" '(' ')' '{' '}' ; \n" \ 50 | "for_in : \"for\" '(' \"in\" ')' '{' '}' ; \n" \ 51 | "var : \"var\" '=' ';' ; \n" \ 52 | "vararg : \"...\" ; \n" \ 53 | "lambda : \"func\" " \ 54 | " '(' ? ( | (',' )*) ')' '{' '}' ; \n" \ 55 | "func : \"func\" " \ 56 | " '(' ? ( | (',' )*) ')' '{' '}' ; \n" \ 57 | "template : ( | )* ; \n" \ 58 | "class : \"class\" '{'