1
+ // Lexer is a classical example of usecase for coroutines.
2
+ // This is a *very* simple and basic lexer that
3
+ // can lex single digit integers, + and -.
4
+ // The example would be better if we could return values
5
+ // when we yield (kind of like a generator). But it is what it is.
6
+
7
+ #include <stdio.h>
8
+ #include <assert.h>
9
+ #include <stdbool.h>
10
+
11
+ #include <coroutine.h>
12
+
13
+ typedef enum {
14
+ TK_INT ,
15
+ TK_OP ,
16
+ TK_EOF
17
+ } TokenKind ;
18
+
19
+ typedef union {
20
+ char tk_op ;
21
+ int tk_int ;
22
+ } TokenValue ;
23
+
24
+ TokenKind token_kind = TK_EOF ;
25
+ TokenValue token_value = {0 };
26
+
27
+ void lex (void * input_void ) {
28
+ if (input_void == NULL ) return ;
29
+
30
+ const char * input = input_void ;
31
+
32
+ while (true) {
33
+ switch (* input ) {
34
+ // Numba
35
+ case '0' : case '1' : case '2' : case '3' : case '4' :
36
+ case '5' : case '6' : case '7' : case '8' : case '9' : {
37
+ token_kind = TK_INT ;
38
+ token_value .tk_int = * input - '0' ;
39
+ } break ;
40
+
41
+ // Operators
42
+ case '+' : case '-' : {
43
+ token_kind = TK_OP ;
44
+ token_value .tk_op = * input ;
45
+ } break ;
46
+
47
+ default : {
48
+ token_kind = TK_EOF ;
49
+ return ;
50
+ }
51
+ }
52
+ input ++ ;
53
+
54
+ // For every token we consume, we yield control back to the caller (a parser, I guess).
55
+ coroutine_yield ();
56
+ }
57
+ }
58
+
59
+ int main (int argc , char * argv []){
60
+ if (argc != 2 ) {
61
+ printf ("Usage: %s <input-text>\n" , argv [1 ]);
62
+ return 1 ;
63
+ }
64
+
65
+ coroutine_init ();
66
+ {
67
+ coroutine_go (lex , argv [1 ]);
68
+
69
+ // Consume those tokens
70
+ bool quit = false;
71
+ while (!quit && coroutine_alive () > 1 ){
72
+ // Yield control to the lexer.
73
+ // It will lex and yield control back to here.
74
+ coroutine_yield ();
75
+ switch (token_kind ){
76
+ case TK_INT : { printf ("TK_INT: %d\n" , token_value .tk_int ); } break ;
77
+ case TK_OP : { printf ("TK_OP: %c\n" , token_value .tk_op ); } break ;
78
+ default : { printf ("Done!\n" ); quit = true; } break ;
79
+ }
80
+ }
81
+ }
82
+ coroutine_finish ();
83
+
84
+ return 0 ;
85
+ }
0 commit comments