Implement lexer skeleton for cclox
This commit is contained in:
parent
84fbf3d138
commit
16b544bb85
@ -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;
|
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
18
cclox_src/object.cc
Normal 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
27
cclox_src/object.hh
Normal 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
7
cclox_src/scanner.cc
Normal 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
11
cclox_src/scanner.hh
Normal 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
5
cclox_src/token.cc
Normal 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
39
cclox_src/token.hh
Normal 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);
|
Loading…
x
Reference in New Issue
Block a user