Skip to content

Commit c8ede46

Browse files
authored
Merge pull request #9 from felipe-bonato/lexer-example
Add lexer example
2 parents 9dc227c + 6082325 commit c8ede46

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ build/counter: examples/counter.c coroutine.h build/coroutine.a
22
gcc -I. -Wall -Wextra -ggdb -o build/counter examples/counter.c build/coroutine.a
33

44
.PHONY: examples
5-
examples: build/counter build/counter_cpp build/counter_c3 build/counter_jai build/echo
5+
examples: build/counter build/counter_cpp build/counter_c3 build/counter_jai build/echo build/lexer
66

77
build/echo: examples/echo.c3 coroutine.c3 build/coroutine.a
88
c3c compile -l build/coroutine.a -o build/echo examples/echo.c3 coroutine.c3
@@ -16,6 +16,9 @@ build/counter_c3: examples/counter.c3 coroutine.c3 build/coroutine.a
1616
build/counter_jai: examples/counter.jai build/coroutine.a build/coroutine.so
1717
jai-linux examples/counter.jai
1818

19+
build/lexer: examples/lexer.c coroutine.h build/coroutine.a
20+
gcc -I. -Wall -Wextra -ggdb -o build/lexer examples/lexer.c build/coroutine.a
21+
1922
build/coroutine.so: coroutine.c
2023
mkdir -p build
2124
gcc -Wall -Wextra -ggdb -shared -fPIC -o build/coroutine.so coroutine.c

examples/lexer.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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[0]);
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

Comments
 (0)