Master the fundamental concepts of lexical analysis through this focused micro-challenge.
Clang, GCC, V8, and Go's gc compiler all scan source with hand-rolled loops like the one you are writing. A lexer walks the input buffer, skips whitespace and comments, classifies the next lexeme, and emits a Token. Flex can generate scanners, but production compilers prefer explicit control for error messages and performance.
The lexer maintains a cursor into the source and repeatedly: skip trivia, peek at the current character, decide what kind of token starts here, consume characters until the lexeme is complete, then return the token with line and column metadata.
cLoading…
= vs ==)Production compilers embed this step inside a longer pipeline. GCC flows through cpp, cc1, assembly, and ld; Clang uses the driver, Sema, LLVM IR passes, and a target backend. LLVM bitcode, JVM bytecode, and WASM are other familiar IRs at the same layer. The exercise isolates one pass so you can test it alone before chaining it to the next stage.
You will implement next_token() and the helper functions that drive a complete scan over a small C-like subset. The task requires a working lexer that emits the token stream your parser will consume, so focus on correct classification and position tracking.
Write the scan loop of a lexer for a small C subset. Your program reads a whole source file from stdin and prints every token it finds, one per line, followed by an end-of-file token.
| Kind | Lexemes |
|---|---|
| Keywords | int return if else while → TOKEN_INT TOKEN_RETURN TOKEN_IF TOKEN_ELSE TOKEN_WHILE |
| Arithmetic | + - * / = → TOKEN_PLUS TOKEN_MINUS TOKEN_STAR TOKEN_SLASH TOKEN_ASSIGN |
| Comparison / logic | == != < > <= >= && || → TOKEN_EQ TOKEN_NE TOKEN_LT TOKEN_GT TOKEN_LE TOKEN_GE TOKEN_AND TOKEN_OR |
| Delimiters | ( ) { } ; , → TOKEN_LPAREN TOKEN_RPAREN TOKEN_LBRACE TOKEN_RBRACE TOKEN_SEMICOLON TOKEN_COMMA |
| Numbers | a run of digits → TOKEN_NUMBER |
| Identifiers | [A-Za-z_][A-Za-z0-9_]* that is not a keyword → TOKEN_IDENTIFIER |
| Anything else | one character → TOKEN_ERROR (e.g. @, a lone !, a lone &) |
Rules:
<= is one TOKEN_LE, not < then =.// starts a comment that runs to the end of the line.12ab is TOKEN_NUMBER '12' then TOKEN_IDENTIFIER 'ab' (the next task turns this into an error).Lines and columns start at 1. A newline moves to the next line, column 1; every other character (including a tab) advances the column by 1. A token's position is the position of its first character.
One line per token:
cLoading…
then a final line with the position just past the last character:
cLoading…
Input:
cLoading…
Output:
cLoading…
(The input ends with a newline, so EOF sits at the start of line 4.)
Lexer struct holding the source, the cursor, and the current line and column.lexer_next_token() skips whitespace and comments, then returns the next Token.main() reads stdin and prints tokens until TOKEN_EOF; you implement the lexer.Hidden tests cover every operator, comments at end of file, tabs, adjacent tokens with no spaces, and empty input.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it works