diff options
author | Rico Sennrich <rico.sennrich@gmx.ch> | 2014-01-16 22:38:23 +0400 |
---|---|---|
committer | Rico Sennrich <rico.sennrich@gmx.ch> | 2014-01-16 22:45:26 +0400 |
commit | 9e177cb472c0906469291da0aaa6c998b3113b85 (patch) | |
tree | d237b81e41bd0e9c3a98c568b4bb97449098cbb7 /util | |
parent | ed25bb2b99ec3106c4fa186eec3ee1c6b6846b5b (diff) |
SyntaxConstraintFeature (without any actual constraints; useful to build/output syntax tree from GHKM tree fragments)
Diffstat (limited to 'util')
-rw-r--r-- | util/generator.hh | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/util/generator.hh b/util/generator.hh new file mode 100644 index 000000000..afa0db611 --- /dev/null +++ b/util/generator.hh @@ -0,0 +1,34 @@ +#pragma once + +// generator/continuation for C++ +// author: Andrew Fedoniouk @ terrainformatica.com +// idea borrowed from: "coroutines in C" Simon Tatham, +// http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html +// BSD license + +template<typename T> + struct _generator + { + T* _stack; + int _line; + _generator():_stack(0), _line(-1) {} + void _push() { T* n = new T; *n = *static_cast<T*>(this); _stack = n; } + bool _pop() { if(!_stack) return false; T* t = _stack; *static_cast<T*>(this) = *_stack; t->_stack = 0; delete t; return true; } + ~_generator() { while(_pop()); } + }; + + #define $generator(NAME) struct NAME : public _generator<NAME> + + #define $emit(T) bool operator()(T& _rv) { \ + if(_line < 0) _line=0; \ + $START: switch(_line) { case 0:; + + #define $stop } _line = 0; if(_pop()) goto $START; return false; } + + #define $restart(WITH) { _push(); _stack->_line = __LINE__; _line=0; WITH; goto $START; case __LINE__:; } + + #define $yield(V) \ + do {\ + _line=__LINE__;\ + _rv = (V); return true; case __LINE__:;\ + } while (0) |