aboutsummaryrefslogtreecommitdiff
path: root/rprt-engine/src/parser.rs
blob: 44feda08b7c23f540548597d7827c351db1b655f (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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::expression::*;
use crate::token::*;

#[derive(Debug, Clone)]
pub enum ParseError {
    UnexpectedToken {
        found: Token, // Own the token, don't borrow it
        expecting: &'static str,
    },
    UnexpectedEndOfInput {
        expecting: &'static str,
    },
}

struct ParseContext {
    tokens: Vec<Token>,
    pos: usize,
}

impl ParseContext {
    fn advance(&mut self) -> Result<(), ParseError> {
        self.pos += 1;
        if self.pos >= self.tokens.len() {
            Err(ParseError::UnexpectedEndOfInput {
                expecting: "more tokens",
            })
        } else {
            Ok(())
        }
    }

    fn current(&self) -> Result<Token, ParseError> {
        self.tokens
            .get(self.pos)
            .cloned()
            .ok_or(ParseError::UnexpectedEndOfInput { expecting: "token" })
    }
}

pub fn parse(tokens: Vec<Token>) -> Result<SelectionValuedExpr, ParseError> {
    let mut context = ParseContext {
        tokens: tokens,
        pos: 0,
    };
    let func = parse_function(&mut context)?;
    Ok(SelectionValuedExpr::NullaryApplicationS(func))
}

fn parse_function(context: &mut ParseContext) -> Result<SelectionFn, ParseError> {
    let func = parse_builtin_function_s(context)?;
    Ok(SelectionFn::Function {
        func: func,
        search_mod: None,
        result_transform: None,
    })
}

fn parse_builtin_function_s(context: &mut ParseContext) -> Result<BuiltinSelectionFn, ParseError> {
    let token = context.current()?;
    match token {
        Token::Empty => Ok(BuiltinSelectionFn::Empty),
        Token::EndOfBuffer => Ok(BuiltinSelectionFn::EndOfBuffer),
        Token::Span => Ok(BuiltinSelectionFn::Span),
        Token::CharacterOffset => parse_char_offset(context),
        Token::Number(n) => Ok(BuiltinSelectionFn::Line(n)),
        Token::Regex(pattern) => Ok(BuiltinSelectionFn::Regex(pattern)),
        Token::AllMatches => parse_all_matches(context),
        Token::PositiveLineOffset => parse_relative_line(context),
        Token::BufferMatch => parse_buffer_match(context),
        _ => Err(ParseError::UnexpectedToken {
            found: token,
            expecting: "selection function",
        }),
    }
}

fn parse_char_offset(context: &mut ParseContext) -> Result<BuiltinSelectionFn, ParseError> {
    context.advance()?;
    let token = context.current()?;
    match token {
        Token::Number(n) => Ok(BuiltinSelectionFn::CharOffset(n)),
        _ => Err(ParseError::UnexpectedToken {
            found: token,
            expecting: "number",
        }),
    }
}

fn parse_all_matches(context: &mut ParseContext) -> Result<BuiltinSelectionFn, ParseError> {
    context.advance()?;
    let token = context.current()?;
    match token {
        Token::Regex(pattern) => Ok(BuiltinSelectionFn::AllMatches(pattern)),
        _ => Err(ParseError::UnexpectedToken {
            found: token,
            expecting: "regex",
        }),
    }
}

fn parse_relative_line(context: &mut ParseContext) -> Result<BuiltinSelectionFn, ParseError> {
    context.advance()?;
    let token = context.current()?;
    match token {
        Token::Number(n) => Ok(BuiltinSelectionFn::RelativeLine(n)),
        _ => Err(ParseError::UnexpectedToken {
            found: token,
            expecting: "number",
        }),
    }
}

fn parse_buffer_match(context: &mut ParseContext) -> Result<BuiltinSelectionFn, ParseError> {
    context.advance()?;
    let token = context.current()?;
    match token {
        Token::Regex(pattern) => Ok(BuiltinSelectionFn::BufferMatch(pattern)),
        _ => Err(ParseError::UnexpectedToken {
            found: token,
            expecting: "regex",
        }),
    }
}