lang_c/
astutil.rs

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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use ast::*;
use span::{Node, Span};

#[cfg_attr(test, derive(Debug, PartialEq, Clone))]
pub enum Operation {
    Member(Node<MemberOperator>, Node<Identifier>),
    Unary(Node<UnaryOperator>),
    Binary(Node<BinaryOperator>, Node<Expression>),
    Call(Vec<Node<Expression>>),
}

fn apply_op(a: Node<Expression>, op: Node<Operation>) -> Node<Expression> {
    let span = Span::span(a.span.start, op.span.end);
    let expr = match op.node {
        Operation::Member(op, id) => Expression::Member(Box::new(Node::new(
            MemberExpression {
                operator: op,
                expression: Box::new(a),
                identifier: id,
            },
            span,
        ))),
        Operation::Unary(op) => Expression::UnaryOperator(Box::new(Node::new(
            UnaryOperatorExpression {
                operator: op,
                operand: Box::new(a),
            },
            span,
        ))),
        Operation::Binary(op, b) => Expression::BinaryOperator(Box::new(Node::new(
            BinaryOperatorExpression {
                operator: op,
                lhs: Box::new(a),
                rhs: Box::new(b),
            },
            span,
        ))),
        Operation::Call(args) => Expression::Call(Box::new(Node::new(
            CallExpression {
                callee: Box::new(a),
                arguments: args,
            },
            span,
        ))),
    };

    Node::new(expr, span)
}

pub fn apply_ops(ops: Vec<Node<Operation>>, expr: Node<Expression>) -> Node<Expression> {
    ops.into_iter().fold(expr, apply_op)
}

pub fn concat<T>(mut a: Vec<T>, b: Vec<T>) -> Vec<T> {
    a.extend(b);
    a
}

pub fn infix(
    node: Node<()>,
    op: BinaryOperator,
    lhs: Node<Expression>,
    rhs: Node<Expression>,
) -> Node<Expression> {
    let span = Span::span(lhs.span.start, rhs.span.end);
    Node::new(
        Expression::BinaryOperator(Box::new(Node::new(
            BinaryOperatorExpression {
                operator: Node::new(op, node.span),
                lhs: Box::new(lhs),
                rhs: Box::new(rhs),
            },
            span,
        ))),
        span,
    )
}

pub fn with_ext(mut d: Node<Declarator>, e: Option<Vec<Node<Extension>>>) -> Node<Declarator> {
    if let Some(e) = e {
        d.node.extensions.extend(e);
    }
    d
}

pub fn ts18661_float(binary: bool, width: usize, extended: bool) -> TS18661FloatType {
    TS18661FloatType {
        format: match (binary, extended) {
            (true, false) => TS18661FloatFormat::BinaryInterchange,
            (true, true) => TS18661FloatFormat::BinaryExtended,
            (false, false) => TS18661FloatFormat::DecimalInterchange,
            (false, true) => TS18661FloatFormat::DecimalExtended,
        },
        width: width,
    }
}

pub fn int_suffix(mut s: &str) -> Result<IntegerSuffix, &'static str> {
    let mut l = IntegerSize::Int;
    let mut u = false;
    let mut i = false;

    while s.len() > 0 {
        if l == IntegerSize::Int && (s.starts_with("ll") || s.starts_with("LL")) {
            l = IntegerSize::LongLong;
            s = &s[2..];
        } else if l == IntegerSize::Int && (s.starts_with("l") || s.starts_with("L")) {
            l = IntegerSize::Long;
            s = &s[1..];
        } else if !u && (s.starts_with("u") || s.starts_with("U")) {
            u = true;
            s = &s[1..];
        } else if !i
            && (s.starts_with("i")
                || s.starts_with("I")
                || s.starts_with("j")
                || s.starts_with("J"))
        {
            i = true;
            s = &s[1..];
        } else {
            return Err("integer suffix");
        }
    }

    Ok(IntegerSuffix {
        size: l,
        unsigned: u,
        imaginary: i,
    })
}