Clean up warnings, update next_body, add more tests

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-05-08 16:19:01 -04:00
parent 378bcef40b
commit e233ff1cfc
4 changed files with 95 additions and 85 deletions

View File

@@ -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(())
} }

View File

@@ -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;

View File

@@ -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, }) = &param_expr { if let Expr::Base(BaseExpr {
kind: BaseExprKind::Ident,
span,
}) = &param_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!(

View File

@@ -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(),