869 private links
Pratt parsing is a parsing algorithm that solves the awkward handling of left-recursion in a recursive descent parser. It elegantly handles both operator precedence and associativity using a single "binding power" concept. The core algorithm is as simple as follows:
fn expr(input: &str) -> S {
let mut lexer = Lexer::new(input);
expr_bp(&mut lexer, 0)
}
fn expr_bp(lexer: &mut Lexer, min_bp: u8) -> S {
let mut lhs = match lexer.next() {
Token::Atom(it) => S::Atom(it),
t => panic!("bad token: {:?}", t),
};
loop {
let op = match lexer.peek() {
Token::Eof => break,
Token::Op(op) => op,
t => panic!("bad token: {:?}", t),
};
let (l_bp, r_bp) = infix_binding_power(op);
if l_bp < min_bp {
break;
}
lexer.next();
let rhs = expr_bp(lexer, r_bp);
lhs = S::Cons(op, vec![lhs, rhs]);
}
lhs
}
fn infix_binding_power(op: char) -> (u8, u8) {
match op {
'+' | '-' => (1, 2),
'*' | '/' => (3, 4),
_ => panic!("bad op: {:?}"),
}
}
Like godblot.org but for decompiling binaries into C code using various decompilers (Ghidra, etc).
A bunch of trivia about linking in UNIX-like operating systems.
I was piqued by this, so I went on read Ken Thompson's original article. I am amazed by it. It's a quite surprising application of quine. Don't worry, it doesn't give me a feeling of existential crisis as I still have faith on the beloved fellow compiler workers.
Read about it in https://dl.acm.org/doi/10.1145/358198.358210 .
Take aways:
- use llvm's lld as linker to get around of platform-specific ld toolchain
- statically link musl libc to avoid platform specific glibc
it's about how to write high performance for modern cpu architecture.
<blockquote>Executables have been fascinating to me ever since I discovered, as a kid,
that they were just files. If you renamed a .exe to something else, you
could open it in notepad! An...</blockquote>
Good explanation of ELF format. (with a Rust parser as demo!)
TOC:
<blockquote>
I.Welcome
II.A Tree-Walk Interpreter
III.A Bytecode Virtual Machine
</blockquote>