Compare commits
2 Commits
a4b9b958e9
...
56196551b8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56196551b8 | ||
|
|
05a1f5d091 |
43
dm/src/common.rs
Normal file
43
dm/src/common.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
use codespan_reporting::diagnostic::Label;
|
||||||
|
use dmc_lib::diagnostic::Diagnostic;
|
||||||
|
|
||||||
|
pub fn to_csr_diagnostic(
|
||||||
|
file_id: usize,
|
||||||
|
diagnostic: &Diagnostic,
|
||||||
|
) -> codespan_reporting::diagnostic::Diagnostic<usize> {
|
||||||
|
let mut primary_label = Label::primary(file_id, diagnostic.start()..diagnostic.end());
|
||||||
|
if let Some(primary_label_message) = diagnostic.primary_label_message() {
|
||||||
|
primary_label = primary_label.with_message(primary_label_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
let secondary_labels: Vec<Label<usize>> = diagnostic
|
||||||
|
.secondary_labels()
|
||||||
|
.iter()
|
||||||
|
.map(|secondary_label| {
|
||||||
|
let mut label =
|
||||||
|
Label::secondary(file_id, secondary_label.start()..secondary_label.end());
|
||||||
|
if let Some(message) = secondary_label.message() {
|
||||||
|
label = label.with_message(message);
|
||||||
|
}
|
||||||
|
label
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut csr_diagnostic = codespan_reporting::diagnostic::Diagnostic::error()
|
||||||
|
.with_message(diagnostic.message())
|
||||||
|
.with_label(primary_label)
|
||||||
|
.with_labels(secondary_labels);
|
||||||
|
|
||||||
|
if let Some(error_code) = diagnostic.error_code() {
|
||||||
|
csr_diagnostic = csr_diagnostic.with_code(format!("E{:04}", error_code));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((reporter_file, reporter_line)) = diagnostic.reporter() {
|
||||||
|
csr_diagnostic = csr_diagnostic.with_note(format!(
|
||||||
|
"Reported by (Rust) source: {}, line {}",
|
||||||
|
reporter_file, reporter_line
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
csr_diagnostic
|
||||||
|
}
|
||||||
@ -1,9 +1,11 @@
|
|||||||
|
mod common;
|
||||||
mod repl;
|
mod repl;
|
||||||
mod run;
|
mod run;
|
||||||
|
|
||||||
use crate::repl::repl;
|
use crate::repl::repl;
|
||||||
use crate::run::compile_and_run_script;
|
use crate::run::compile_and_run_script;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
@ -47,7 +49,7 @@ fn main() {
|
|||||||
repl(
|
repl(
|
||||||
&mut io::stdin().lock(),
|
&mut io::stdin().lock(),
|
||||||
&mut io::stdout().lock(),
|
&mut io::stdout().lock(),
|
||||||
&mut io::stderr().lock(),
|
&mut StandardStream::stderr(ColorChoice::Always),
|
||||||
register_count,
|
register_count,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
use crate::common::to_csr_diagnostic;
|
||||||
|
use codespan_reporting::files::SimpleFiles;
|
||||||
|
use codespan_reporting::term::{Config, WriteStyle, emit_to_write_style};
|
||||||
use dmc_lib::SyntheticFunctionSession;
|
use dmc_lib::SyntheticFunctionSession;
|
||||||
use dmc_lib::constants_table::ConstantsTable;
|
use dmc_lib::constants_table::ConstantsTable;
|
||||||
use dmc_lib::diagnostic::Diagnostics;
|
use dmc_lib::diagnostic::Diagnostics;
|
||||||
@ -11,9 +14,13 @@ use std::io::{BufRead, Write};
|
|||||||
pub fn repl(
|
pub fn repl(
|
||||||
read: &mut impl BufRead,
|
read: &mut impl BufRead,
|
||||||
out: &mut impl Write,
|
out: &mut impl Write,
|
||||||
err: &mut impl Write,
|
err: &mut impl WriteStyle,
|
||||||
register_count: usize,
|
register_count: usize,
|
||||||
) {
|
) {
|
||||||
|
let diagnostics_config = Config::default();
|
||||||
|
let mut files: SimpleFiles<&str, String> = SimpleFiles::new();
|
||||||
|
let mut current_file_id;
|
||||||
|
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
|
|
||||||
let mut session = SyntheticFunctionSession::new("__repl");
|
let mut session = SyntheticFunctionSession::new("__repl");
|
||||||
@ -48,8 +55,10 @@ pub fn repl(
|
|||||||
.insert(function.name_owned(), function);
|
.insert(function.name_owned(), function);
|
||||||
}
|
}
|
||||||
Err(diagnostics) => {
|
Err(diagnostics) => {
|
||||||
|
current_file_id = files.add("input", String::from(input));
|
||||||
for diagnostic in diagnostics {
|
for diagnostic in diagnostics {
|
||||||
writeln!(err, "{}", diagnostic.message()).unwrap();
|
let csr_diagnostic = to_csr_diagnostic(current_file_id, &diagnostic);
|
||||||
|
emit_to_write_style(err, &diagnostics_config, &files, &csr_diagnostic).unwrap();
|
||||||
}
|
}
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
continue 'repl;
|
continue 'repl;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use codespan_reporting::diagnostic::Label;
|
use crate::common::to_csr_diagnostic;
|
||||||
use codespan_reporting::files::SimpleFiles;
|
use codespan_reporting::files::SimpleFiles;
|
||||||
use codespan_reporting::term;
|
use codespan_reporting::term;
|
||||||
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
||||||
@ -88,43 +88,7 @@ fn report_and_exit(
|
|||||||
let writer = StandardStream::stderr(ColorChoice::Always);
|
let writer = StandardStream::stderr(ColorChoice::Always);
|
||||||
let config = term::Config::default();
|
let config = term::Config::default();
|
||||||
for diagnostic in diagnostics {
|
for diagnostic in diagnostics {
|
||||||
let mut primary_label =
|
let csr_diagnostic = to_csr_diagnostic(script_file_id, diagnostic);
|
||||||
Label::primary(script_file_id, diagnostic.start()..diagnostic.end());
|
|
||||||
if let Some(primary_label_message) = diagnostic.primary_label_message() {
|
|
||||||
primary_label = primary_label.with_message(primary_label_message);
|
|
||||||
}
|
|
||||||
|
|
||||||
let secondary_labels: Vec<Label<usize>> = diagnostic
|
|
||||||
.secondary_labels()
|
|
||||||
.iter()
|
|
||||||
.map(|secondary_label| {
|
|
||||||
let mut label = Label::secondary(
|
|
||||||
script_file_id,
|
|
||||||
secondary_label.start()..secondary_label.end(),
|
|
||||||
);
|
|
||||||
if let Some(message) = secondary_label.message() {
|
|
||||||
label = label.with_message(message);
|
|
||||||
}
|
|
||||||
label
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut csr_diagnostic = codespan_reporting::diagnostic::Diagnostic::error()
|
|
||||||
.with_message(diagnostic.message())
|
|
||||||
.with_label(primary_label)
|
|
||||||
.with_labels(secondary_labels);
|
|
||||||
|
|
||||||
if let Some(error_code) = diagnostic.error_code() {
|
|
||||||
csr_diagnostic = csr_diagnostic.with_code(format!("E{:04}", error_code));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((reporter_file, reporter_line)) = diagnostic.reporter() {
|
|
||||||
csr_diagnostic = csr_diagnostic.with_note(format!(
|
|
||||||
"Reported by (Rust) source: {}, line {}",
|
|
||||||
reporter_file, reporter_line
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
term::emit_to_write_style(&mut writer.lock(), &config, files, &csr_diagnostic).unwrap();
|
term::emit_to_write_style(&mut writer.lock(), &config, files, &csr_diagnostic).unwrap();
|
||||||
}
|
}
|
||||||
if diagnostics.len() == 1 {
|
if diagnostics.len() == 1 {
|
||||||
|
|||||||
@ -62,7 +62,7 @@ pub fn parse_statement(input: &str) -> ParseResult<Option<Statement>> {
|
|||||||
(statement, diagnostics)
|
(statement, diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_expression(input: &str) -> ParseResult<Expression> {
|
pub fn parse_expression(input: &str) -> ParseResult<Option<Expression>> {
|
||||||
let mut parser = Parser::new(input);
|
let mut parser = Parser::new(input);
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
diagnostics.append(&mut parser.advance());
|
diagnostics.append(&mut parser.advance());
|
||||||
@ -918,9 +918,9 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
let initializer = if self.current.is_some() && self.peek_current(TokenKind::Equals) {
|
let initializer = if self.current.is_some() && self.peek_current(TokenKind::Equals) {
|
||||||
diagnostics.append(&mut self.advance()); // equals
|
diagnostics.append(&mut self.advance()); // equals
|
||||||
let (expression, mut ds) = self.expression();
|
let (maybe_expression, mut ds) = self.expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
Some(expression)
|
maybe_expression
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -961,10 +961,7 @@ impl<'a> Parser<'a> {
|
|||||||
Some(let_statement) => (Some(Statement::Let(let_statement)), diagnostics),
|
Some(let_statement) => (Some(Statement::Let(let_statement)), diagnostics),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => self.expression_statement_or_assign_statement(),
|
||||||
let (statement, diagnostics) = self.expression_statement_or_assign_statement();
|
|
||||||
(Some(statement), diagnostics)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -987,65 +984,100 @@ impl<'a> Parser<'a> {
|
|||||||
let (_, mut ds) = self.expect_advance(TokenKind::Equals);
|
let (_, mut ds) = self.expect_advance(TokenKind::Equals);
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
|
||||||
let (expression, mut ds) = self.expression();
|
let (maybe_expression, mut ds) = self.expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
|
||||||
if let Some(identifier) = maybe_identifier {
|
let identifier = match maybe_identifier {
|
||||||
let let_statement = LetStatement::new(
|
Some(identifier) => identifier,
|
||||||
self.next_node_id(),
|
None => {
|
||||||
self.token_text(&identifier),
|
return (None, diagnostics);
|
||||||
SourceRange::new(identifier.start(), identifier.end()),
|
}
|
||||||
is_mut,
|
};
|
||||||
expression,
|
let expression = match maybe_expression {
|
||||||
);
|
Some(expression) => expression,
|
||||||
(Some(let_statement), diagnostics)
|
None => {
|
||||||
} else {
|
return (None, diagnostics);
|
||||||
(None, diagnostics)
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let let_statement = LetStatement::new(
|
||||||
|
self.next_node_id(),
|
||||||
|
self.token_text(&identifier),
|
||||||
|
SourceRange::new(identifier.start(), identifier.end()),
|
||||||
|
is_mut,
|
||||||
|
expression,
|
||||||
|
);
|
||||||
|
(Some(let_statement), diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expression_statement_or_assign_statement(&mut self) -> ParseResult<Statement> {
|
fn expression_statement_or_assign_statement(&mut self) -> ParseResult<Option<Statement>> {
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
let (base, mut ds) = self.expression();
|
let (maybe_base, mut ds) = self.expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let base = match maybe_base {
|
||||||
|
Some(base) => base,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if self.current.is_some() && self.peek_current(TokenKind::Equals) {
|
if self.current.is_some() && self.peek_current(TokenKind::Equals) {
|
||||||
let (assign_statement, mut ds) = self.assign_rhs(base);
|
let (maybe_assign_statement, mut ds) = self.assign_rhs(base);
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
(Statement::Assign(assign_statement), diagnostics)
|
if let Some(assign_statement) = maybe_assign_statement {
|
||||||
|
(Some(Statement::Assign(assign_statement)), diagnostics)
|
||||||
|
} else {
|
||||||
|
(None, diagnostics)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
Statement::Expression(ExpressionStatement::new(base)),
|
Some(Statement::Expression(ExpressionStatement::new(base))),
|
||||||
diagnostics,
|
diagnostics,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_rhs(&mut self, destination: Expression) -> ParseResult<AssignStatement> {
|
fn assign_rhs(&mut self, destination: Expression) -> ParseResult<Option<AssignStatement>> {
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
let (_, mut ds) = self.expect_advance(TokenKind::Equals);
|
let (_, mut ds) = self.expect_advance(TokenKind::Equals);
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
|
||||||
let (value, mut ds) = self.expression();
|
let (maybe_value, mut ds) = self.expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
if let Some(value) = maybe_value {
|
||||||
(AssignStatement::new(destination, value), diagnostics)
|
(Some(AssignStatement::new(destination, value)), diagnostics)
|
||||||
|
} else {
|
||||||
|
(None, diagnostics)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expression(&mut self) -> ParseResult<Expression> {
|
fn expression(&mut self) -> ParseResult<Option<Expression>> {
|
||||||
self.bitwise_or_expression()
|
self.bitwise_or_expression()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bitwise_or_expression(&mut self) -> ParseResult<Expression> {
|
fn bitwise_or_expression(&mut self) -> ParseResult<Option<Expression>> {
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
|
|
||||||
let (mut base, mut ds) = self.bitwise_xor_expression();
|
let (maybe_base, mut ds) = self.bitwise_xor_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let mut base = match maybe_base {
|
||||||
|
Some(base) => base,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
while self.current.is_some() && self.peek_current(TokenKind::Bar) {
|
while self.current.is_some() && self.peek_current(TokenKind::Bar) {
|
||||||
diagnostics.append(&mut self.advance()); // |
|
diagnostics.append(&mut self.advance()); // |
|
||||||
let (rhs, mut ds) = self.bitwise_xor_expression();
|
let (maybe_rhs, mut ds) = self.bitwise_xor_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let rhs = match maybe_rhs {
|
||||||
|
Some(rhs) => rhs,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||||
base = Expression::Binary(BinaryExpression::new(
|
base = Expression::Binary(BinaryExpression::new(
|
||||||
@ -1056,19 +1088,32 @@ impl<'a> Parser<'a> {
|
|||||||
source_range,
|
source_range,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
(base, diagnostics)
|
(Some(base), diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bitwise_xor_expression(&mut self) -> ParseResult<Expression> {
|
fn bitwise_xor_expression(&mut self) -> ParseResult<Option<Expression>> {
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
|
|
||||||
let (mut base, mut ds) = self.bitwise_and_expression();
|
let (maybe_base, mut ds) = self.bitwise_and_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let mut base = match maybe_base {
|
||||||
|
Some(base) => base,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
while self.current.is_some() && self.peek_current(TokenKind::Caret) {
|
while self.current.is_some() && self.peek_current(TokenKind::Caret) {
|
||||||
diagnostics.append(&mut self.advance()); // ^
|
diagnostics.append(&mut self.advance()); // ^
|
||||||
let (rhs, mut ds) = self.bitwise_and_expression();
|
let (maybe_rhs, mut ds) = self.bitwise_and_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let rhs = match maybe_rhs {
|
||||||
|
Some(rhs) => rhs,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||||
base = Expression::Binary(BinaryExpression::new(
|
base = Expression::Binary(BinaryExpression::new(
|
||||||
@ -1079,19 +1124,31 @@ impl<'a> Parser<'a> {
|
|||||||
source_range,
|
source_range,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
(base, diagnostics)
|
(Some(base), diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bitwise_and_expression(&mut self) -> ParseResult<Expression> {
|
fn bitwise_and_expression(&mut self) -> ParseResult<Option<Expression>> {
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
|
|
||||||
let (mut base, mut ds) = self.shift_expression();
|
let (maybe_base, mut ds) = self.shift_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let mut base = match maybe_base {
|
||||||
|
Some(base) => base,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
while self.current.is_some() && self.peek_current(TokenKind::Ampersand) {
|
while self.current.is_some() && self.peek_current(TokenKind::Ampersand) {
|
||||||
diagnostics.append(&mut self.advance()); // &
|
diagnostics.append(&mut self.advance()); // &
|
||||||
let (rhs, mut ds) = self.shift_expression();
|
let (maybe_rhs, mut ds) = self.shift_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let rhs = match maybe_rhs {
|
||||||
|
Some(rhs) => rhs,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||||
@ -1103,14 +1160,20 @@ impl<'a> Parser<'a> {
|
|||||||
source_range,
|
source_range,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
(base, diagnostics)
|
(Some(base), diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shift_expression(&mut self) -> ParseResult<Expression> {
|
fn shift_expression(&mut self) -> ParseResult<Option<Expression>> {
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
|
|
||||||
let (mut base, mut ds) = self.additive_expression();
|
let (maybe_base, mut ds) = self.additive_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let mut base = match maybe_base {
|
||||||
|
Some(base) => base,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
while self.current.is_some() {
|
while self.current.is_some() {
|
||||||
let current = self.current.as_ref().unwrap();
|
let current = self.current.as_ref().unwrap();
|
||||||
@ -1122,8 +1185,14 @@ impl<'a> Parser<'a> {
|
|||||||
self.expect_immediately_after_advance(TokenKind::Lt, &previous_cloned); // second <
|
self.expect_immediately_after_advance(TokenKind::Lt, &previous_cloned); // second <
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
|
||||||
let (rhs, mut ds) = self.additive_expression();
|
let (maybe_rhs, mut ds) = self.additive_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let rhs = match maybe_rhs {
|
||||||
|
Some(rhs) => rhs,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||||
@ -1142,8 +1211,14 @@ impl<'a> Parser<'a> {
|
|||||||
self.expect_immediately_after_advance(TokenKind::Gt, &previous_cloned); // second >
|
self.expect_immediately_after_advance(TokenKind::Gt, &previous_cloned); // second >
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
|
||||||
let (rhs, mut ds) = self.additive_expression();
|
let (maybe_rhs, mut ds) = self.additive_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let rhs = match maybe_rhs {
|
||||||
|
Some(rhs) => rhs,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||||
@ -1159,22 +1234,34 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(base, diagnostics)
|
(Some(base), diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn additive_expression(&mut self) -> ParseResult<Expression> {
|
fn additive_expression(&mut self) -> ParseResult<Option<Expression>> {
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
|
|
||||||
let (mut base, mut ds) = self.multiplicative_expression();
|
let (maybe_base, mut ds) = self.multiplicative_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let mut base = match maybe_base {
|
||||||
|
Some(base) => base,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
while self.current.is_some() {
|
while self.current.is_some() {
|
||||||
let current = self.current.as_ref().unwrap();
|
let current = self.current.as_ref().unwrap();
|
||||||
match current.kind() {
|
match current.kind() {
|
||||||
TokenKind::Plus => {
|
TokenKind::Plus => {
|
||||||
diagnostics.append(&mut self.advance()); // plus
|
diagnostics.append(&mut self.advance()); // plus
|
||||||
let (rhs, mut ds) = self.multiplicative_expression();
|
let (maybe_rhs, mut ds) = self.multiplicative_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let rhs = match maybe_rhs {
|
||||||
|
Some(rhs) => rhs,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||||
@ -1188,8 +1275,14 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
TokenKind::Minus => {
|
TokenKind::Minus => {
|
||||||
diagnostics.append(&mut self.advance()); // minus
|
diagnostics.append(&mut self.advance()); // minus
|
||||||
let (rhs, mut ds) = self.multiplicative_expression();
|
let (maybe_rhs, mut ds) = self.multiplicative_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let rhs = match maybe_rhs {
|
||||||
|
Some(rhs) => rhs,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||||
@ -1204,22 +1297,34 @@ impl<'a> Parser<'a> {
|
|||||||
_ => break,
|
_ => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(base, diagnostics)
|
(Some(base), diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn multiplicative_expression(&mut self) -> ParseResult<Expression> {
|
fn multiplicative_expression(&mut self) -> ParseResult<Option<Expression>> {
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
|
|
||||||
let (mut base, mut ds) = self.prefix_expression();
|
let (maybe_base, mut ds) = self.prefix_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let mut base = match maybe_base {
|
||||||
|
Some(base) => base,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
while self.current.is_some() {
|
while self.current.is_some() {
|
||||||
let current = self.current.as_ref().unwrap();
|
let current = self.current.as_ref().unwrap();
|
||||||
match current.kind() {
|
match current.kind() {
|
||||||
TokenKind::Star => {
|
TokenKind::Star => {
|
||||||
diagnostics.append(&mut self.advance()); // multiply
|
diagnostics.append(&mut self.advance()); // multiply
|
||||||
let (rhs, mut ds) = self.prefix_expression();
|
let (maybe_rhs, mut ds) = self.prefix_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let rhs = match maybe_rhs {
|
||||||
|
Some(rhs) => rhs,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||||
@ -1233,8 +1338,14 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
TokenKind::Slash => {
|
TokenKind::Slash => {
|
||||||
diagnostics.append(&mut self.advance()); // slash
|
diagnostics.append(&mut self.advance()); // slash
|
||||||
let (rhs, mut ds) = self.prefix_expression();
|
let (maybe_rhs, mut ds) = self.prefix_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let rhs = match maybe_rhs {
|
||||||
|
Some(rhs) => rhs,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||||
@ -1248,8 +1359,14 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
TokenKind::Modulo => {
|
TokenKind::Modulo => {
|
||||||
diagnostics.append(&mut self.advance()); // modulo
|
diagnostics.append(&mut self.advance()); // modulo
|
||||||
let (rhs, mut ds) = self.prefix_expression();
|
let (maybe_rhs, mut ds) = self.prefix_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let rhs = match maybe_rhs {
|
||||||
|
Some(rhs) => rhs,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||||
@ -1264,10 +1381,10 @@ impl<'a> Parser<'a> {
|
|||||||
_ => break,
|
_ => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(base, diagnostics)
|
(Some(base), diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prefix_expression(&mut self) -> ParseResult<Expression> {
|
fn prefix_expression(&mut self) -> ParseResult<Option<Expression>> {
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
|
|
||||||
// first, collect all consecutive operators
|
// first, collect all consecutive operators
|
||||||
@ -1286,8 +1403,14 @@ impl<'a> Parser<'a> {
|
|||||||
// now go in reverse and build up expressions
|
// now go in reverse and build up expressions
|
||||||
// the parser is currently just after the prefix operators, so we need a suffix expression
|
// the parser is currently just after the prefix operators, so we need a suffix expression
|
||||||
// as a base
|
// as a base
|
||||||
let (mut base, mut ds) = self.suffix_expression();
|
let (maybe_base, mut ds) = self.suffix_expression();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let mut base = match maybe_base {
|
||||||
|
Some(base) => base,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
while let Some(operator_token) = operator_tokens.pop() {
|
while let Some(operator_token) = operator_tokens.pop() {
|
||||||
let source_range = SourceRange::new(operator_token.start(), base.source_range().end());
|
let source_range = SourceRange::new(operator_token.start(), base.source_range().end());
|
||||||
@ -1302,14 +1425,20 @@ impl<'a> Parser<'a> {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(base, diagnostics)
|
(Some(base), diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suffix_expression(&mut self) -> ParseResult<Expression> {
|
fn suffix_expression(&mut self) -> ParseResult<Option<Expression>> {
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
|
|
||||||
let (mut base, mut ds) = self.expression_base();
|
let (maybe_base, mut ds) = self.expression_base();
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
let mut base = match maybe_base {
|
||||||
|
Some(base) => base,
|
||||||
|
None => {
|
||||||
|
return (None, diagnostics);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
while self.current.is_some() {
|
while self.current.is_some() {
|
||||||
let current = self.current.as_ref().unwrap();
|
let current = self.current.as_ref().unwrap();
|
||||||
@ -1323,10 +1452,10 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(base, diagnostics)
|
(Some(base), diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expression_base(&mut self) -> ParseResult<Expression> {
|
fn expression_base(&mut self) -> ParseResult<Option<Expression>> {
|
||||||
let current = match self.current.as_ref() {
|
let current = match self.current.as_ref() {
|
||||||
None => {
|
None => {
|
||||||
let mut ds = Diagnostics::new();
|
let mut ds = Diagnostics::new();
|
||||||
@ -1334,7 +1463,7 @@ impl<'a> Parser<'a> {
|
|||||||
&EXPRESSION_FIRSTS,
|
&EXPRESSION_FIRSTS,
|
||||||
self.input.len(),
|
self.input.len(),
|
||||||
));
|
));
|
||||||
return (todo!(), ds);
|
return (None, ds);
|
||||||
}
|
}
|
||||||
Some(current) => current,
|
Some(current) => current,
|
||||||
};
|
};
|
||||||
@ -1345,11 +1474,11 @@ impl<'a> Parser<'a> {
|
|||||||
let source_range = SourceRange::new(current.start(), current.end());
|
let source_range = SourceRange::new(current.start(), current.end());
|
||||||
diagnostics.append(&mut self.advance());
|
diagnostics.append(&mut self.advance());
|
||||||
(
|
(
|
||||||
Expression::Integer(IntegerLiteral::new(
|
Some(Expression::Integer(IntegerLiteral::new(
|
||||||
self.next_node_id(),
|
self.next_node_id(),
|
||||||
i32::from_str(raw).unwrap(),
|
i32::from_str(raw).unwrap(),
|
||||||
source_range,
|
source_range,
|
||||||
)),
|
))),
|
||||||
diagnostics,
|
diagnostics,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -1358,11 +1487,11 @@ impl<'a> Parser<'a> {
|
|||||||
let source_range = SourceRange::new(current.start(), current.end());
|
let source_range = SourceRange::new(current.start(), current.end());
|
||||||
diagnostics.append(&mut self.advance());
|
diagnostics.append(&mut self.advance());
|
||||||
(
|
(
|
||||||
Expression::Double(DoubleLiteral::new(
|
Some(Expression::Double(DoubleLiteral::new(
|
||||||
self.next_node_id(),
|
self.next_node_id(),
|
||||||
f64::from_str(raw).unwrap(),
|
f64::from_str(raw).unwrap(),
|
||||||
source_range,
|
source_range,
|
||||||
)),
|
))),
|
||||||
diagnostics,
|
diagnostics,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -1371,11 +1500,11 @@ impl<'a> Parser<'a> {
|
|||||||
let source_range = SourceRange::new(current.start(), current.end());
|
let source_range = SourceRange::new(current.start(), current.end());
|
||||||
diagnostics.append(&mut self.advance());
|
diagnostics.append(&mut self.advance());
|
||||||
(
|
(
|
||||||
Expression::String(StringLiteral::new(
|
Some(Expression::String(StringLiteral::new(
|
||||||
self.next_node_id(),
|
self.next_node_id(),
|
||||||
&with_quotes[1..with_quotes.len() - 1],
|
&with_quotes[1..with_quotes.len() - 1],
|
||||||
source_range,
|
source_range,
|
||||||
)),
|
))),
|
||||||
diagnostics,
|
diagnostics,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -1384,11 +1513,11 @@ impl<'a> Parser<'a> {
|
|||||||
let source_range = SourceRange::new(current.start(), current.end());
|
let source_range = SourceRange::new(current.start(), current.end());
|
||||||
diagnostics.append(&mut self.advance());
|
diagnostics.append(&mut self.advance());
|
||||||
(
|
(
|
||||||
Expression::Identifier(Identifier::new(
|
Some(Expression::Identifier(Identifier::new(
|
||||||
self.next_node_id(),
|
self.next_node_id(),
|
||||||
declared_name,
|
declared_name,
|
||||||
source_range,
|
source_range,
|
||||||
)),
|
))),
|
||||||
diagnostics,
|
diagnostics,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -1430,14 +1559,18 @@ impl<'a> Parser<'a> {
|
|||||||
let mut expressions = vec![];
|
let mut expressions = vec![];
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
|
|
||||||
let (expression, mut ds) = self.expression();
|
let (maybe_expression, mut ds) = self.expression();
|
||||||
expressions.push(expression);
|
if let Some(expression) = maybe_expression {
|
||||||
|
expressions.push(expression);
|
||||||
|
}
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
|
|
||||||
while self.current.is_some() && self.peek_current(TokenKind::Comma) {
|
while self.current.is_some() && self.peek_current(TokenKind::Comma) {
|
||||||
diagnostics.append(&mut self.advance()); // comma
|
diagnostics.append(&mut self.advance()); // comma
|
||||||
let (expression, mut ds) = self.expression();
|
let (maybe_expression, mut ds) = self.expression();
|
||||||
expressions.push(expression);
|
if let Some(expression) = maybe_expression {
|
||||||
|
expressions.push(expression);
|
||||||
|
}
|
||||||
diagnostics.append(&mut ds);
|
diagnostics.append(&mut ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1677,11 +1810,15 @@ mod concrete_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn assert_expression(input: &str) -> Expression {
|
fn assert_expression(input: &str) -> Expression {
|
||||||
let (expression, diagnostics) = parse_expression(input);
|
let (maybe_expression, diagnostics) = parse_expression(input);
|
||||||
if !diagnostics.is_empty() {
|
if !diagnostics.is_empty() {
|
||||||
report_diagnostics(&diagnostics);
|
report_diagnostics(&diagnostics);
|
||||||
}
|
}
|
||||||
expression
|
if let Some(expression) = maybe_expression {
|
||||||
|
expression
|
||||||
|
} else {
|
||||||
|
panic!("parse_expression produced a None")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_function_in<'a>(
|
fn assert_function_in<'a>(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user