Skip to content
This repository has been archived by the owner on Jun 2, 2020. It is now read-only.

Commit

Permalink
First commit - compiling, scanner partially complete.
Browse files Browse the repository at this point in the history
  • Loading branch information
mcon committed Nov 25, 2018
1 parent 4cc36ac commit 3cbb01f
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "lox-rust"
version = "0.1.0"
authors = ["Matthew Constable <[email protected]>"]

[dependencies]
argparse = "0.2.2"
15 changes: 15 additions & 0 deletions lox-rust.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="RUST_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/benches" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
48 changes: 48 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
extern crate argparse;

use std::io::{self, Read};
use argparse::{ArgumentParser, Store};
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
mod scanner;

fn main() {
let mut file_name = String::new();

{
let mut ap = ArgumentParser::new();
ap.set_description("Execute code written in lox");
ap.refer(&mut file_name)
.add_argument("file", Store, "File containing lox code to run");
ap.parse_args_or_exit();
}
match file_name.len() {
0 => run_prompt(),
_ => run_file(&file_name)
}
}

fn run_prompt() {
let stdin = io::stdin();
for line in stdin.lock().lines() {
let line = line.unwrap();
println!("> {}", line);
run(line);
}
}

fn run_file(source_file: &String) {
let file = File::open(source_file).expect("failed to open file");

let mut buf_reader = BufReader::new(file);
let mut contents = String::new();
buf_reader.read_to_string(&mut contents).expect("failed to read file contents to buffer");

println!("contents: {}", contents);
run(contents);
}

fn run(source: String) {

}
102 changes: 102 additions & 0 deletions src/scanner.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#[allow(dead_code)]
#[derive(Clone)]
pub enum TokenType {
// Single-character tokens.
LeftParen,
RightParen,
LeftBrace,
RightBrace,
COMMA, DOT, MINUS, PLUS, SEMICOLON, SLASH, STAR,

// One or two character tokens.
BANG,
BangEqual,
EQUAL,
EqualEqual,
GREATER,
GreaterEqual,
LESS,
LessEqual,

// Literals.
IDENTIFIER, STRING, NUMBER,

// Keywords.
AND, CLASS, ELSE, FALSE, FUN, FOR, IF, NIL, OR,
PRINT, RETURN, SUPER, THIS, TRUE, VAR, WHILE,

EOF
}
#[warn(dead_code)]

impl TokenType {
fn source_from_char (source: char) -> Result<TokenType, String> {
match source {
'(' => Ok(TokenType::LeftParen),
')' => Ok(TokenType::RightParen),
'{' => Ok(TokenType::LeftBrace),
'}' => Ok(TokenType::RightBrace),
',' => Ok(TokenType::COMMA),
'.' => Ok(TokenType::DOT),
'-' => Ok(TokenType::MINUS),
'+' => Ok(TokenType::PLUS),
';' => Ok(TokenType::SEMICOLON),
'*' => Ok(TokenType::STAR),
_ => Err(format!("Token is not valid syntax: {}", source))
}
}
}

#[derive(Clone)]
struct Token {
token_type: TokenType,
lexeme: String,
line: usize
}

struct Scanner {
source: String,
tokens: Vec<Token>
}

impl Scanner {
pub fn new (source: String) -> Scanner
{
Scanner{
source: source,
tokens: Vec::new()
}
}
pub fn scan_tokens(&mut self) -> Vec<Token> {
let mut line = 0;

if !self.tokens.is_empty() {
// TODO: Slight hack for now: am returning copy of tokens in stead of reference.
return self.tokens.to_vec();
}

for (idx, character) in self.source.chars().enumerate() {
match character {
'\n' => line+=1,
_ => {
let token = Scanner::scan_token(format!("{}", character).as_str(), idx);
self.tokens.push(token);

}
}
}
self.tokens.push(Token{token_type: TokenType::EOF, lexeme: String::new(), line: line});

return self.tokens.to_vec();
// TODO: Should return errors from this function as a vector to be handled by parent code - print for now.
}

pub fn scan_token(remaining_source: &str, line: usize) -> Token {
let character = remaining_source.chars().next().expect("Sholudn't be at end");
Token {
token_type: TokenType::source_from_char(character).expect(format!("Token: '{}' on line {} should be valid", character, line).as_str()),
lexeme: format!("{}", character),
line: line
}
}
}
1 change: 1 addition & 0 deletions test.lox
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
barbaz

0 comments on commit 3cbb01f

Please sign in to comment.