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
use crate::parser::peg::parse_error::{Expect, PEGParseError};
use crate::parser::peg::parse_result::ParseResult;
use crate::parser::peg::parser_core::{ParserContext, ParserState};
use crate::parser::peg::parser_core_ast::{CoreAst, ParsePairRaw};
use crate::parser::peg::parser_core_expression::{parse_expression_name, skip_single_layout};
use crate::sources::source_file::{SourceFile, SourceFileIterator};
use crate::sources::span::Span;
use std::collections::{HashMap, VecDeque};
#[allow(clippy::unnecessary_unwrap)]
pub fn parse_file<'src>(
ast: &'src CoreAst<'src>,
file: &'src SourceFile,
) -> (ParsePairRaw, Vec<PEGParseError>) {
let mut state = ParserContext {
file,
ast,
errors: HashMap::new(),
};
let mut errors = vec![];
let mut last_err_pos: Option<usize> = None;
let mut last_err_offset = 0usize;
loop {
let (res, err) = parse_file_sub(&state, state.ast.starting_sort, file.iter());
if !res.ok {
let err = err.expect("Not ok means an error happened.");
if last_err_pos.is_none()
|| last_err_pos.unwrap() + last_err_offset < res.pos_err.position()
{
errors.push(err);
last_err_pos = Some(res.pos_err.position());
last_err_offset = 0;
state.errors.insert(last_err_pos.unwrap(), last_err_offset);
continue;
} else {
let len_left = res.pos_err.clone().count();
if last_err_offset >= len_left {
return (res.result, errors);
}
last_err_offset += 1;
state.errors.insert(last_err_pos.unwrap(), last_err_offset);
}
} else {
return (res.result, errors);
}
}
}
pub fn parse_file_sub<'src>(
state: &ParserContext<'src>,
sort: &'src str,
pos: SourceFileIterator<'src>,
) -> (ParseResult<'src, ParsePairRaw>, Option<PEGParseError>) {
let mut cache = ParserState {
cache: HashMap::new(),
cache_stack: VecDeque::new(),
best_error: None,
no_layout_nest_count: 0usize,
no_errors_nest_count: 0usize,
allow_layout: true,
};
let mut res = parse_expression_name(state, &mut cache, sort, pos);
if !res.ok {
return (res, Some(cache.best_error.unwrap()));
}
loop {
let (ok, after_layout_pos) = skip_single_layout(state, &mut cache, res.pos.clone());
if !ok {
break;
};
res.pos = after_layout_pos;
}
if res.pos.peek().is_none() {
(res, None)
} else {
res.ok = false;
match cache.best_error {
Some(err) => (res, Some(err)),
None => {
let curpos = res.pos.position();
while res.pos.next().is_some() {}
let endpos = res.pos.position();
(
res,
Some(PEGParseError::expect(
Span::from_end(state.file, curpos, endpos),
Expect::NotEntireInput(),
)),
)
}
}
}
}