doughlang: "fix" semi elision, add "fully qualified" paths, add proper pattern prec parsing.
This actually gets some old code parsing!
This commit is contained in:
66
samples/usable.do
Normal file
66
samples/usable.do
Normal file
@@ -0,0 +1,66 @@
|
||||
//! Sample doughlang code
|
||||
|
||||
struct Expr {
|
||||
Atom (f64),
|
||||
Op (char, [Expr]),
|
||||
}
|
||||
|
||||
fn execute(expr: Expr) -> f64 {
|
||||
match expr {
|
||||
ExprAtom(value) => value,
|
||||
ExprOp('*', [lhs, rhs]) => execute(lhs) * execute(rhs),
|
||||
ExprOp('/', [lhs, rhs]) => execute(lhs) / execute(rhs),
|
||||
ExprOp('%', [lhs, rhs]) => execute(lhs) % execute(rhs),
|
||||
ExprOp('+', [lhs, rhs]) => execute(lhs) + execute(rhs),
|
||||
ExprOp('-', [lhs, rhs]) => execute(lhs) - execute(rhs),
|
||||
// ExprOp('>', [lhs, rhs]) => (execute(lhs) as u64 >> execute(rhs) as u64) as f64,
|
||||
// ExprOp('<', [lhs, rhs]) => (execute(lhs) as u64 << execute(rhs) as u64) as f64,
|
||||
ExprOp('-', [lhs]) => - execute(lhs),
|
||||
other => {
|
||||
panic("Unknown operation: " + fmt(other))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Formats an expression to a string
|
||||
fn fmt_expr(expr: Expr) -> str {
|
||||
match expr {
|
||||
ExprAtom(value) => fmt(value),
|
||||
ExprOp(operator, [lhs, rhs]) => fmt('(', fmt_expr(lhs), ' ', operator, ' ', fmt_expr(rhs), ')'),
|
||||
ExprOp(operator, [rhs]) => fmt(operator, fmt_expr(rhs)),
|
||||
_ => println("Unexpected expr: ", expr),
|
||||
}
|
||||
}
|
||||
|
||||
/// Prints an expression
|
||||
fn print_expr(expr: Expr) {
|
||||
println(fmt_expr(expr))
|
||||
}
|
||||
|
||||
/// Parses expressions
|
||||
fn parse(line: [char], power: i32) -> (Expr, [char]) {
|
||||
fn map((expr, line): (Expr, [char]), f: fn(Expr) -> Expr) -> (Expr, [char]) {
|
||||
(f(expr), line)
|
||||
}
|
||||
|
||||
line = space(line);
|
||||
|
||||
let (lhs, line) = match line {
|
||||
['0'..'9', ..] => number(line),
|
||||
['(', ..rest] => match parse(rest, Power::None) {
|
||||
(expr, [')', ..rest]) => (expr, rest),
|
||||
(expr, rest) => panic(fmt("Expected ')', got ", expr, ", ", rest)),
|
||||
},
|
||||
[op, ..rest] => parse(rest, pre_bp(op)).map(|lhs| Expr::Op(op, [lhs])),
|
||||
_ => panic("Unexpected end of input"),
|
||||
};
|
||||
|
||||
while let [op, ..rest] = space(line) {
|
||||
let (before, after) = inf_bp(op);
|
||||
if before < power {
|
||||
break;
|
||||
};
|
||||
(lhs, line) = parse(rest, after).map(|rhs| Expr::Op(op, [lhs, rhs]));
|
||||
};
|
||||
(lhs, line)
|
||||
}
|
||||
Reference in New Issue
Block a user