brink_format/inkt/
read.rs1use pest::Parser;
12use pest_derive::Parser;
13
14use crate::story::StoryData;
15
16mod defs;
17mod instructions;
18mod lines;
19mod primitives;
20mod values;
21
22#[derive(Parser)]
23#[grammar = "inkt/inkt.pest"]
24struct InktParser;
25
26#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct InktParseError {
29 pub message: String,
30 pub line: usize,
31 pub col: usize,
32}
33
34impl core::fmt::Display for InktParseError {
35 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
36 write!(f, "{}:{}: {}", self.line, self.col, self.message)
37 }
38}
39
40impl std::error::Error for InktParseError {}
41
42pub fn read_inkt(input: &str) -> Result<StoryData, InktParseError> {
44 let pairs = InktParser::parse(Rule::story, input).map_err(|e| {
45 let (line, col) = match e.line_col {
46 pest::error::LineColLocation::Pos(pos) => pos,
47 pest::error::LineColLocation::Span(start, _) => start,
48 };
49 InktParseError {
50 message: e.to_string(),
51 line,
52 col,
53 }
54 })?;
55
56 let story_pair = pairs.into_iter().next().ok_or_else(|| InktParseError {
57 message: "no story node".into(),
58 line: 1,
59 col: 1,
60 })?;
61
62 parse_story(story_pair)
63}
64
65type P<'a> = pest::iterators::Pair<'a, Rule>;
66
67fn parse_story(pair: P<'_>) -> Result<StoryData, InktParseError> {
68 let mut name_table = Vec::new();
69 let mut seen_container_ids = std::collections::HashSet::new();
76 let mut variables = Vec::new();
77 let mut list_defs = Vec::new();
78 let mut list_items = Vec::new();
79 let mut externals = Vec::new();
80 let mut addresses = Vec::new();
81 let mut address_paths = Vec::new();
82 let mut containers = Vec::new();
83 let mut line_tables = Vec::new();
84 let mut list_literals = Vec::new();
85 let mut literal_pool = Vec::new();
86 let mut private_defs = Vec::new();
87 let mut alias_table = Vec::new();
88 let mut effect_rows = Vec::new();
89 let mut frame_shapes = Vec::new();
90 let mut struct_shapes = Vec::new();
91 let mut debug_info = None;
92 let mut line_variant_groups = Vec::new();
93 let mut source_checksum = 0u32;
94
95 for inner in pair.into_inner() {
96 match inner.as_rule() {
97 Rule::story_checksum => {
98 if let Some(hex_pair) = inner.into_inner().next() {
99 source_checksum = primitives::parse_hex_u32(hex_pair.as_str());
100 }
101 }
102 Rule::name_table => name_table = defs::parse_name_table(inner)?,
103 Rule::globals => variables = defs::parse_globals(inner)?,
104 Rule::lists => list_defs = defs::parse_lists(inner)?,
105 Rule::list_items => list_items = defs::parse_list_items(inner)?,
106 Rule::externals => externals = defs::parse_externals(inner)?,
107 Rule::addresses => addresses = defs::parse_addresses(inner)?,
108 Rule::address_paths => address_paths = defs::parse_address_paths(inner)?,
109 Rule::list_literals => list_literals = defs::parse_list_literals(inner)?,
110 Rule::literal_pool => literal_pool = values::parse_literal_pool(inner)?,
111 Rule::struct_shapes => struct_shapes = defs::parse_struct_shapes(inner)?,
112 Rule::visibility => private_defs = defs::parse_visibility(inner)?,
113 Rule::alias_table => alias_table = defs::parse_alias_table(inner)?,
114 Rule::effect_rows => effect_rows = defs::parse_effect_rows(inner)?,
115 Rule::frame_shapes => frame_shapes = defs::parse_frame_shapes(inner)?,
116 Rule::debug_info => debug_info = Some(defs::parse_debug_info(inner)?),
117 Rule::line_variant_groups => {
118 line_variant_groups = defs::parse_line_variant_groups(inner)?;
119 }
120 Rule::container => {
121 let (line, col) = inner.line_col();
122 let (container, lt) = lines::parse_container(inner)?;
123 if !seen_container_ids.insert(container.id) {
124 return Err(InktParseError {
125 message: format!("duplicate container address: {}", container.id),
126 line,
127 col,
128 });
129 }
130 let is_scope_owner = container.scope_id == container.id;
131 containers.push(container);
132 if is_scope_owner {
135 line_tables.push(lt);
136 }
137 }
138 _ => {}
139 }
140 }
141
142 line_tables.sort_by_key(|lt| lt.scope_id.to_raw());
145
146 Ok(StoryData {
147 containers,
148 line_tables,
149 variables,
150 list_defs,
151 list_items,
152 externals,
153 addresses,
154 address_paths,
155 name_table,
156 list_literals,
157 literal_pool,
158 struct_shapes,
159 private_defs,
160 alias_table,
161 effect_rows,
162 frame_shapes,
163 debug_info,
164 line_variant_groups,
165 source_checksum,
166 })
167}