Add lexer, parser, ast, and basic command line interaction
* Add lexer and parser using lrpar crate * AST is added and constructed via lexer and parser * Command line program `not` will read a file and parse it Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,5 +1,38 @@
|
|||||||
use not_python::syn;
|
use not_python::syn::ast;
|
||||||
|
|
||||||
fn main() {
|
use std::{fs, path::PathBuf};
|
||||||
println!("hell world");
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
|
#[derive(StructOpt, Debug)]
|
||||||
|
struct Options {
|
||||||
|
/// The input file to work with.
|
||||||
|
///
|
||||||
|
/// By default, the file will be executed. If -c is passed, it will not run and only compile.
|
||||||
|
/// Supplying - for the path will read from STDIN.
|
||||||
|
#[structopt(name = "FILE", parse(from_os_str))]
|
||||||
|
input: PathBuf,
|
||||||
|
/*
|
||||||
|
/// Disassemble object that would be passed to VM and exit before running it.
|
||||||
|
#[structopt(short = "d", long)]
|
||||||
|
disassemble: bool,
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let opt = Options::from_args();
|
||||||
|
let text = fs::read_to_string(&opt.input)?;
|
||||||
|
let ast = match ast::parse(text.as_str()) {
|
||||||
|
Ok(ast) => ast,
|
||||||
|
Err(errs) => {
|
||||||
|
for err in errs {
|
||||||
|
eprintln!("{}", err);
|
||||||
|
}
|
||||||
|
return Err("errors reported, exiting".into());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
println!("{:#?}", ast);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,14 +115,16 @@ pub enum Atom {
|
|||||||
String(String),
|
String(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(text: &str) -> Result<Option<Vec<Stmt>>, Vec<lrpar::LexParseError<u32>>> {
|
pub fn parse(text: &str) -> Result<Option<Vec<Stmt>>, Vec<String>> {
|
||||||
use crate::syn::{lexer, parser};
|
use crate::syn::{lexer, parser};
|
||||||
let lexerdef = lexer::lexerdef();
|
let lexerdef = lexer::lexerdef();
|
||||||
let lexer = lexerdef.lexer(text);
|
let lexer = lexerdef.lexer(text);
|
||||||
let (res, errors) = parser::parse(&lexer);
|
let (res, errors) = parser::parse(&lexer);
|
||||||
|
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
return Err(errors)
|
return Err(errors.into_iter()
|
||||||
|
.map(|e| e.pp(&lexer, &parser::token_epp))
|
||||||
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(res.transpose().unwrap())
|
Ok(res.transpose().unwrap())
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
%%
|
%%
|
||||||
[\n;]+ "EOL"
|
[\r\n;]+ "EOL"
|
||||||
[a-zA-Z_][a-zA-Z0-9_]* "IDENT"
|
[a-zA-Z_][a-zA-Z0-9_]* "IDENT"
|
||||||
:[a-zA-Z_][a-zA-Z0-9_]* "SYM"
|
:[a-zA-Z_][a-zA-Z0-9_]* "SYM"
|
||||||
[0-9]+ "NUM"
|
[0-9]+ "NUM"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ Body -> Result<Vec<Stmt>>:
|
|||||||
Body 'EOL' Stmt {
|
Body 'EOL' Stmt {
|
||||||
flatten($1, $3)
|
flatten($1, $3)
|
||||||
}
|
}
|
||||||
|
| Body 'EOL' { $1 }
|
||||||
| Stmt { Ok(vec![$1?]) }
|
| Stmt { Ok(vec![$1?]) }
|
||||||
| { Ok(Vec::new()) }
|
| { Ok(Vec::new()) }
|
||||||
;
|
;
|
||||||
@@ -48,6 +49,9 @@ AccessExpr -> Result<Expr>:
|
|||||||
AtomExpr AccessExprTail {
|
AtomExpr AccessExprTail {
|
||||||
Ok(AccessExpr::new_expr($1?, $2?))
|
Ok(AccessExpr::new_expr($1?, $2?))
|
||||||
}
|
}
|
||||||
|
| AtomExpr {
|
||||||
|
Ok(AccessExpr::new_expr($1?, Default::default()))
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
AccessExprTail -> Result<Vec<Access>>:
|
AccessExprTail -> Result<Vec<Access>>:
|
||||||
|
|||||||
Reference in New Issue
Block a user