Rewrite to Java, add Scanner, TokenTypes, and Main class
This commit is contained in:
parent
8c05ed5835
commit
449ce575a7
|
|
@ -1,2 +1,6 @@
|
||||||
# CobaltScript
|
# Cobalt
|
||||||
A small programming language designed for general purpose scripting and for learning interpreter design
|
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