Implement lexer skeleton for cclox

This commit is contained in:
Abdelrahman Said 2025-06-07 23:38:47 +01:00
parent 84fbf3d138
commit 16b544bb85
7 changed files with 179 additions and 3 deletions

View File

@ -1,6 +1,75 @@
#include <cstdio>
#include "token.hh"
#include "scanner.hh"
#include <iostream>
#include <fstream>
#include <string>
#include <sysexits.h>
#include <cstdint>
#include <vector>
#define PROMPT "> "
static bool had_error = false;
void run_file(const char *path);
void run_prompt();
void run(const std::string &code);
void error(int line, const std::string &message);
void report(int line, const std::string &where, const std::string &message);
int main(int argc, char *argv[]) {
if (argc > 2) {
std::cout << "Usage: cclox [script]\n";
exit(EX_USAGE);
}
if (argc == 2) {
run_file(argv[1]);
} else {
run_prompt();
}
int main() {
printf("Hello from cclox\n");
return 0;
}
void run_file(const char *path) {
if (std::ifstream source_code{path, std::ios::ate}) {
uint64_t size = source_code.tellg();
std::string code(size, '\0');
source_code.seekg(0);
source_code.read(&code[0], size);
run(code);
if (had_error) {
exit(EX_DATAERR);
}
}
}
void run_prompt() {
std::string line{};
std::cout << PROMPT;
while (std::getline(std::cin, line)) {
run(line);
std::cout << PROMPT;
had_error = false;
}
}
void run(const std::string &code) {
Scanner scanner{code};
std::vector<Token> tokens = scanner.scan_tokens();
for (auto token : tokens) {
std::cout << token << '\n';
}
}
void error(int line, const std::string &message) {
report(line, "", message);
}
void report(int line, const std::string &where, const std::string &message) {
std::cout << "[line " << line << "] Error" << where << ": " << message << '\n';
had_error = true;
}

18
cclox_src/object.cc Normal file
View File

@ -0,0 +1,18 @@
#include "object.hh"
void Identifier::write(std::ostream &os) const {
os << identifier;
};
void StringLit::write(std::ostream &os) const {
os << literal;
};
void Number::write(std::ostream &os) const {
os << number;
};
std::ostream &operator<<(std::ostream &os, const Object &obj) {
obj.write(os);
return os;
}

27
cclox_src/object.hh Normal file
View File

@ -0,0 +1,27 @@
#pragma once
#include <string>
#include <iostream>
struct Object {
Object() = delete;
virtual ~Object() = default;
virtual void write(std::ostream &os) const = 0;
};
struct Identifier : public Object {
virtual void write(std::ostream &os) const final;
std::string identifier;
};
struct StringLit : public Object {
virtual void write(std::ostream &os) const final;
std::string literal;
};
struct Number : public Object {
virtual void write(std::ostream &os) const final;
double number;
};
std::ostream &operator<<(std::ostream &os, const Object &obj);

7
cclox_src/scanner.cc Normal file
View File

@ -0,0 +1,7 @@
#include "scanner.hh"
#include "token.hh"
#include <vector>
std::vector<Token> Scanner::scan_tokens() {
return std::vector<Token>{};
}

11
cclox_src/scanner.hh Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include "token.hh"
#include <vector>
struct Scanner {
Scanner(const std::string &code) : code{code} {};
std::vector<Token> scan_tokens();
std::string code;
};

5
cclox_src/token.cc Normal file
View File

@ -0,0 +1,5 @@
#include "token.hh"
std::ostream &operator<<(std::ostream &os, const Token &token) {
return os << uint8_t(token.type) << ' ' << token.lexeme << ' ' << token.literal;
}

39
cclox_src/token.hh Normal file
View File

@ -0,0 +1,39 @@
#pragma once
#include "object.hh"
#include <cstdint>
#include <string>
enum class TokenType : uint8_t {
// Single-character tokens.
LEFT_PAREN, RIGHT_PAREN, LEFT_BRACE, RIGHT_BRACE,
COMMA, DOT, MINUS, PLUS, SEMICOLON, SLASH, STAR,
// One or two character tokens.
BANG, BANG_EQUAL,
EQUAL, EQUAL_EQUAL,
GREATER, GREATER_EQUAL,
LESS, LESS_EQUAL,
// Literals.
IDENTIFIER, STRING, NUMBER,
// Keywords.
AND, CLASS, ELSE, FALSE, FUN, FOR, IF, NIL, OR,
PRINT, RETURN, SUPER, THIS, TRUE, VAR, WHILE,
EOFILE,
};
struct Token {
Token(TokenType type, const std::string &lexeme, Object &literal, int line)
: type{type}, lexeme{lexeme}, literal{literal}, line{line}
{};
TokenType type;
std::string lexeme;
Object &literal;
int line;
};
std::ostream &operator<<(std::ostream &os, const Token &token);