overhaul operator precedence
arithmetic operators now have the same precedence. if you want them to bind tighter, you remove the spaces around them: - 2 + 2 * 2 = 8 - 2 + 2*2 = 6
This commit is contained in:
parent
09f2292e62
commit
b52c1b26c9
4 changed files with 144 additions and 43 deletions
|
@ -3,7 +3,7 @@ use alloc::vec::Vec;
|
|||
use crate::{
|
||||
diagnostic::Diagnostic,
|
||||
source::{SourceCode, Span},
|
||||
token::{Lexis, TokenAllocError, TokenKind},
|
||||
token::{Lexis, Spaces, TokenAllocError, TokenKind},
|
||||
};
|
||||
|
||||
pub struct Lexer<'a> {
|
||||
|
@ -132,7 +132,8 @@ fn color(l: &mut Lexer<'_>) -> TokenKind {
|
|||
TokenKind::Color
|
||||
}
|
||||
|
||||
fn whitespace_and_comments(l: &mut Lexer<'_>) {
|
||||
fn whitespace_and_comments(l: &mut Lexer<'_>) -> bool {
|
||||
let mut matched = false;
|
||||
loop {
|
||||
match l.current() {
|
||||
'-' => {
|
||||
|
@ -142,6 +143,7 @@ fn whitespace_and_comments(l: &mut Lexer<'_>) {
|
|||
while l.current() != '\n' && l.current() != '\0' {
|
||||
l.advance();
|
||||
}
|
||||
matched = true;
|
||||
} else {
|
||||
// An unfortunate little bit of backtracking here;
|
||||
// This seems like the simplest possible solution though.
|
||||
|
@ -153,14 +155,18 @@ fn whitespace_and_comments(l: &mut Lexer<'_>) {
|
|||
}
|
||||
}
|
||||
|
||||
' ' | '\r' | '\t' => l.advance(),
|
||||
' ' | '\r' | '\t' => {
|
||||
l.advance();
|
||||
matched = true
|
||||
}
|
||||
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
matched
|
||||
}
|
||||
|
||||
fn newline(l: &mut Lexer<'_>) -> (TokenKind, Span) {
|
||||
fn newline(l: &mut Lexer<'_>, has_left_space: bool) -> (TokenKind, Span, bool) {
|
||||
let start = l.position;
|
||||
l.advance(); // skip the initial newline
|
||||
let end = l.position;
|
||||
|
@ -177,11 +183,11 @@ fn newline(l: &mut Lexer<'_>) -> (TokenKind, Span) {
|
|||
}
|
||||
}
|
||||
|
||||
(TokenKind::Newline, Span::new(start, end))
|
||||
(TokenKind::Newline, Span::new(start, end), has_left_space)
|
||||
}
|
||||
|
||||
fn token(l: &mut Lexer<'_>) -> (TokenKind, Span) {
|
||||
whitespace_and_comments(l);
|
||||
fn token(l: &mut Lexer<'_>) -> (TokenKind, Span, bool) {
|
||||
let has_left_space = whitespace_and_comments(l);
|
||||
|
||||
let start = l.position;
|
||||
let kind = match l.current() {
|
||||
|
@ -203,7 +209,7 @@ fn token(l: &mut Lexer<'_>) -> (TokenKind, Span) {
|
|||
'<' => one_or_two(l, TokenKind::Less, '=', TokenKind::LessEqual),
|
||||
'>' => one_or_two(l, TokenKind::Greater, '=', TokenKind::GreaterEqual),
|
||||
|
||||
'\n' => return newline(l),
|
||||
'\n' => return newline(l, has_left_space),
|
||||
'(' => one(l, TokenKind::LParen),
|
||||
')' => one(l, TokenKind::RParen),
|
||||
'[' => one(l, TokenKind::LBrack),
|
||||
|
@ -222,13 +228,22 @@ fn token(l: &mut Lexer<'_>) -> (TokenKind, Span) {
|
|||
}
|
||||
};
|
||||
let end = l.position;
|
||||
(kind, Span::new(start, end))
|
||||
(kind, Span::new(start, end), has_left_space)
|
||||
}
|
||||
|
||||
pub fn lex(l: &mut Lexer<'_>) -> Result<(), TokenAllocError> {
|
||||
loop {
|
||||
let (kind, span) = token(l);
|
||||
l.lexis.push(kind, span)?;
|
||||
let (kind, span, has_left_space) = token(l);
|
||||
|
||||
if !l.lexis.is_empty() {
|
||||
let prev = l.lexis.len() - 1;
|
||||
let spaces = l.lexis.spaces(prev);
|
||||
l.lexis
|
||||
.set_spaces(prev, Spaces::new(spaces.left(), has_left_space));
|
||||
}
|
||||
let spaces = Spaces::new(has_left_space, false);
|
||||
l.lexis.push(kind, spaces, span)?;
|
||||
|
||||
if kind == TokenKind::Eof {
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue