Index: example/range_parser.cfa
===================================================================
--- example/range_parser.cfa	(revision 7636fcc64e46f44cabe92d04feda8adb8419968b)
+++ example/range_parser.cfa	(revision 7636fcc64e46f44cabe92d04feda8adb8419968b)
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <fstream.hfa>
+#include <coroutine.hfa>
+
+coroutine RangeParser {
+	const char * text;
+	int com;
+};
+
+void ?{}(RangeParser & this, const char * text) {
+	this.text = text;
+}
+
+static inline void push(RangeParser & this, int val) { this.com = val; suspend; }
+static inline int next(RangeParser & this) { return resume(this).com; }
+
+void main(RangeParser & this) {
+	for() {
+		int start = -1, stop = -1;
+		int start_len = -1, stop_len = -1;
+		int ret = sscanf(this.text, "%u%n-%u%n", &start, &start_len, &stop, &stop_len);
+		switch(ret) {
+		case 0:
+			// Not a range, maybe a comma?
+			if(this.text[0] == ',') {
+				this.text ++;
+				continue;
+			}
+
+			serr | "Error: unexpected character in next range: '" | this.text |"'";
+			exit(2);
+		case 1:
+			// Only one value, push it!
+			push(this, start);
+			this.text += start_len;
+			break;
+		case 2:
+			if(start > stop) {
+				serr | "Error: next range out of order '" | this.text |"'";
+				exit(2);
+			}
+			for(int i = start; i <= stop; i++) {
+				push(this, i);
+			}
+			this.text += stop_len;
+			break;
+		default:
+			serr | "Error reading next block: '" | this.text |"', returned" | ret;
+			exit(2);
+		}
+
+		if(this.text[0] == '\0') break;
+	}
+	this.com = -1;
+}
+
+int main(int argc, char * argv[]) {
+	if(argc != 2) {
+		serr | "Usage:" | argv[0] | "range";
+		return 1;
+	}
+
+	RangeParser rp = { argv[1] };
+
+	for() {
+		int i = next(rp);
+		if(i < 0) break;
+		sout | i | nonl;
+	}
+	sout | nl;
+}
