rott/dev_tests/src/temp.rs

130 lines
3.7 KiB
Rust

//! src/main.rs
//! --------------------------------------------
//! Build & run:
//! cargo run
//! --------------------------------------------
use std::env;
use std::fs;
use std::io::{self, Read, Write};
use std::path::Path;
use rottlib::arena::Arena;
use rottlib::lexer::TokenizedFile;
use rottlib::parser::{ParseError, Parser, pretty::ExprTree};
/*
- Convenient array definitions: [1, 3, 5, 2, 4]
- Boolean dynamic arrays
- Structures in default properties
- Auto conversion of arrays into strings
- Making 'var' and 'local' unnecessary
- Allowing variable creation in 'for' loops
- Allowing variable creation at any place inside a function
- Default parameters for functions
- Function overloading?
- repeat/until
- The syntax of the default properties block is pretty strict for an arcane reason. Particularly adding spaces before or after the "=" will lead to errors in pre-UT2003 versions.
- Scopes
- different names for variables and in config file
- anonymous pairs (objects?) and value destruction
>>> AST > HIR > MIR > byte code
*/
/// Closest plan:
/// - Add top-level declaration parsing
/// - Handle pretty.rs shit somehow
/// - COMMITS
/// ---------------------------------------
/// - Add fancy error reporting
/// - Make a fancy REPL
/// - Add evaluation
///
/// WARNINGS:
/// - Empty code/switch blocks
fn parse_and_print(src: &str) -> Result<(), ParseError> {
let tokenized = TokenizedFile::from_str(src);
let arena = Arena::new();
let mut parser = Parser::new(&tokenized, &arena);
let expr = parser.parse_expression(); // ArenaNode<Expression>
println!("{}", ExprTree(&*expr)); // if ArenaNode<Deref>
// or: println!("{}", ExprTree(expr.as_ref())); // if no Deref
Ok(())
}
fn repl_once() -> Result<(), ParseError> {
print!("Enter an statement > ");
io::stdout().flush().unwrap();
let mut input = String::new();
if io::stdin().read_line(&mut input).is_err() {
eprintln!("failed to read input");
return Ok(());
}
if input.trim().is_empty() {
return Ok(());
}
parse_and_print(&input)
}
fn read_stdin_all() -> io::Result<String> {
let mut buf = String::new();
io::stdin().read_to_string(&mut buf)?;
Ok(buf)
}
fn read_file_to_string(path: &Path) -> io::Result<String> {
fs::read_to_string(path)
}
fn main() -> Result<(), ParseError> {
// Accept a single positional arg as the input path.
// "-" means read all of stdin.
let mut args = env::args().skip(1);
if let Some(arg1) = args.next() {
if arg1 == "-h" || arg1 == "--help" {
println!("Usage:");
println!(
" {} # REPL",
env::args().next().unwrap_or_else(|| "prog".into())
);
println!(
" {} <file> # parse file",
env::args().next().unwrap_or_else(|| "prog".into())
);
println!(
" {} - # read source from stdin",
env::args().next().unwrap_or_else(|| "prog".into())
);
return Ok(());
}
if arg1 == "-" {
match read_stdin_all() {
Ok(src) => return parse_and_print(&src),
Err(e) => {
eprintln!("stdin read error: {}", e);
return Ok(());
}
}
} else {
let path = Path::new(&arg1);
match read_file_to_string(path) {
Ok(src) => return parse_and_print(&src),
Err(e) => {
eprintln!("file read error ({}): {}", path.display(), e);
return Ok(());
}
}
}
}
// No filename provided -> keep REPL behavior
repl_once()
}