Clean up warnings, update next_body, add more tests
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
36
src/main.rs
36
src/main.rs
@@ -3,9 +3,7 @@ mod syn;
|
|||||||
use std::{
|
use std::{
|
||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
fs,
|
fs,
|
||||||
io::{stdout, Write},
|
path::PathBuf,
|
||||||
path::{Path, PathBuf},
|
|
||||||
process,
|
|
||||||
};
|
};
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
@@ -34,35 +32,7 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
let opt = Options::from_args();
|
let opt = Options::from_args();
|
||||||
let text = fs::read_to_string(&opt.input)?;
|
let text = fs::read_to_string(&opt.input)?;
|
||||||
let parser = Parser::try_from(text.as_str())?;
|
let mut parser = Parser::try_from(text.as_str())?;
|
||||||
/*
|
println!("{:#?}", parser.next_body()?);
|
||||||
let object = assemble::assemble_path(&opt.input)?;
|
|
||||||
|
|
||||||
if opt.compile_only {
|
|
||||||
let outfile = opt.out.clone().unwrap_or_else(|| {
|
|
||||||
let mut outfile = opt.input.clone();
|
|
||||||
assert!(outfile.set_extension("obj"));
|
|
||||||
outfile
|
|
||||||
});
|
|
||||||
let bytes = object.to_bytes();
|
|
||||||
let mut writer = get_writer(&outfile)?;
|
|
||||||
writer.write(&bytes)?;
|
|
||||||
Ok(())
|
|
||||||
} else if opt.disassemble {
|
|
||||||
let outfile = opt
|
|
||||||
.out
|
|
||||||
.as_ref()
|
|
||||||
.map(|p| p.as_path())
|
|
||||||
.unwrap_or_else(|| Path::new("-"));
|
|
||||||
let mut writer = get_writer(&outfile)?;
|
|
||||||
object.disasm(&mut writer)?;
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
let mut state = State::new();
|
|
||||||
state.load_object(object, opt.max_mem.unwrap_or(DEFAULT_MAX_MEM))?;
|
|
||||||
let status = state.exec()?;
|
|
||||||
process::exit((status & 0xffff_ffff) as i32);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ impl<'t> Lexer<'t> {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
let start = self.pos;
|
let start = self.pos;
|
||||||
self.pos.adv_str(token_text);
|
self.pos.adv_str(token_text);
|
||||||
let end = self.pos;
|
let end = self.pos;
|
||||||
|
|||||||
@@ -75,6 +75,20 @@ impl<'t> Parser<'t> {
|
|||||||
// Statement parsing
|
// Statement parsing
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
impl<'t> Parser<'t> {
|
impl<'t> Parser<'t> {
|
||||||
|
/// Gets the remaining list of statements in this file, expecting EOF at the end.
|
||||||
|
pub fn next_body(&mut self) -> Result<Vec<Stmt>> {
|
||||||
|
let body = self.next_block_body()?;
|
||||||
|
if let Some(token) = self.curr_token {
|
||||||
|
return Err(Error::ExpectedGot {
|
||||||
|
expected: "EOF, statement, or expression".to_string(),
|
||||||
|
got: token.kind().to_string(),
|
||||||
|
pos: token.span().start,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(body)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn next_stmt(&mut self) -> Result<Option<Stmt>> {
|
pub fn next_stmt(&mut self) -> Result<Option<Stmt>> {
|
||||||
// skip any leading EOL tokens
|
// skip any leading EOL tokens
|
||||||
while self.match_any_token_kind(&EOL)?.is_some() {}
|
while self.match_any_token_kind(&EOL)?.is_some() {}
|
||||||
@@ -87,7 +101,6 @@ impl<'t> Parser<'t> {
|
|||||||
let expr = self.next_expr()?;
|
let expr = self.next_expr()?;
|
||||||
if self.match_token_kind(TokenKind::Eq)?.is_some() {
|
if self.match_token_kind(TokenKind::Eq)?.is_some() {
|
||||||
let rhs = self.next_expr()?;
|
let rhs = self.next_expr()?;
|
||||||
self.expect_eol_or_eof("end-of-line after assignment")?;
|
|
||||||
let span = expr.span().union(rhs.span());
|
let span = expr.span().union(rhs.span());
|
||||||
Ok(Some(Stmt::Assign(AssignStmt {
|
Ok(Some(Stmt::Assign(AssignStmt {
|
||||||
lhs: expr,
|
lhs: expr,
|
||||||
@@ -95,7 +108,6 @@ impl<'t> Parser<'t> {
|
|||||||
span,
|
span,
|
||||||
})))
|
})))
|
||||||
} else {
|
} else {
|
||||||
// TODO catch EOF
|
|
||||||
self.expect_eol_or_eof("end-of-line after expression")?;
|
self.expect_eol_or_eof("end-of-line after expression")?;
|
||||||
Ok(Some(Stmt::Expr(expr)))
|
Ok(Some(Stmt::Expr(expr)))
|
||||||
}
|
}
|
||||||
@@ -105,18 +117,20 @@ impl<'t> Parser<'t> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a list of statements until it reaches a right curly brace.
|
/// Parses a list of statements until it reaches a right curly brace.
|
||||||
pub fn next_body(&mut self) -> Result<Vec<Stmt>> {
|
fn next_block_body(&mut self) -> Result<Vec<Stmt>> {
|
||||||
let mut body = Vec::new();
|
let mut body = Vec::new();
|
||||||
|
|
||||||
|
// end of body token
|
||||||
if self.is_token_kind(TokenKind::RBrace) {
|
if self.is_token_kind(TokenKind::RBrace) {
|
||||||
// end of body token
|
self.expect_eol_or_eof("end-of-line after assignment")?;
|
||||||
return Ok(body);
|
return Ok(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Some(stmt) = self.next_stmt()? {
|
while let Some(stmt) = self.next_stmt()? {
|
||||||
body.push(stmt);
|
body.push(stmt);
|
||||||
|
|
||||||
|
// end of body token
|
||||||
if self.is_token_kind(TokenKind::RBrace) {
|
if self.is_token_kind(TokenKind::RBrace) {
|
||||||
// end of body token
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,7 +244,10 @@ impl<'t> Parser<'t> {
|
|||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
TokenKind::LBrace => {
|
TokenKind::LBrace => {
|
||||||
let body = self.next_body()?;
|
// turn on newline parsing because we're going to start parsing statements again
|
||||||
|
let prev_skip = self.set_skip_newlines(false)?;
|
||||||
|
let body = self.next_block_body()?;
|
||||||
|
self.set_skip_newlines(prev_skip)?;
|
||||||
let end_token =
|
let end_token =
|
||||||
self.expect_token_kind(TokenKind::RBrace, "end of block (right curly brace)")?;
|
self.expect_token_kind(TokenKind::RBrace, "end of block (right curly brace)")?;
|
||||||
let span = token.span().union(end_token.span());
|
let span = token.span().union(end_token.span());
|
||||||
@@ -266,7 +283,8 @@ impl<'t> Parser<'t> {
|
|||||||
let mut list = self.next_expr_list(TokenKind::RParen)?;
|
let mut list = self.next_expr_list(TokenKind::RParen)?;
|
||||||
|
|
||||||
self.set_skip_newlines(prev_skip)?;
|
self.set_skip_newlines(prev_skip)?;
|
||||||
let end_token = self.expect_token_kind(TokenKind::RParen, "end of tuple")?;
|
let end_token =
|
||||||
|
self.expect_token_kind(TokenKind::RParen, "end of tuple")?;
|
||||||
let span = token.span().union(end_token.span());
|
let span = token.span().union(end_token.span());
|
||||||
list.insert(0, first);
|
list.insert(0, first);
|
||||||
Expr::Base(
|
Expr::Base(
|
||||||
@@ -318,11 +336,18 @@ impl<'t> Parser<'t> {
|
|||||||
// check that the LHS is a tuple of idents, and get the parameters as well.
|
// check that the LHS is a tuple of idents, and get the parameters as well.
|
||||||
let mut params: Vec<String>;
|
let mut params: Vec<String>;
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Base(BaseExpr { kind: BaseExprKind::Tuple(ref tuple), .. }) => {
|
Expr::Base(BaseExpr {
|
||||||
|
kind: BaseExprKind::Tuple(ref tuple),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
// Multi-parameter case
|
// Multi-parameter case
|
||||||
params = Vec::with_capacity(tuple.len());
|
params = Vec::with_capacity(tuple.len());
|
||||||
for param_expr in tuple.iter() {
|
for param_expr in tuple.iter() {
|
||||||
if let Expr::Base(BaseExpr { kind: BaseExprKind::Ident, span, }) = ¶m_expr {
|
if let Expr::Base(BaseExpr {
|
||||||
|
kind: BaseExprKind::Ident,
|
||||||
|
span,
|
||||||
|
}) = ¶m_expr
|
||||||
|
{
|
||||||
let name = span.text_at(self.lexer.text());
|
let name = span.text_at(self.lexer.text());
|
||||||
params.push(name.to_string());
|
params.push(name.to_string());
|
||||||
} else {
|
} else {
|
||||||
@@ -335,7 +360,10 @@ impl<'t> Parser<'t> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Base(BaseExpr { kind: BaseExprKind::Ident, span }) => {
|
Expr::Base(BaseExpr {
|
||||||
|
kind: BaseExprKind::Ident,
|
||||||
|
span,
|
||||||
|
}) => {
|
||||||
// Single parameter case
|
// Single parameter case
|
||||||
params = vec![span.text_at(self.lexer.text()).to_string()]
|
params = vec![span.text_at(self.lexer.text()).to_string()]
|
||||||
}
|
}
|
||||||
@@ -352,13 +380,14 @@ impl<'t> Parser<'t> {
|
|||||||
// function definition
|
// function definition
|
||||||
let rhs = self.next_expr()?;
|
let rhs = self.next_expr()?;
|
||||||
let span = expr.span().union(rhs.span());
|
let span = expr.span().union(rhs.span());
|
||||||
// TODO : get params from tuple expr - it's a little funky to do it at this stage but I
|
Ok(Expr::Fun(
|
||||||
// think it will be fine
|
FunExpr {
|
||||||
Ok(Expr::Fun(FunExpr {
|
params,
|
||||||
params,
|
expr: rhs,
|
||||||
expr: rhs,
|
span,
|
||||||
span,
|
}
|
||||||
}.into()))
|
.into(),
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
}
|
}
|
||||||
@@ -799,54 +828,28 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_fun_expr() {
|
fn test_fun_expr() {
|
||||||
test_parser!(
|
test_parser!(
|
||||||
Parser::try_from(
|
Parser::try_from(r#"() -> ()"#).unwrap(),
|
||||||
r#"() -> ()"#
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
next_expr,
|
next_expr,
|
||||||
fun_expr(
|
fun_expr(vec![], base_expr(BaseExprKind::Tuple(vec![])))
|
||||||
vec![],
|
|
||||||
base_expr(BaseExprKind::Tuple(vec![]))
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
test_parser!(
|
test_parser!(
|
||||||
Parser::try_from(
|
Parser::try_from(r#"() -> 1"#).unwrap(),
|
||||||
r#"() -> 1"#
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
next_expr,
|
next_expr,
|
||||||
fun_expr(
|
fun_expr(vec![], base_expr(BaseExprKind::Num),)
|
||||||
vec![],
|
|
||||||
base_expr(BaseExprKind::Num),
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
test_parser!(
|
test_parser!(
|
||||||
Parser::try_from(
|
Parser::try_from(r#"(a) -> 1"#).unwrap(),
|
||||||
r#"(a) -> 1"#
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
next_expr,
|
next_expr,
|
||||||
fun_expr(
|
fun_expr(vec![String::from("a"),], base_expr(BaseExprKind::Num),)
|
||||||
vec![
|
|
||||||
String::from("a"),
|
|
||||||
],
|
|
||||||
base_expr(BaseExprKind::Num),
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
test_parser!(
|
test_parser!(
|
||||||
Parser::try_from(
|
Parser::try_from(r#"(a, b) -> a + b"#).unwrap(),
|
||||||
r#"(a, b) -> a + b"#
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
next_expr,
|
next_expr,
|
||||||
fun_expr(
|
fun_expr(
|
||||||
vec![
|
vec![String::from("a"), String::from("b"),],
|
||||||
String::from("a"),
|
|
||||||
String::from("b"),
|
|
||||||
],
|
|
||||||
bin_expr(
|
bin_expr(
|
||||||
base_expr(BaseExprKind::Ident),
|
base_expr(BaseExprKind::Ident),
|
||||||
BinOp::Plus,
|
BinOp::Plus,
|
||||||
@@ -1170,6 +1173,38 @@ mod test {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_stray_right_brace_body() {
|
||||||
|
let mut parser = Parser::try_from(
|
||||||
|
r"
|
||||||
|
}
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
parser.next_body().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_block_body() {
|
||||||
|
test_parser!(
|
||||||
|
Parser::try_from(
|
||||||
|
r"
|
||||||
|
a = 1
|
||||||
|
b = :sym
|
||||||
|
foo()
|
||||||
|
"
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
next_block_body,
|
||||||
|
vec![
|
||||||
|
assign_stmt(base_expr(BaseExprKind::Ident), base_expr(BaseExprKind::Num),),
|
||||||
|
assign_stmt(base_expr(BaseExprKind::Ident), base_expr(BaseExprKind::Sym),),
|
||||||
|
Stmt::Expr(fun_call_expr(base_expr(BaseExprKind::Ident), vec![],))
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_assign_stmt() {
|
fn test_assign_stmt() {
|
||||||
test_parser!(
|
test_parser!(
|
||||||
|
|||||||
@@ -49,7 +49,11 @@ impl Pos {
|
|||||||
pub fn next_char(&self, c: char) -> Self {
|
pub fn next_char(&self, c: char) -> Self {
|
||||||
Pos {
|
Pos {
|
||||||
source: self.source + 1,
|
source: self.source + 1,
|
||||||
line: self.line,
|
line: if c == '\n' {
|
||||||
|
self.line + 1
|
||||||
|
} else {
|
||||||
|
self.line
|
||||||
|
},
|
||||||
col: self.col + 1,
|
col: self.col + 1,
|
||||||
byte: self.byte + self.len,
|
byte: self.byte + self.len,
|
||||||
len: c.len_utf8(),
|
len: c.len_utf8(),
|
||||||
|
|||||||
Reference in New Issue
Block a user