Rewrite to Java, add Scanner, TokenTypes, and Main class
This commit is contained in:
parent
8c05ed5835
commit
449ce575a7
|
|
@ -1,2 +1,6 @@
|
|||
# CobaltScript
|
||||
A small programming language designed for general purpose scripting and for learning interpreter design
|
||||
# Cobalt
|
||||
Cobalt is a small programming language designed for general purpose and systems level scripting. This project follows very closely to the curriculum from [Crafting Interpreters](http://craftinginterpreters.com/) by Robert Nystrom, and is intended to be a pet project for myself to learn programming language design and interpreter design concepts.
|
||||
|
||||
Currently, Cobalt follows the same grammer and design structure as [Lox](https://github.com/munificent/craftinginterpreters), the language featured in Nystrom's book. However, I eventually plan to mutate Cobalt from these design patterns and create a unique syntax and structure once I have reached a high enough proficiency.
|
||||
|
||||
This project is a **work in progress**, so some things might be a bit broken. YMMV :)
|
||||
|
|
|
|||
68
cobalt/Cobalt.java
Normal file
68
cobalt/Cobalt.java
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package cobalt;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
public class Cobalt {
|
||||
|
||||
static boolean hadError = false;
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
if (args.length > 1) {
|
||||
System.out.println("Usage: cobalt [script]");
|
||||
System.exit(64);
|
||||
} else if (args.length == 1) {
|
||||
//runFile(args[0]);
|
||||
} else {
|
||||
//runPrompt()
|
||||
}
|
||||
}
|
||||
|
||||
private static void runFile(String path) throws IOException {
|
||||
byte[] bytes = Files.readAllBytes(Paths.get(path));
|
||||
run(new String(bytes, Charset.defaultCharset()));
|
||||
if (hadError) System.exit(65);
|
||||
}
|
||||
|
||||
private static void runPrompt() throws IOException {
|
||||
InputStreamReader input = new InputStreamReader(System.in);
|
||||
BufferedReader reader = new BufferedReader(input);
|
||||
|
||||
for (;;) {
|
||||
System.out.print("> ");
|
||||
String line = reader.readLine();
|
||||
if (line == null) break;
|
||||
run(line);
|
||||
hadError = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void run(String source) {
|
||||
// Wont compile since we don't use the standard Java Scanner,
|
||||
// gets implemented further in the textbook
|
||||
Scanner scanner = new Scanner(source);
|
||||
// Same situation for Token type
|
||||
List<Token> tokens = scanner.scanTokens();
|
||||
|
||||
for (Token token : tokens) {
|
||||
System.out.println(token);
|
||||
}
|
||||
}
|
||||
|
||||
static void error(int line, String message) {
|
||||
report(line, "", message);
|
||||
}
|
||||
|
||||
private static void report(int line, String where, String message) {
|
||||
System.err.println(
|
||||
"[line " + line + "] Error" + where + ": " + message
|
||||
);
|
||||
hadError = true;
|
||||
|
||||
}
|
||||
}
|
||||
34
cobalt/Scanner.java
Normal file
34
cobalt/Scanner.java
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
package cobalt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cobalt.TokenType.*;
|
||||
|
||||
class Scanner {
|
||||
private final String source;
|
||||
private final List<Token> tokens = new ArrayList<>();
|
||||
private int start = 0;
|
||||
private int current = 0;
|
||||
private int line = 0;
|
||||
|
||||
Scanner(String source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
List<Token> scanTokens() {
|
||||
while (!isAtEnd()) {
|
||||
start = current;
|
||||
scanTokens();
|
||||
}
|
||||
|
||||
tokens.add(new Token(EOF, "", null, line));
|
||||
return tokens;
|
||||
}
|
||||
|
||||
private boolean isAtEnd() {
|
||||
return current >= source.length();
|
||||
}
|
||||
}
|
||||
19
cobalt/Token.java
Normal file
19
cobalt/Token.java
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package cobalt;
|
||||
|
||||
class Token {
|
||||
final TokenType type;
|
||||
final String lexeme;
|
||||
final Object literal;
|
||||
final int line;
|
||||
|
||||
Token(TokenType type, String lexeme, Object literal, int line) {
|
||||
this.type = type;
|
||||
this.lexeme = lexeme;
|
||||
this.literal = literal;
|
||||
this.line = line;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type + " " + lexeme + " " + literal;
|
||||
}
|
||||
}
|
||||
20
cobalt/TokenType.java
Normal file
20
cobalt/TokenType.java
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package cobalt;
|
||||
|
||||
enum TokenType {
|
||||
// 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,
|
||||
|
||||
EOF
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#include <iostream>
|
||||
|
||||
#ifndef LEXER_H
|
||||
#define LEXER_H
|
||||
|
||||
class Lexer
|
||||
{
|
||||
private:
|
||||
std::string extension = ".prog";
|
||||
public:
|
||||
Lexer(std::string &file_name);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#include <iostream>
|
||||
|
||||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
|
||||
class Parser
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
Parser(std::string input_file);
|
||||
};
|
||||
|
||||
#endif
|
||||
20
makefile
20
makefile
|
|
@ -1,20 +0,0 @@
|
|||
|
||||
#OBJS specifies which files to compile as part of the project
|
||||
OBJS = $(wildcard src/*.cpp)
|
||||
|
||||
#CC specifies which compiler we're using
|
||||
CC = g++
|
||||
|
||||
#COMPILER_FLAGS specifies the additional compilation options we're using
|
||||
# -w suppresses all warnings
|
||||
COMPILER_FLAGS = -w
|
||||
|
||||
#LINKER_FLAGS specifies the libraries we're linking against
|
||||
LINKER_FLAGS =
|
||||
|
||||
#OBJ_NAME specifies the name of our exectuable
|
||||
OBJ_NAME = cobalt
|
||||
|
||||
#This is the target that compiles our executable
|
||||
all : $(OBJS)
|
||||
$(CC) $(OBJS) $(COMPILER_FLAGS) $(LINKER_FLAGS) -o $(OBJ_NAME)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
hello world, this is a lexer test
|
||||
hello world
|
||||
Kanye's new name is Ye
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "../include/lexer.h"
|
||||
|
||||
char c;
|
||||
FILE* input_file;
|
||||
|
||||
Lexer::Lexer(std::string &file_name) {
|
||||
input_file = fopen(file_name.c_str(),"r");
|
||||
if(input_file == nullptr) {
|
||||
std::cout << "[Error] Script " << input_file << " could not be read\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
c = getc(input_file);
|
||||
if (c == EOF) {
|
||||
//do something related to eof here?
|
||||
fclose(input_file);
|
||||
}
|
||||
}
|
||||
|
||||
char nextChar() {
|
||||
if (c != EOF) {
|
||||
c = getc(input_file);
|
||||
} else {
|
||||
c = EOF;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
15
src/main.cpp
15
src/main.cpp
|
|
@ -1,15 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "../include/lexer.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc > 1) {
|
||||
std::string file_name(argv[1]);
|
||||
Lexer lex(file_name);
|
||||
} else {
|
||||
std::cout << "[Error] No input file provided\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "../include/parser.h"
|
||||
|
||||
Parser::Parser(std::string input_file) {
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user