forked from AbleOS/holey-bytes
adding '<op>=' syntax
This commit is contained in:
parent
70955c1792
commit
3c09a5f23e
|
@ -1,4 +1,3 @@
|
|||
|
||||
Type := struct {
|
||||
brah: int,
|
||||
blah: int,
|
||||
|
|
|
@ -12,7 +12,7 @@ fib := fn(n: int): int {
|
|||
c := a + b;
|
||||
a = b;
|
||||
b = c;
|
||||
n = n - 1;
|
||||
n -= 1;
|
||||
|
||||
stack_reclamation_edge_case := 0;
|
||||
|
||||
|
|
|
@ -724,7 +724,7 @@ impl<'a> Codegen<'a> {
|
|||
match *expr {
|
||||
E::Ident { id, .. } if ident::is_null(id) => id,
|
||||
E::UnOp {
|
||||
op: T::Star, val, ..
|
||||
op: T::Mul, val, ..
|
||||
} => {
|
||||
let ty = self.ty(val);
|
||||
self.alloc_pointer(ty)
|
||||
|
@ -918,7 +918,7 @@ impl<'a> Codegen<'a> {
|
|||
Some(Value { ty, loc })
|
||||
}
|
||||
E::UnOp {
|
||||
op: T::Amp,
|
||||
op: T::Band,
|
||||
val,
|
||||
pos,
|
||||
} => {
|
||||
|
@ -953,7 +953,7 @@ impl<'a> Codegen<'a> {
|
|||
})
|
||||
}
|
||||
E::UnOp {
|
||||
op: T::Star,
|
||||
op: T::Mul,
|
||||
val,
|
||||
pos,
|
||||
} => {
|
||||
|
@ -1198,7 +1198,7 @@ impl<'a> Codegen<'a> {
|
|||
self.display_ty(right.ty)
|
||||
);
|
||||
|
||||
if matches!(op, T::Plus | T::Minus) {
|
||||
if matches!(op, T::Add | T::Sub) {
|
||||
let min_size = lsize.min(rsize);
|
||||
if bt::is_signed(ty) && min_size < size {
|
||||
let operand = if lsize < rsize { lhs.0 } else { rhs.0 };
|
||||
|
@ -1280,16 +1280,16 @@ impl<'a> Codegen<'a> {
|
|||
use instrs as i;
|
||||
Some(
|
||||
match op {
|
||||
T::Plus => [i::add8, i::add16, i::add32, i::add64],
|
||||
T::Minus => [i::sub8, i::sub16, i::sub32, i::sub64],
|
||||
T::Star => [i::mul8, i::mul16, i::mul32, i::mul64],
|
||||
T::FSlash if signed => [
|
||||
T::Add => [i::add8, i::add16, i::add32, i::add64],
|
||||
T::Sub => [i::sub8, i::sub16, i::sub32, i::sub64],
|
||||
T::Mul => [i::mul8, i::mul16, i::mul32, i::mul64],
|
||||
T::Div if signed => [
|
||||
|a, b, c| i::dirs8(a, ZERO, b, c),
|
||||
|a, b, c| i::dirs16(a, ZERO, b, c),
|
||||
|a, b, c| i::dirs32(a, ZERO, b, c),
|
||||
|a, b, c| i::dirs64(a, ZERO, b, c),
|
||||
],
|
||||
T::FSlash => [
|
||||
T::Div => [
|
||||
|a, b, c| i::diru8(a, ZERO, b, c),
|
||||
|a, b, c| i::diru16(a, ZERO, b, c),
|
||||
|a, b, c| i::diru32(a, ZERO, b, c),
|
||||
|
|
|
@ -29,8 +29,8 @@ macro_rules! gen_token_kind {
|
|||
$punkt:ident = $punkt_lit:literal,
|
||||
)*
|
||||
#[ops] $(
|
||||
#[prec = $prec:literal] $(
|
||||
$op:ident = $op_lit:literal,
|
||||
#[$prec:ident] $(
|
||||
$op:ident = $op_lit:literal $(=> $assign:ident)?,
|
||||
)*
|
||||
)*
|
||||
}
|
||||
|
@ -42,7 +42,8 @@ macro_rules! gen_token_kind {
|
|||
|
||||
$( Self::$keyword => stringify!($keyword_lit), )*
|
||||
$( Self::$punkt => stringify!($punkt_lit), )*
|
||||
$($( Self::$op => $op_lit, )*)*
|
||||
$($( Self::$op => $op_lit,
|
||||
$(Self::$assign => concat!($op_lit, "="),)?)*)*
|
||||
};
|
||||
f.write_str(s)
|
||||
}
|
||||
|
@ -52,9 +53,10 @@ macro_rules! gen_token_kind {
|
|||
#[inline(always)]
|
||||
pub fn precedence(&self) -> Option<u8> {
|
||||
Some(match self {
|
||||
$($(Self::$op)|* => $prec,)*
|
||||
$($(Self::$op => ${ignore($prec)} ${index(1)},
|
||||
$(Self::$assign => 0,)?)*)*
|
||||
_ => return None,
|
||||
})
|
||||
} + 1)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -64,6 +66,13 @@ macro_rules! gen_token_kind {
|
|||
_ => Self::Ident,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assign_op(&self) -> Option<Self> {
|
||||
Some(match self {
|
||||
$($($(Self::$assign => Self::$op,)?)*)*
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
|
@ -71,7 +80,7 @@ macro_rules! gen_token_kind {
|
|||
$( $pattern, )*
|
||||
$( $keyword, )*
|
||||
$( $punkt, )*
|
||||
$($( $op, )*)*
|
||||
$($( $op, $($assign,)? )*)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -104,26 +113,39 @@ gen_token_kind! {
|
|||
Comma = ",",
|
||||
Dot = ".",
|
||||
Ctor = ".{",
|
||||
Tupl = ".(",
|
||||
Tupl = ".(",
|
||||
#[ops]
|
||||
#[prec = 1]
|
||||
#[prec]
|
||||
Decl = ":=",
|
||||
Assign = "=",
|
||||
#[prec = 21]
|
||||
#[prec]
|
||||
Or = "||",
|
||||
#[prec]
|
||||
And = "&&",
|
||||
#[prec]
|
||||
Bor = "|" => BorAss,
|
||||
#[prec]
|
||||
Xor = "^" => XorAss,
|
||||
#[prec]
|
||||
Band = "&" => BandAss,
|
||||
#[prec]
|
||||
Eq = "==",
|
||||
Ne = "!=",
|
||||
#[prec]
|
||||
Le = "<=",
|
||||
Ge = ">=",
|
||||
Lt = "<",
|
||||
Gt = ">",
|
||||
Eq = "==",
|
||||
Ne = "!=",
|
||||
#[prec = 22]
|
||||
Amp = "&",
|
||||
#[prec = 23]
|
||||
Plus = "+",
|
||||
Minus = "-",
|
||||
#[prec = 24]
|
||||
Star = "*",
|
||||
FSlash = "/",
|
||||
#[prec]
|
||||
Shl = "<<" => ShlAss,
|
||||
Shr = ">>" => ShrAss,
|
||||
#[prec]
|
||||
Add = "+" => AddAss,
|
||||
Sub = "-" => SubAss,
|
||||
#[prec]
|
||||
Mul = "*" => MulAss,
|
||||
Div = "/" => DivAss,
|
||||
Mod = "%" => ModAss,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,11 +177,92 @@ impl<'a> Lexer<'a> {
|
|||
}
|
||||
|
||||
pub fn next(&mut self) -> Token {
|
||||
Iterator::next(self).unwrap_or(Token {
|
||||
kind: TokenKind::Eof,
|
||||
start: self.pos,
|
||||
end: self.pos,
|
||||
})
|
||||
use TokenKind as T;
|
||||
loop {
|
||||
let mut start = self.pos;
|
||||
|
||||
let Some(c) = self.advance() else {
|
||||
return Token {
|
||||
kind: T::Eof,
|
||||
start,
|
||||
end: self.pos,
|
||||
};
|
||||
};
|
||||
|
||||
let kind = match c {
|
||||
b'\n' | b'\r' | b'\t' | b' ' => continue,
|
||||
b'0'..=b'9' => {
|
||||
while let Some(b'0'..=b'9') = self.peek() {
|
||||
self.advance();
|
||||
}
|
||||
T::Number
|
||||
}
|
||||
c @ (b'a'..=b'z' | b'A'..=b'Z' | b'_' | b'@') => {
|
||||
while let Some(b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_') = self.peek() {
|
||||
self.advance();
|
||||
}
|
||||
|
||||
if c == b'@' {
|
||||
start += 1;
|
||||
T::Driective
|
||||
} else {
|
||||
let ident = &self.bytes[start as usize..self.pos as usize];
|
||||
T::from_ident(ident)
|
||||
}
|
||||
}
|
||||
b':' if self.advance_if(b'=') => T::Decl,
|
||||
b':' => T::Colon,
|
||||
b',' => T::Comma,
|
||||
b'.' if self.advance_if(b'{') => T::Ctor,
|
||||
b'.' if self.advance_if(b'(') => T::Tupl,
|
||||
b'.' => T::Dot,
|
||||
b';' => T::Semi,
|
||||
b'!' if self.advance_if(b'=') => T::Ne,
|
||||
b'=' if self.advance_if(b'=') => T::Eq,
|
||||
b'=' => T::Assign,
|
||||
b'<' if self.advance_if(b'=') => T::Le,
|
||||
b'<' if self.advance_if(b'<') => match self.advance_if(b'=') {
|
||||
true => T::ShlAss,
|
||||
false => T::Shl,
|
||||
},
|
||||
b'<' => T::Lt,
|
||||
b'>' if self.advance_if(b'=') => T::Ge,
|
||||
b'>' if self.advance_if(b'>') => match self.advance_if(b'=') {
|
||||
true => T::ShrAss,
|
||||
false => T::Shr,
|
||||
},
|
||||
b'>' => T::Gt,
|
||||
b'+' if self.advance_if(b'=') => T::AddAss,
|
||||
b'+' => T::Add,
|
||||
b'-' if self.advance_if(b'=') => T::SubAss,
|
||||
b'-' => T::Sub,
|
||||
b'*' if self.advance_if(b'=') => T::MulAss,
|
||||
b'*' => T::Mul,
|
||||
b'/' if self.advance_if(b'=') => T::DivAss,
|
||||
b'/' => T::Div,
|
||||
b'%' if self.advance_if(b'=') => T::ModAss,
|
||||
b'%' => T::Mod,
|
||||
b'&' if self.advance_if(b'=') => T::BandAss,
|
||||
b'&' if self.advance_if(b'&') => T::And,
|
||||
b'&' => T::Band,
|
||||
b'^' if self.advance_if(b'=') => T::XorAss,
|
||||
b'^' => T::Xor,
|
||||
b'|' if self.advance_if(b'=') => T::BorAss,
|
||||
b'|' if self.advance_if(b'|') => T::Or,
|
||||
b'|' => T::Bor,
|
||||
b'(' => T::LParen,
|
||||
b')' => T::RParen,
|
||||
b'{' => T::LBrace,
|
||||
b'}' => T::RBrace,
|
||||
_ => T::Error,
|
||||
};
|
||||
|
||||
return Token {
|
||||
kind,
|
||||
start,
|
||||
end: self.pos,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn advance_if(&mut self, arg: u8) -> bool {
|
||||
|
@ -232,11 +335,11 @@ impl<'a> Iterator for Lexer<'a> {
|
|||
b'<' => T::Lt,
|
||||
b'>' if self.advance_if(b'=') => T::Ge,
|
||||
b'>' => T::Gt,
|
||||
b'+' => T::Plus,
|
||||
b'-' => T::Minus,
|
||||
b'*' => T::Star,
|
||||
b'/' => T::FSlash,
|
||||
b'&' => T::Amp,
|
||||
b'+' => T::Add,
|
||||
b'-' => T::Sub,
|
||||
b'*' => T::Mul,
|
||||
b'/' => T::Div,
|
||||
b'&' => T::Band,
|
||||
b'(' => T::LParen,
|
||||
b')' => T::RParen,
|
||||
b'{' => T::LBrace,
|
||||
|
|
|
@ -74,7 +74,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
self.bin_expr(left, 0)
|
||||
}
|
||||
|
||||
fn bin_expr(&mut self, mut left: Expr<'a>, min_prec: u8) -> Expr<'a> {
|
||||
fn bin_expr(&mut self, mut fold: Expr<'a>, min_prec: u8) -> Expr<'a> {
|
||||
loop {
|
||||
let Some(prec) = self.token.kind.precedence() else {
|
||||
break;
|
||||
|
@ -87,14 +87,22 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
let op = self.next().kind;
|
||||
let right = self.unit_expr();
|
||||
let right = self.bin_expr(right, prec);
|
||||
left = Expr::BinOp {
|
||||
left: self.arena.alloc(left),
|
||||
right: self.arena.alloc(right),
|
||||
op,
|
||||
};
|
||||
let right = &*self.arena.alloc(right);
|
||||
let left = &*self.arena.alloc(fold);
|
||||
|
||||
if let Some(op) = op.assign_op() {
|
||||
let right = Expr::BinOp { left, op, right };
|
||||
fold = Expr::BinOp {
|
||||
left,
|
||||
op: TokenKind::Assign,
|
||||
right: self.arena.alloc(right),
|
||||
};
|
||||
} else {
|
||||
fold = Expr::BinOp { left, right, op };
|
||||
}
|
||||
}
|
||||
|
||||
left
|
||||
fold
|
||||
}
|
||||
|
||||
fn try_resolve_builtin(name: &str) -> Option<Ident> {
|
||||
|
@ -220,7 +228,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
},
|
||||
body: self.ptr_expr(),
|
||||
},
|
||||
T::Amp | T::Star => E::UnOp {
|
||||
T::Band | T::Mul => E::UnOp {
|
||||
pos: token.start,
|
||||
op: token.kind,
|
||||
val: self.ptr_unit_expr(),
|
||||
|
|
|
@ -8,23 +8,23 @@ Ident "int"
|
|||
LBrace "{"
|
||||
Return "return"
|
||||
Number "10"
|
||||
Minus "-"
|
||||
Sub "-"
|
||||
Number "20"
|
||||
FSlash "/"
|
||||
Div "/"
|
||||
Number "2"
|
||||
Plus "+"
|
||||
Add "+"
|
||||
Number "4"
|
||||
Star "*"
|
||||
Mul "*"
|
||||
LParen "("
|
||||
Number "2"
|
||||
Plus "+"
|
||||
Add "+"
|
||||
Number "2"
|
||||
RParen ")"
|
||||
Minus "-"
|
||||
Sub "-"
|
||||
Number "4"
|
||||
Star "*"
|
||||
Mul "*"
|
||||
Number "4"
|
||||
Plus "+"
|
||||
Add "+"
|
||||
Number "1"
|
||||
Semi ";"
|
||||
RBrace "}"
|
||||
|
|
Loading…
Reference in a new issue