Add cli flags
This commit is contained in:
parent
cd5ec62e42
commit
ede0ca3993
8 changed files with 267 additions and 45 deletions
148
Cargo.lock
generated
148
Cargo.lock
generated
|
@ -26,6 +26,17 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
|
@ -47,6 +58,12 @@ dependencies = [
|
|||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
|
@ -59,6 +76,45 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6aad2534fad53df1cc12519c5cda696dd3e20e6118a027e24054aea14a0bdcbe"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color-eyre"
|
||||
version = "0.6.1"
|
||||
|
@ -90,6 +146,7 @@ dependencies = [
|
|||
name = "crftng-intrprtrs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"color-eyre",
|
||||
"dotenv",
|
||||
"from_variants",
|
||||
|
@ -182,6 +239,27 @@ version = "0.26.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
|
@ -194,6 +272,16 @@ version = "0.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
|
@ -261,6 +349,12 @@ version = "1.10.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "3.3.0"
|
||||
|
@ -273,6 +367,30 @@ version = "0.2.8"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.36"
|
||||
|
@ -353,6 +471,21 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.4"
|
||||
|
@ -446,6 +579,12 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
@ -462,6 +601,15 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
|
|
|
@ -4,6 +4,7 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "3.1.9", features = ["derive"] }
|
||||
color-eyre = "0.6.1"
|
||||
dotenv = "0.15.0"
|
||||
from_variants = "1.0.0"
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
use super::astnode;
|
||||
use super::astnode::{ASTNode, BinaryExpr};
|
||||
use crate::error::ErrorLocationWrapper;
|
||||
use crate::lexer::{token, token::TokenType};
|
||||
|
||||
use std::iter;
|
||||
use std::result::Result as StdResult;
|
||||
|
||||
type Result<T> = StdResult<T, ASTParsingError>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ASTParsingError {
|
||||
pub enum InnerASTParsingError {
|
||||
IncorrectToken(TokenType),
|
||||
UnmatchedBrace,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ASTParsingError {
|
||||
impl std::fmt::Display for InnerASTParsingError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match *self {
|
||||
Self::UnmatchedBrace => write!(f, "Unmatched brace"),
|
||||
|
@ -21,7 +20,10 @@ impl std::fmt::Display for ASTParsingError {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl std::error::Error for ASTParsingError {}
|
||||
impl std::error::Error for InnerASTParsingError {}
|
||||
|
||||
pub type ASTParsingError = ErrorLocationWrapper<InnerASTParsingError>;
|
||||
type Result<T> = StdResult<T, ASTParsingError>;
|
||||
|
||||
pub struct Parser<'a, T: Iterator<Item = token::Token<'a>>> {
|
||||
token_iter: iter::Peekable<T>,
|
||||
|
@ -145,24 +147,28 @@ impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
|
|||
}
|
||||
|
||||
fn primary(&mut self) -> Result<ASTNode> {
|
||||
let node = match self.token_iter.next().map(|it| it.token_type) {
|
||||
Some(TokenType::False) => ASTNode::Literal(astnode::Literal::Bool(false)),
|
||||
Some(TokenType::True) => ASTNode::Literal(astnode::Literal::Bool(true)),
|
||||
Some(TokenType::Int(i)) => ASTNode::Literal(astnode::Literal::Int(i)),
|
||||
Some(TokenType::String(i)) => ASTNode::Literal(astnode::Literal::String(i)),
|
||||
Some(TokenType::Float(f)) => ASTNode::Literal(astnode::Literal::Float(f)),
|
||||
Some(TokenType::LeftParen) => {
|
||||
let expr = self.expression()?;
|
||||
let group = astnode::GroupingExpr::new(Box::new(expr));
|
||||
match self
|
||||
.token_iter
|
||||
.next_if(|v| matches!(v.token_type, TokenType::RightParen))
|
||||
{
|
||||
Some(_) => return Ok(group.into()),
|
||||
None => return Err(ASTParsingError::UnmatchedBrace),
|
||||
let node = match self.token_iter.next() {
|
||||
Some(token) => match token.token_type {
|
||||
TokenType::False => ASTNode::Literal(astnode::Literal::Bool(false)),
|
||||
TokenType::True => ASTNode::Literal(astnode::Literal::Bool(true)),
|
||||
TokenType::Int(i) => ASTNode::Literal(astnode::Literal::Int(i)),
|
||||
TokenType::String(i) => ASTNode::Literal(astnode::Literal::String(i)),
|
||||
TokenType::Float(f) => ASTNode::Literal(astnode::Literal::Float(f)),
|
||||
TokenType::LeftParen => {
|
||||
let expr = self.expression()?;
|
||||
let group = astnode::GroupingExpr::new(Box::new(expr));
|
||||
match self
|
||||
.token_iter
|
||||
.next_if(|v| matches!(v.token_type, TokenType::RightParen))
|
||||
{
|
||||
Some(_) => return Ok(group.into()),
|
||||
None => {
|
||||
return Err(token.location.wrap(InnerASTParsingError::UnmatchedBrace))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(a) => return Err(ASTParsingError::IncorrectToken(a)),
|
||||
a => return Err(token.location.wrap(InnerASTParsingError::IncorrectToken(a))),
|
||||
},
|
||||
None => todo!(),
|
||||
};
|
||||
Ok(node)
|
||||
|
|
|
@ -71,3 +71,9 @@ impl<T: Error> Error for ErrorLocationWrapper<T> {
|
|||
Some(&self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Location<'a> {
|
||||
pub fn wrap<T: Error>(self, err: T) -> ErrorLocationWrapper<T> {
|
||||
ErrorLocationWrapper::new(err, self.into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ impl<'a, 'b> Lexer<'a, 'b> {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn scan_tokens(&mut self) -> Result<Vec<token::Token>, Vec<LexingError>> {
|
||||
pub fn scan_tokens(&mut self) -> Result<Vec<token::Token<'b>>, Vec<LexingError>> {
|
||||
let mut tokens = Vec::new();
|
||||
let mut errors = Vec::new();
|
||||
|
||||
|
|
32
src/lib.rs
32
src/lib.rs
|
@ -3,18 +3,32 @@ pub mod error;
|
|||
pub mod interpreter;
|
||||
pub mod lexer;
|
||||
|
||||
use interpreter::ast_walker::Interpret;
|
||||
use ast::{astnode::ASTNode, parser::ASTParsingError};
|
||||
use interpreter::ast_walker::{Interpret, RuntimeError};
|
||||
use interpreter::types::Value;
|
||||
use lexer::Lexer;
|
||||
use lexer::{token::Token, Lexer, LexingError};
|
||||
|
||||
pub fn lex<'a, 'b>(
|
||||
code: &'a str,
|
||||
file: Option<&'b str>,
|
||||
) -> Result<Vec<Token<'b>>, Vec<LexingError>> {
|
||||
let mut lexer = Lexer::new(code, file);
|
||||
lexer.scan_tokens()
|
||||
}
|
||||
|
||||
pub fn parse(tokens: Vec<Token>) -> Result<Vec<ASTNode>, Vec<ASTParsingError>> {
|
||||
let mut parser = crate::ast::parser::Parser::new(tokens.into_iter());
|
||||
parser.scan_expressions()
|
||||
}
|
||||
|
||||
pub fn exec(nodes: Vec<ASTNode>) -> Result<Value, RuntimeError> {
|
||||
nodes[0].interpret()
|
||||
}
|
||||
|
||||
pub fn run(code: &str) -> Result<Value, run::Error> {
|
||||
let mut lexer = Lexer::new(code, None);
|
||||
let tokens = lexer.scan_tokens()?;
|
||||
|
||||
let mut parser = crate::ast::parser::Parser::new(tokens.into_iter());
|
||||
let expressions = parser.scan_expressions()?;
|
||||
|
||||
Ok(expressions[0].interpret()?)
|
||||
let tokens = lex(code, None)?;
|
||||
let nodes = parse(tokens)?;
|
||||
Ok(exec(nodes)?)
|
||||
}
|
||||
|
||||
mod run {
|
||||
|
|
72
src/main.rs
72
src/main.rs
|
@ -1,15 +1,62 @@
|
|||
use crftng_intrprtrs::run;
|
||||
use std::{fs, io, path};
|
||||
use clap::Parser;
|
||||
use crftng_intrprtrs::{exec, lex, parse};
|
||||
use std::path::PathBuf;
|
||||
use std::{fs, io};
|
||||
use tracing::Level;
|
||||
use tracing_subscriber::{EnvFilter, FmtSubscriber};
|
||||
|
||||
fn run_file(file: &path::Path) -> Result<(), io::Error> {
|
||||
let src = fs::read_to_string(file)?;
|
||||
println!("{:?}", run(&src).unwrap());
|
||||
#[derive(Parser, Debug)]
|
||||
struct Args {
|
||||
#[clap(parse(from_os_str))]
|
||||
file: Option<PathBuf>,
|
||||
|
||||
#[clap(short)]
|
||||
dump_ast: bool,
|
||||
#[clap(short)]
|
||||
no_run: bool,
|
||||
}
|
||||
|
||||
fn run(code: &str, args: &Args) {
|
||||
let src_file = args.file.as_ref().map(|f| f.to_string_lossy().to_string());
|
||||
let tokens = match lex(code, src_file.as_deref()) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
for error in e {
|
||||
println!("{}", error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
let ast = match parse(tokens) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
for error in e {
|
||||
println!("{}", error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if args.dump_ast {
|
||||
for node in &ast {
|
||||
println!("{:?}", node);
|
||||
}
|
||||
}
|
||||
|
||||
if !args.no_run {
|
||||
println!("{:?}", exec(ast));
|
||||
}
|
||||
}
|
||||
|
||||
fn run_file(args: &Args) -> Result<(), io::Error> {
|
||||
let src = fs::read_to_string(args.file.as_ref().unwrap())?;
|
||||
run(&src, args);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_repl() {
|
||||
fn run_repl(args: &Args) {
|
||||
assert!(args.file.is_none());
|
||||
|
||||
let mut line_buf = String::new();
|
||||
loop {
|
||||
match io::stdin().read_line(&mut line_buf) {
|
||||
|
@ -21,10 +68,7 @@ fn run_repl() {
|
|||
|
||||
let line = line_buf.trim();
|
||||
if !line.is_empty() {
|
||||
match run(line) {
|
||||
Ok(v) => println!("{:?}", v),
|
||||
Err(e) => println!("{}", e),
|
||||
}
|
||||
run(&line_buf, args);
|
||||
line_buf.clear();
|
||||
}
|
||||
}
|
||||
|
@ -43,9 +87,11 @@ fn main() {
|
|||
|
||||
tracing::subscriber::set_global_default(subscriber).unwrap();
|
||||
|
||||
if let Some(file) = std::env::args_os().nth(1) {
|
||||
run_file(file.as_ref()).unwrap();
|
||||
let args = Args::parse();
|
||||
|
||||
if args.file.is_some() {
|
||||
run_file(&args).unwrap();
|
||||
} else {
|
||||
run_repl()
|
||||
run_repl(&args)
|
||||
}
|
||||
}
|
||||
|
|
1
test.lox
Normal file
1
test.lox
Normal file
|
@ -0,0 +1 @@
|
|||
1 == 1;
|
Loading…
Reference in a new issue