summaryrefslogtreecommitdiff
path: root/src/taiga.lalrpop
blob: ffee4ee2a39b9dcbdfa1224efeed4e0f3b773728 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use std::str::FromStr;
use ast::{self, WithLocation};

grammar;

pub Program: ast::Program = {
    Expression => ast::Program(<>),
};

Expression: Box<ast::WithLocation<ast::Expression>> = {
    <e1:Expression> "&&" <e2:ExpressionEq> => Box::new(e1.join_map(*e2, |v1, v2| {
        ast::Expression::BinOp(ast::BinOp::And, Box::new(v1), Box::new(v2))
    })),
    <e1:Expression> "||" <e2:ExpressionEq> => Box::new(e1.join_map(*e2, |v1, v2| {
        ast::Expression::BinOp(ast::BinOp::Or, Box::new(v1), Box::new(v2))
    })),
    <l: @L> "!" <e: ExpressionEq> <r: @R> => Box::new(WithLocation::new(
        ast::Expression::UnaryOp(ast::UnaryOp::Not, e),
        l, r
    )),
    <ExpressionEq> => <>,
};

ExpressionEq: Box<ast::WithLocation<ast::Expression>> = {
    <e1:ExpressionEq> "=" <e2:ExpressionCmp> => Box::new(e1.join_map(*e2, |v1, v2| {
        ast::Expression::BinOp(ast::BinOp::Eq, Box::new(v1), Box::new(v2))
    })),
    <e1:ExpressionEq> "!=" <e2:ExpressionCmp> => Box::new(e1.join_map(*e2, |v1, v2| {
        ast::Expression::BinOp(ast::BinOp::Neq, Box::new(v1), Box::new(v2))
    })),
    <ExpressionCmp> => <>,
};

ExpressionCmp: Box<ast::WithLocation<ast::Expression>> = {
    <e1:ExpressionCmp> ">" <e2:ExpressionAdd> => Box::new(e1.join_map(*e2, |v1, v2| {
        ast::Expression::BinOp(ast::BinOp::Gt, Box::new(v1), Box::new(v2))
    })),
    <e1:ExpressionCmp> "<" <e2:ExpressionAdd> => Box::new(e1.join_map(*e2, |v1, v2| {
        ast::Expression::BinOp(ast::BinOp::Lt, Box::new(v1), Box::new(v2))
    })),
    <e1:ExpressionCmp> ">=" <e2:ExpressionAdd> => Box::new(e1.join_map(*e2, |v1, v2| {
        ast::Expression::BinOp(ast::BinOp::Ge, Box::new(v1), Box::new(v2))
    })),
    <e1:ExpressionCmp> "<=" <e2:ExpressionAdd> => Box::new(e1.join_map(*e2, |v1, v2| {
        ast::Expression::BinOp(ast::BinOp::Le, Box::new(v1), Box::new(v2))
    })),
    <ExpressionAdd> => <>,
};

ExpressionAdd: Box<ast::WithLocation<ast::Expression>> = {
    <e1:ExpressionAdd> "+" <e2:ExpressionMul> => Box::new(e1.join_map(*e2, |v1, v2| {
        ast::Expression::BinOp(ast::BinOp::Add, Box::new(v1), Box::new(v2))
    })),
    <e1:ExpressionAdd> "-" <e2:ExpressionMul> => Box::new(e1.join_map(*e2, |v1, v2| {
        ast::Expression::BinOp(ast::BinOp::Sub, Box::new(v1), Box::new(v2))
    })),
    <ExpressionMul> => <>,
};

ExpressionMul: Box<ast::WithLocation<ast::Expression>> = {
    <e1:ExpressionMul> "*" <e2:ExpressionSign> => Box::new(e1.join_map(*e2, |v1, v2| {
        ast::Expression::BinOp(ast::BinOp::Mul, Box::new(v1), Box::new(v2))
    })),
    <e1:ExpressionMul> "/" <e2:ExpressionSign> => Box::new(e1.join_map(*e2, |v1, v2| {
        ast::Expression::BinOp(ast::BinOp::Div, Box::new(v1), Box::new(v2))
    })),
    <e1:ExpressionMul> "//" <e2:ExpressionSign> => Box::new(e1.join_map(*e2, |v1, v2| {
        ast::Expression::BinOp(ast::BinOp::FloorDiv, Box::new(v1), Box::new(v2))
    })),
    <ExpressionSign> => <>,
};

ExpressionSign: Box<ast::WithLocation<ast::Expression>> = {
    <l: @L> "+" <e: ExpressionBase> <r: @R> => Box::new(WithLocation::new(
        ast::Expression::UnaryOp(ast::UnaryOp::Pos, e),
        l, r
    )),
    <l: @L> "-" <e: ExpressionBase> <r: @R> => Box::new(WithLocation::new(
        ast::Expression::UnaryOp(ast::UnaryOp::Neg, e),
        l, r
    )),
    <ExpressionBase> => <>,
};

ExpressionBase: Box<ast::WithLocation<ast::Expression>> = {
    Num => Box::new(<>.map(|v| ast::Expression::Number(v))),
    String => Box::new(<>.map(|v| ast::Expression::String(v))),
    Spanned<r"nil"> => Box::new(<>.map(|v| ast::Expression::Nil)),
    "(" <Expression> ")" => <>,
};

Num: WithLocation<u64> = <e: Spanned<r"[0-9]+">> => e.map(|v| u64::from_str(v).unwrap());
String: WithLocation<String> = <l: @L> <v:r##""(?:[^"\\]|\\\\)*""##> <r: @R> => {
    WithLocation::new(v[1..v.len() - 1].to_owned(), l, r)
};

Spanned<T>: WithLocation<T> = {
    <l: @L> <v: T> <r: @R> => WithLocation::new(v, l, r)
};