Implement lexer skeleton for cclox
This commit is contained in:
		@@ -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);
 | 
				
			||||||
		Reference in New Issue
	
	Block a user