1#![allow(clippy::upper_case_acronyms)]
2
3use super::Attributes;
5use super::ast::{
6 self, BitNum, Control, GuardComp as GC, GuardExpr, NumType,
7 StaticGuardExpr, Transition,
8};
9use crate::{
10 Attribute, Direction, PortDef, Primitive, Width,
11 attribute::SetAttribute,
12 attributes::ParseAttributeWrapper,
13 source_info::{
14 FileId as MetadataFileId, LineNum, PositionId, SourceInfoResult,
15 SourceInfoTable,
16 },
17};
18use calyx_utils::{self, CalyxResult, Id, PosString, float};
19use calyx_utils::{FileIdx, GPosIdx, GlobalPositionTable};
20use pest::pratt_parser::{Assoc, Op, PrattParser};
21use pest_consume::{Error, Parser, match_nodes};
22use std::io::Read;
23use std::path::Path;
24use std::str::FromStr;
25use std::{fs, path::PathBuf};
26
27type ParseResult<T> = Result<T, Error<Rule>>;
28type ComponentDef = ast::ComponentDef;
29
30type ParsedConnections = (
32 Vec<ast::Wire>,
33 Vec<ast::Group>,
34 Vec<ast::StaticGroup>,
35 Vec<ast::Fsm>,
36);
37
38#[derive(Clone)]
40struct UserData {
41 pub file: FileIdx,
43}
44
45type Node<'i> = pest_consume::Node<'i, Rule, UserData>;
48
49const _GRAMMAR: &str = include_str!("syntax.pest");
51
52lazy_static::lazy_static! {
55 static ref PRATT: PrattParser<Rule> =
56 PrattParser::new()
57 .op(Op::infix(Rule::guard_or, Assoc::Left))
58 .op(Op::infix(Rule::guard_and, Assoc::Left));
59}
60
61#[derive(Parser)]
62#[grammar = "syntax.pest"]
63pub struct CalyxParser;
64
65impl CalyxParser {
66 pub fn parse_file(path: &Path) -> CalyxResult<ast::NamespaceDef> {
68 let time = std::time::Instant::now();
69 let content = &fs::read(path).map_err(|err| {
70 calyx_utils::Error::invalid_file(format!(
71 "Failed to read {}: {err}",
72 path.to_string_lossy(),
73 ))
74 })?;
75 let string_content = std::str::from_utf8(content)?.to_string();
77 let file = GlobalPositionTable::add_file(
78 path.to_string_lossy().to_string(),
79 string_content,
80 );
81 let user_data = UserData { file };
82
83 let content = GlobalPositionTable::get_source(file);
84
85 let inputs =
87 CalyxParser::parse_with_userdata(Rule::file, content, user_data)
88 .map_err(|e| e.with_path(&path.to_string_lossy()))
89 .map_err(|e| {
90 calyx_utils::Error::parse_error(e.variant.message())
91 .with_pos(&Self::error_span(&e, file))
92 })?;
93 let input = inputs.single().map_err(|e| {
94 calyx_utils::Error::parse_error(e.variant.message())
95 .with_pos(&Self::error_span(&e, file))
96 })?;
97 let out = CalyxParser::file(input).map_err(|e| {
98 calyx_utils::Error::parse_error(e.variant.message())
99 .with_pos(&Self::error_span(&e, file))
100 })?;
101 log::info!(
102 "Parsed `{}` in {}ms",
103 path.to_string_lossy(),
104 time.elapsed().as_millis()
105 );
106 Ok(out)
107 }
108
109 pub fn parse<R: Read>(mut r: R) -> CalyxResult<ast::NamespaceDef> {
110 let mut buf = String::new();
111 r.read_to_string(&mut buf).map_err(|err| {
112 calyx_utils::Error::invalid_file(format!(
113 "Failed to parse buffer: {err}",
114 ))
115 })?;
116 let file = GlobalPositionTable::add_file("<stdin>".to_string(), buf);
118 let user_data = UserData { file };
119 let content = GlobalPositionTable::get_source(file);
120
121 let inputs =
123 CalyxParser::parse_with_userdata(Rule::file, content, user_data)
124 .map_err(|e| {
125 calyx_utils::Error::parse_error(e.variant.message())
126 .with_pos(&Self::error_span(&e, file))
127 })?;
128 let input = inputs.single().map_err(|e| {
129 calyx_utils::Error::parse_error(e.variant.message())
130 .with_pos(&Self::error_span(&e, file))
131 })?;
132 let out = CalyxParser::file(input).map_err(|e| {
133 calyx_utils::Error::parse_error(e.variant.message())
134 .with_pos(&Self::error_span(&e, file))
135 })?;
136 Ok(out)
137 }
138
139 fn get_span(node: &Node) -> GPosIdx {
140 let ud = node.user_data();
141 let sp = node.as_span();
142 let pos = GlobalPositionTable::add_pos(ud.file, sp.start(), sp.end());
143 GPosIdx(pos)
144 }
145
146 fn error_span(error: &pest::error::Error<Rule>, file: FileIdx) -> GPosIdx {
147 let (start, end) = match error.location {
148 pest::error::InputLocation::Pos(off) => (off, off + 1),
149 pest::error::InputLocation::Span((start, end)) => (start, end),
150 };
151 let pos = GlobalPositionTable::add_pos(file, start, end);
152 GPosIdx(pos)
153 }
154
155 #[allow(clippy::result_large_err)]
156 fn guard_expr_helper(
157 ud: UserData,
158 pairs: pest::iterators::Pairs<Rule>,
159 ) -> ParseResult<Box<GuardExpr>> {
160 PRATT
161 .map_primary(|primary| match primary.as_rule() {
162 Rule::term => {
163 Self::term(Node::new_with_user_data(primary, ud.clone()))
164 .map(Box::new)
165 }
166 x => unreachable!("Unexpected rule {:?} for guard_expr", x),
167 })
168 .map_infix(|lhs, op, rhs| {
169 Ok(match op.as_rule() {
170 Rule::guard_or => Box::new(GuardExpr::Or(lhs?, rhs?)),
171 Rule::guard_and => Box::new(GuardExpr::And(lhs?, rhs?)),
172 _ => unreachable!(),
173 })
174 })
175 .parse(pairs)
176 }
177
178 #[allow(clippy::result_large_err)]
179 fn static_guard_expr_helper(
180 ud: UserData,
181 pairs: pest::iterators::Pairs<Rule>,
182 ) -> ParseResult<Box<StaticGuardExpr>> {
183 PRATT
184 .map_primary(|primary| match primary.as_rule() {
185 Rule::static_term => Self::static_term(
186 Node::new_with_user_data(primary, ud.clone()),
187 )
188 .map(Box::new),
189 x => unreachable!(
190 "Unexpected rule {:?} for static_guard_expr",
191 x
192 ),
193 })
194 .map_infix(|lhs, op, rhs| {
195 Ok(match op.as_rule() {
196 Rule::guard_or => Box::new(StaticGuardExpr::Or(lhs?, rhs?)),
197 Rule::guard_and => {
198 Box::new(StaticGuardExpr::And(lhs?, rhs?))
199 }
200 _ => unreachable!(),
201 })
202 })
203 .parse(pairs)
204 }
205
206 #[cfg(test)]
207 pub fn parse_source_info_table(
209 input: &str,
210 ) -> Result<SourceInfoResult<SourceInfoTable>, Box<Error<Rule>>> {
211 let inputs = CalyxParser::parse_with_userdata(
212 Rule::source_info_table,
213 input,
214 UserData {
215 file: GlobalPositionTable::add_file("".into(), "".into()),
216 },
217 )?;
218 let input = inputs.single()?;
219 Ok(CalyxParser::source_info_table(input)?)
220 }
221}
222
223#[allow(clippy::large_enum_variant)]
224enum ExtOrComp {
225 Ext((Option<PosString>, Vec<Primitive>)),
226 Comp(ComponentDef),
227 PrimInline(Primitive),
228}
229
230#[pest_consume::parser]
231impl CalyxParser {
232 fn EOI(_input: Node) -> ParseResult<()> {
233 Ok(())
234 }
235
236 fn semi(_input: Node) -> ParseResult<()> {
237 Ok(())
238 }
239
240 fn comma_req(_input: Node) -> ParseResult<()> {
241 Ok(())
242 }
243 fn comma(input: Node) -> ParseResult<()> {
244 match_nodes!(
245 input.clone().into_children();
246 [comma_req(_)] => Ok(()),
247 [] => Err(input.error("expected comma"))
248 )
249 }
250
251 fn comb(_input: Node) -> ParseResult<()> {
252 Ok(())
253 }
254
255 fn static_word(_input: Node) -> ParseResult<()> {
256 Ok(())
257 }
258
259 fn reference(_input: Node) -> ParseResult<()> {
260 Ok(())
261 }
262
263 fn identifier(input: Node) -> ParseResult<Id> {
265 Ok(Id::new(input.as_str()))
266 }
267
268 fn bitwidth(input: Node) -> ParseResult<u64> {
269 input
270 .as_str()
271 .parse::<u64>()
272 .map_err(|_| input.error("Expected valid bitwidth"))
273 }
274
275 fn static_annotation(input: Node) -> ParseResult<std::num::NonZeroU64> {
276 Ok(match_nodes!(
277 input.into_children();
278 [static_word(_), latency_annotation(latency)] => latency,
279 ))
280 }
281
282 fn static_optional_latency(
283 input: Node,
284 ) -> ParseResult<Option<std::num::NonZeroU64>> {
285 Ok(match_nodes!(
286 input.into_children();
287 [static_word(_), latency_annotation(latency)] => Some(latency),
288 [static_word(_)] => None,
289 ))
290 }
291
292 fn both_comb_static(
293 input: Node,
294 ) -> ParseResult<Option<std::num::NonZeroU64>> {
295 Err(input.error("Cannot have both comb and static annotations"))
296 }
297
298 fn comb_or_static(
299 input: Node,
300 ) -> ParseResult<Option<std::num::NonZeroU64>> {
301 match_nodes!(
302 input.clone().into_children();
303 [both_comb_static(_)] => unreachable!("both_comb_static did not error"),
304 [comb(_)] => Ok(None),
305 [static_annotation(latency)] => Ok(Some(latency)),
306 )
307 }
308
309 fn bad_num(input: Node) -> ParseResult<u64> {
310 Err(input.error("Expected number with bitwidth (like 32'd10)."))
311 }
312
313 fn hex(input: Node) -> ParseResult<u64> {
314 u64::from_str_radix(input.as_str(), 16)
315 .map_err(|_| input.error("Expected hexadecimal number"))
316 }
317 fn decimal(input: Node) -> ParseResult<u64> {
318 #[allow(clippy::from_str_radix_10)]
319 u64::from_str_radix(input.as_str(), 10)
320 .map_err(|_| input.error("Expected decimal number"))
321 }
322 fn octal(input: Node) -> ParseResult<u64> {
323 u64::from_str_radix(input.as_str(), 8)
324 .map_err(|_| input.error("Expected octal number"))
325 }
326 fn binary(input: Node) -> ParseResult<u64> {
327 u64::from_str_radix(input.as_str(), 2)
328 .map_err(|_| input.error("Expected binary number"))
329 }
330
331 fn float(input: Node) -> ParseResult<String> {
335 Ok(input.as_str().to_string())
336 }
337
338 fn num_lit(input: Node) -> ParseResult<BitNum> {
339 let span = Self::get_span(&input);
340 let num = match_nodes!(
341 input.clone().into_children();
342 [bitwidth(width), decimal(val)] => BitNum {
343 width,
344 num_type: NumType::Decimal,
345 val,
346 span
347 },
348 [bitwidth(width), hex(val)] => BitNum {
349 width,
350 num_type: NumType::Hex,
351 val,
352 span
353 },
354 [bitwidth(width), octal(val)] => BitNum {
355 width,
356 num_type: NumType::Octal,
357 val,
358 span
359 },
360 [bitwidth(width), binary(val)] => BitNum {
361 width,
362 num_type: NumType::Binary,
363 val,
364 span
365 },
366
367 );
368
369 if num.width == 0
372 || (num.width < 64 && u64::pow(2, num.width as u32) <= num.val)
373 {
374 let lit_str = match num.num_type {
375 NumType::Binary => format!("{:b}", num.val),
376 NumType::Decimal => format!("{}", num.val),
377 NumType::Octal => format!("{:o}", num.val),
378 NumType::Hex => format!("{:x}", num.val),
379 };
380 let bit_plural = if num.width == 1 { "bit" } else { "bits" };
381 Err(input.error(format!(
382 "Cannot represent given literal '{}' in {} {}",
383 lit_str, num.width, bit_plural
384 )))
385 } else {
386 Ok(num)
387 }
388 }
389
390 fn char(input: Node) -> ParseResult<&str> {
391 Ok(input.as_str())
392 }
393
394 fn string_lit(input: Node) -> ParseResult<PosString> {
395 let span = Self::get_span(&input);
396 Ok(match_nodes!(
397 input.into_children();
398 [char(c)..] => PosString::new(c.collect::<Vec<_>>().join(""), span)
399 ))
400 }
401
402 fn attribute(input: Node) -> ParseResult<ParseAttributeWrapper> {
404 match_nodes!(
405 input.clone().into_children();
406 [string_lit(key), bitwidth(num)] => Attribute::from_str(key.as_ref()).map(|attr| (attr, num).into()).map_err(|e| input.error(format!("{e:?}"))),
407 [string_lit(key), attr_set(nums)] => {
408 let attr = SetAttribute::from_str(key.as_ref()).map_err(|e| input.error(format!("{e:?}")))?;
409 Ok((attr, nums).into())
410 }
411 )
412 }
413 fn attributes(input: Node) -> ParseResult<Attributes> {
414 match_nodes!(
415 input.clone().into_children();
416 [attribute(kvs)..] => kvs.collect::<Vec<_>>().try_into().map_err(|e| input.error(format!("{e:?}")))
417 )
418 }
419 fn name_with_attribute(input: Node) -> ParseResult<(Id, Attributes)> {
420 Ok(match_nodes!(
421 input.into_children();
422 [identifier(name), attributes(attrs)] => (name, attrs),
423 [identifier(name)] => (name, Attributes::default()),
424 ))
425 }
426
427 fn block_char(input: Node) -> ParseResult<&str> {
428 Ok(input.as_str())
429 }
430
431 fn block_string(input: Node) -> ParseResult<String> {
432 Ok(match_nodes!(
433 input.into_children();
434 [block_char(c)..] => c.collect::<String>().trim().to_string()
435 ))
436 }
437
438 fn attr_val(input: Node) -> ParseResult<u64> {
439 Ok(match_nodes!(
440 input.into_children();
441 [bitwidth(num)] => num
442 ))
443 }
444
445 fn attr_set(input: Node) -> ParseResult<Vec<u32>> {
446 Ok(match_nodes!(
447 input.into_children();
448 [bitwidth(num)..] => num.into_iter().map(|n| {let n_32: u32 = n.try_into().expect("set values must fit in a u32"); n_32}).collect()
449 ))
450 }
451
452 fn latency_annotation(input: Node) -> ParseResult<std::num::NonZeroU64> {
453 let num = match_nodes!(
454 input.clone().into_children();
455 [bitwidth(value)] => value,
456 );
457 if num == 0 {
458 Err(input.error("latency annotation of 0"))
459 } else {
460 Ok(std::num::NonZeroU64::new(num).unwrap())
461 }
462 }
463
464 fn at_attribute(input: Node) -> ParseResult<ParseAttributeWrapper> {
465 match_nodes!(
466 input.clone().into_children();
467 [identifier(key), attr_val(num)] => Attribute::from_str(key.as_ref()).map_err(|e| input.error(format!("{e:?}"))).map(|attr| (attr, num).into()),
468 [identifier(key), attr_set(nums)] => {
469 let attr = SetAttribute::from_str(key.as_ref()).map_err(|e| input.error(format!("{e:?}")))?;
470 Ok((attr, nums).into())
471 },
472 [identifier(key)] => Attribute::from_str(key.as_ref()).map_err(|e| input.error(format!("{e:?}"))).map(|attr| (attr, 1).into()),
473 )
474 }
475
476 fn at_attributes(input: Node) -> ParseResult<Attributes> {
477 match_nodes!(
478 input.clone().into_children();
479 [at_attribute(kvs)..] => kvs.collect::<Vec<_>>().try_into().map_err(|e| input.error(format!("{e:?}")))
480 )
481 }
482
483 fn params(input: Node) -> ParseResult<Vec<Id>> {
485 Ok(match_nodes!(
486 input.into_children();
487 [identifier(id)..] => id.collect()
488 ))
489 }
490
491 fn args(input: Node) -> ParseResult<Vec<u64>> {
492 Ok(match_nodes!(
493 input.into_children();
494 [bitwidth(bw)..] => bw.collect(),
495 [] => vec![]
496 ))
497 }
498
499 fn io_port(input: Node) -> ParseResult<(Id, Width, Attributes)> {
500 Ok(match_nodes!(
501 input.into_children();
502 [at_attributes(attrs), identifier(id), bitwidth(value)] =>
503 (id, Width::Const { value }, attrs),
504 [at_attributes(attrs), identifier(id), identifier(value)] =>
505 (id, Width::Param { value }, attrs)
506 ))
507 }
508
509 fn inputs(input: Node) -> ParseResult<Vec<PortDef<Width>>> {
510 Ok(match_nodes!(
511 input.into_children();
512 [io_port((name, width, attributes))] => {
513 let pd = PortDef::new(
514 name, width, Direction::Input, attributes
515 );
516 vec![pd]
517 },
518 [io_port((name, width, attributes)), comma(_), inputs(rest)] => {
519 let pd = PortDef::new(
520 name, width, Direction::Input, attributes
521 );
522 let mut v = vec![pd];
523 v.extend(rest);
524 v
525 }
526 ))
527 }
528
529 fn outputs(input: Node) -> ParseResult<Vec<PortDef<Width>>> {
530 Ok(match_nodes!(
531 input.into_children();
532 [io_port((name, width, attributes))] => {
533 let pd = PortDef::new(
534 name, width, Direction::Output, attributes
535 );
536 vec![pd]
537 },
538 [io_port((name, width, attributes)), comma(_), outputs(rest)] => {
539 let pd = PortDef::new(
540 name, width, Direction::Output, attributes
541 );
542 let mut v = vec![pd];
543 v.extend(rest);
544 v
545 }
546 ))
547 }
548
549 fn signature(input: Node) -> ParseResult<Vec<PortDef<Width>>> {
550 Ok(match_nodes!(
551 input.into_children();
552 [] => Vec::with_capacity(4),
555 [inputs(ins)] => ins ,
556 [outputs(outs)] => outs ,
557 [inputs(ins), outputs(outs)] => {
558 ins.into_iter().chain(outs.into_iter()).collect()
559 },
560 ))
561 }
562
563 fn sig_with_params(
565 input: Node,
566 ) -> ParseResult<(Vec<Id>, Vec<PortDef<Width>>)> {
567 Ok(match_nodes!(
568 input.into_children();
569 [params(p), signature(s)] => (p, s),
570 [signature(s)] => (vec![], s),
571 ))
572 }
573 fn primitive(input: Node) -> ParseResult<Primitive> {
574 let span = Self::get_span(&input);
575 Ok(match_nodes!(
576 input.into_children();
577 [name_with_attribute((name, attrs)), sig_with_params((p, s))] => Primitive {
578 name,
579 params: p,
580 signature: s,
581 attributes: attrs.add_span(span),
582 is_comb: false,
583 latency: None,
584 body: None,
585 },
586 [comb_or_static(cs_res), name_with_attribute((name, attrs)), sig_with_params((p, s))] => Primitive {
587 name,
588 params: p,
589 signature: s,
590 attributes: attrs.add_span(span),
591 is_comb: cs_res.is_none(),
592 latency: cs_res,
593 body: None,
594 }
595 ))
596 }
597
598 fn float_const(input: Node) -> ParseResult<ast::Cell> {
600 let span = Self::get_span(&input);
601 Ok(match_nodes!(
602 input.clone().into_children();
603 [
604 at_attributes(attrs),
605 identifier(id),
606 bitwidth(rep),
607 bitwidth(width),
608 float(val)
609 ] => {
610 let v = match float::parse(rep, width, val) {
611 Ok(v) => v,
612 Err(e) => return Err(input.error(format!("{e:?}")))
613 };
614 ast::Cell::from(
615 id,
616 Id::from("std_float_const"),
617 vec![rep, width, v],
618 attrs.add_span(span),
619 false
620 )
621 },
622 [
623 at_attributes(attrs),
624 reference(_),
625 identifier(id),
626 bitwidth(rep),
627 bitwidth(width),
628 float(val)
629 ] => {
630 let v = match float::parse(rep, width, val) {
631 Ok(v) => v,
632 Err(e) => return Err(input.error(format!("{e:?}")))
633 };
634 ast::Cell::from(
635 id,
636 Id::from("std_float_const"),
637 vec![rep, width, v],
638 attrs.add_span(span),
639 true
640 )},
641 ))
642 }
643
644 fn cell_without_semi(input: Node) -> ParseResult<ast::Cell> {
645 let span = Self::get_span(&input);
646 Ok(match_nodes!(
647 input.into_children();
648 [float_const(fl)] => fl,
649 [at_attributes(attrs), reference(_), identifier(id), identifier(prim), args(args)] =>
650 ast::Cell::from(id, prim, args, attrs.add_span(span),true),
651 [at_attributes(attrs), identifier(id), identifier(prim), args(args)] =>
652 ast::Cell::from(id, prim, args, attrs.add_span(span),false)
653 ))
654 }
655
656 fn cell(input: Node) -> ParseResult<ast::Cell> {
657 match_nodes!(
658 input.clone().into_children();
659 [cell_without_semi(_)] =>
660 Err(input.error("Declaration is missing `;`")),
661 [cell_without_semi(node), semi(_)] => Ok(node),
662 )
663 }
664
665 fn cells(input: Node) -> ParseResult<Vec<ast::Cell>> {
666 Ok(match_nodes!(
667 input.into_children();
668 [cell(cells)..] => cells.collect()
669 ))
670 }
671
672 fn port(input: Node) -> ParseResult<ast::Port> {
674 Ok(match_nodes!(
675 input.into_children();
676 [identifier(component), identifier(port)] =>
677 ast::Port::Comp { component, port },
678 [identifier(port)] => ast::Port::This { port }
679 ))
680 }
681
682 fn hole(input: Node) -> ParseResult<ast::Port> {
683 Ok(match_nodes!(
684 input.into_children();
685 [identifier(struct_elem), identifier(name)] => ast::Port::Hole { struct_elem, name }
686 ))
687 }
688
689 #[allow(clippy::upper_case_acronyms)]
690 fn LHS(input: Node) -> ParseResult<ast::Port> {
691 Ok(match_nodes!(
692 input.into_children();
693 [port(port)] => port,
694 [hole(hole)] => hole
695 ))
696 }
697
698 fn expr(input: Node) -> ParseResult<ast::Atom> {
699 match_nodes!(
700 input.into_children();
701 [LHS(port)] => Ok(ast::Atom::Port(port)),
702 [num_lit(num)] => Ok(ast::Atom::Num(num)),
703 [bad_num(_)] => unreachable!("bad_num returned non-error result"),
704 )
705 }
706
707 fn guard_eq(_input: Node) -> ParseResult<()> {
708 Ok(())
709 }
710 fn guard_neq(_input: Node) -> ParseResult<()> {
711 Ok(())
712 }
713 fn guard_leq(_input: Node) -> ParseResult<()> {
714 Ok(())
715 }
716 fn guard_geq(_input: Node) -> ParseResult<()> {
717 Ok(())
718 }
719 fn guard_lt(_input: Node) -> ParseResult<()> {
720 Ok(())
721 }
722 fn guard_gt(_input: Node) -> ParseResult<()> {
723 Ok(())
724 }
725
726 fn cmp_expr(input: Node) -> ParseResult<ast::CompGuard> {
727 Ok(match_nodes!(
728 input.into_children();
729 [expr(l), guard_eq(_), expr(r)] => (GC::Eq, l, r),
730 [expr(l), guard_neq(_), expr(r)] => (GC::Neq, l, r),
731 [expr(l), guard_geq(_), expr(r)] => (GC::Geq, l, r),
732 [expr(l), guard_leq(_), expr(r)] => (GC::Leq, l, r),
733 [expr(l), guard_gt(_), expr(r)] => (GC::Gt, l, r),
734 [expr(l), guard_lt(_), expr(r)] => (GC::Lt, l, r),
735 ))
736 }
737
738 fn guard_not(_input: Node) -> ParseResult<()> {
739 Ok(())
740 }
741
742 fn guard_expr(input: Node) -> ParseResult<Box<GuardExpr>> {
743 let ud = input.user_data().clone();
744 Self::guard_expr_helper(ud, input.into_pair().into_inner())
745 }
746
747 fn static_guard_expr(input: Node) -> ParseResult<Box<StaticGuardExpr>> {
748 let ud = input.user_data().clone();
749 Self::static_guard_expr_helper(ud, input.into_pair().into_inner())
750 }
751
752 fn term(input: Node) -> ParseResult<ast::GuardExpr> {
753 Ok(match_nodes!(
754 input.into_children();
755 [guard_expr(guard)] => *guard,
756 [cmp_expr((gc, a1, a2))] => ast::GuardExpr::CompOp((gc, a1, a2)),
757 [expr(e)] => ast::GuardExpr::Atom(e),
758 [guard_not(_), expr(e)] => {
759 ast::GuardExpr::Not(Box::new(ast::GuardExpr::Atom(e)))
760 },
761 [guard_not(_), cmp_expr((gc, a1, a2))] => {
762 ast::GuardExpr::Not(Box::new(ast::GuardExpr::CompOp((gc, a1, a2))))
763 },
764 [guard_not(_), guard_expr(e)] => {
765 ast::GuardExpr::Not(e)
766 },
767 [guard_not(_), expr(e)] =>
768 ast::GuardExpr::Not(Box::new(ast::GuardExpr::Atom(e)))
769 ))
770 }
771
772 fn static_term(input: Node) -> ParseResult<ast::StaticGuardExpr> {
773 Ok(match_nodes!(
774 input.into_children();
775 [static_timing_expr(interval)] => ast::StaticGuardExpr::StaticInfo(interval),
776 [static_guard_expr(guard)] => *guard,
777 [cmp_expr((gc, a1, a2))] => ast::StaticGuardExpr::CompOp((gc, a1, a2)),
778 [expr(e)] => ast::StaticGuardExpr::Atom(e),
779 [guard_not(_), expr(e)] => {
780 ast::StaticGuardExpr::Not(Box::new(ast::StaticGuardExpr::Atom(e)))
781 },
782 [guard_not(_), cmp_expr((gc, a1, a2))] => {
783 ast::StaticGuardExpr::Not(Box::new(ast::StaticGuardExpr::CompOp((gc, a1, a2))))
784 },
785 [guard_not(_), static_guard_expr(e)] => {
786 ast::StaticGuardExpr::Not(e)
787 },
788 [guard_not(_), expr(e)] =>
789 ast::StaticGuardExpr::Not(Box::new(ast::StaticGuardExpr::Atom(e)))
790 ))
791 }
792
793 fn switch_stmt(input: Node) -> ParseResult<ast::Guard> {
794 Ok(match_nodes!(
795 input.into_children();
796 [guard_expr(guard), expr(expr)] => ast::Guard { guard: Some(*guard), expr },
797 ))
798 }
799
800 fn static_switch_stmt(input: Node) -> ParseResult<ast::StaticGuard> {
801 Ok(match_nodes!(
802 input.into_children();
803 [static_guard_expr(guard), expr(expr)] => ast::StaticGuard { guard: Some(*guard), expr },
804 ))
805 }
806
807 fn wire(input: Node) -> ParseResult<ast::Wire> {
808 let span = Self::get_span(&input);
809 Ok(match_nodes!(
810 input.into_children();
811 [at_attributes(attrs), LHS(dest), expr(expr)] => ast::Wire {
812 src: ast::Guard { guard: None, expr },
813 dest,
814 attributes: attrs.add_span(span),
815 },
816 [at_attributes(attrs), LHS(dest), switch_stmt(src)] => ast::Wire {
817 src,
818 dest,
819 attributes: attrs.add_span(span),
820 }
821 ))
822 }
823
824 fn static_wire(input: Node) -> ParseResult<ast::StaticWire> {
825 let span = Self::get_span(&input);
826 Ok(match_nodes!(
827 input.into_children();
828 [at_attributes(attrs), LHS(dest), expr(expr)] => ast::StaticWire {
829 src: ast::StaticGuard { guard: None, expr },
830 dest,
831 attributes: attrs.add_span(span),
832 },
833 [at_attributes(attrs), LHS(dest), static_switch_stmt(src)] => ast::StaticWire {
834 src,
835 dest,
836 attributes: attrs.add_span(span),
837 }
838 ))
839 }
840
841 fn static_timing_expr(input: Node) -> ParseResult<(u64, u64)> {
842 Ok(match_nodes!(
843 input.into_children();
844 [bitwidth(single_num)] => (single_num, single_num+1),
845 [bitwidth(start_interval), bitwidth(end_interval)] => (start_interval, end_interval)
846 ))
847 }
848
849 fn group(input: Node) -> ParseResult<ast::Group> {
850 let span = Self::get_span(&input);
851 Ok(match_nodes!(
852 input.into_children();
853 [name_with_attribute((name, attrs)), wire(wire)..] => ast::Group {
854 name,
855 attributes: attrs.add_span(span),
856 wires: wire.collect(),
857 is_comb: false,
858 },
859 [comb(_), name_with_attribute((name, attrs)), wire(wire)..] => ast::Group {
860 name,
861 attributes: attrs.add_span(span),
862 wires: wire.collect(),
863 is_comb: true,
864 }
865 ))
866 }
867
868 fn static_group(input: Node) -> ParseResult<ast::StaticGroup> {
869 let span = Self::get_span(&input);
870 Ok(match_nodes!(
871 input.into_children();
872 [static_annotation(latency), name_with_attribute((name, attrs)), static_wire(wire)..] => ast::StaticGroup {
873 name,
874 attributes: attrs.add_span(span),
875 wires: wire.collect(),
876 latency,
877 }
878 ))
879 }
880
881 fn state_idx(input: Node) -> ParseResult<u64> {
883 input
884 .as_str()
885 .parse::<u64>()
886 .map_err(|_| input.error("Expected valid state index"))
887 }
888
889 fn transition_rule(
894 input: Node,
895 ) -> ParseResult<(Option<ast::GuardExpr>, u64)> {
896 Ok(match_nodes!(
897 input.into_children();
898 [guard_expr(guard_expr), state_idx(state)] => { let guard = Some(*guard_expr);
900 (guard, state)
901 },
902 [state_idx(state)] => { let guard = None; (guard, state)
905 }
906 ))
907 }
908
909 fn transition(input: Node) -> ParseResult<Transition> {
914 Ok(match_nodes!(
915 input.into_children();
916 [
917 state_idx(idx)
918 ] => {
919 ast::Transition::Unconditional(idx)
920 },
921 [
922 transition_rule(pairs)..,
923 ] => {
924 ast::Transition::Conditional(pairs.collect())
926 }
927 ))
928 }
929
930 fn state(input: Node) -> ParseResult<(u64, Vec<ast::Wire>, Transition)> {
934 Ok(match_nodes!(
935 input.into_children();
936 [
937 state_idx(idx),
938 wire(wires)..,
939 transition(trans)
940 ] => {
941 let state_wires : Vec<ast::Wire> = wires.collect();
942 (idx, state_wires, trans) }
944 ))
945 }
946
947 fn fsm(input: Node) -> ParseResult<ast::Fsm> {
950 let span = Self::get_span(&input);
951 Ok(match_nodes!(
952 input.into_children();
953 [name_with_attribute((name, attrs)), state(states)..] => {
954 let mut state_data = Vec::new();
955
956 for (state_idx, assignments, transition) in states {
957 let fsm_state = ast::FSMState {
958 assignments,
959 transition,
960 };
961 state_data.push((state_idx, fsm_state));
962 }
963 state_data.sort_by(|(idx1, _), (idx2, _)| idx1.cmp(idx2));
965 let fsm_states : Vec<ast::FSMState> = state_data.into_iter().map(|(_, r)| r).collect();
966
967 ast::Fsm {
968 name,
969 attributes: attrs.add_span(span),
970 fsm_states,
971 }
972 }
973 ))
974 }
975
976 fn connections(input: Node) -> ParseResult<ParsedConnections> {
978 let mut wires = Vec::new();
979 let mut groups = Vec::new();
980 let mut static_groups = Vec::new();
981 let mut fsms = Vec::new();
982 for node in input.into_children() {
983 match node.as_rule() {
984 Rule::wire => wires.push(Self::wire(node)?),
985 Rule::group => groups.push(Self::group(node)?),
986 Rule::static_group => {
987 static_groups.push(Self::static_group(node)?)
988 }
989 Rule::fsm => fsms.push(Self::fsm(node)?),
990 _ => unreachable!(),
991 }
992 }
993 Ok((wires, groups, static_groups, fsms))
994 }
995
996 fn invoke_arg(input: Node) -> ParseResult<(Id, ast::Atom)> {
998 Ok(match_nodes!(
999 input.into_children();
1000 [identifier(name), port(p)] => (name, ast::Atom::Port(p)),
1001 [identifier(name), num_lit(bn)] => (name, ast::Atom::Num(bn))
1002
1003 ))
1004 }
1005
1006 fn invoke_args(input: Node) -> ParseResult<Vec<(Id, ast::Atom)>> {
1007 Ok(match_nodes!(
1008 input.into_children();
1009 [invoke_arg(args)..] => args.collect()
1010 ))
1011 }
1012
1013 fn invoke_ref_arg(input: Node) -> ParseResult<(Id, Id)> {
1014 Ok(match_nodes!(
1015 input.into_children();
1016 [identifier(outcell), identifier(incell)] => (outcell, incell)
1017 ))
1018 }
1019
1020 fn invoke_ref_args(input: Node) -> ParseResult<Vec<(Id, Id)>> {
1021 Ok(match_nodes!(
1022 input.into_children();
1023 [invoke_ref_arg(args)..] => args.collect(),
1024 [] => Vec::new()
1025 ))
1026 }
1027
1028 fn invoke(input: Node) -> ParseResult<ast::Control> {
1029 let span = Self::get_span(&input);
1030 Ok(match_nodes!(
1031 input.into_children();
1032 [at_attributes(attrs), identifier(comp), invoke_ref_args(cells),invoke_args(inputs), invoke_args(outputs)] =>
1033 ast::Control::Invoke {
1034 comp,
1035 inputs,
1036 outputs,
1037 attributes: attrs.add_span(span),
1038 comb_group: None,
1039 ref_cells: cells
1040 },
1041 [at_attributes(attrs), identifier(comp), invoke_ref_args(cells),invoke_args(inputs), invoke_args(outputs), identifier(group)] =>
1042 ast::Control::Invoke {
1043 comp,
1044 inputs,
1045 outputs,
1046 attributes: attrs.add_span(span),
1047 comb_group: Some(group),
1048 ref_cells: cells
1049 },
1050 ))
1051 }
1052
1053 fn static_invoke(input: Node) -> ParseResult<ast::Control> {
1054 let span = Self::get_span(&input);
1055 Ok(match_nodes!(
1056 input.into_children();
1057 [at_attributes(attrs), static_optional_latency(latency), identifier(comp), invoke_ref_args(cells),invoke_args(inputs), invoke_args(outputs)] =>
1058 ast::Control::StaticInvoke {
1059 comp,
1060 inputs,
1061 outputs,
1062 attributes: attrs.add_span(span),
1063 ref_cells: cells,
1064 latency,
1065 comb_group: None,
1066 },
1067 [at_attributes(attrs), static_optional_latency(latency), identifier(comp), invoke_ref_args(cells),invoke_args(inputs), invoke_args(outputs), identifier(group)] =>
1068 ast::Control::StaticInvoke {
1069 comp,
1070 inputs,
1071 outputs,
1072 attributes: attrs.add_span(span),
1073 ref_cells: cells,
1074 latency,
1075 comb_group: Some(group),
1076 },
1077 ))
1078 }
1079
1080 fn empty(input: Node) -> ParseResult<ast::Control> {
1081 let span = Self::get_span(&input);
1082 Ok(match_nodes!(
1083 input.into_children();
1084 [at_attributes(attrs)] => ast::Control::Empty {
1085 attributes: attrs.add_span(span)
1086 }
1087 ))
1088 }
1089
1090 fn enable(input: Node) -> ParseResult<ast::Control> {
1091 let span = Self::get_span(&input);
1092 Ok(match_nodes!(
1093 input.into_children();
1094 [at_attributes(attrs), identifier(name)] => ast::Control::Enable {
1095 comp: name,
1096 attributes: attrs.add_span(span)
1097 }
1098 ))
1099 }
1100
1101 fn seq(input: Node) -> ParseResult<ast::Control> {
1102 let span = Self::get_span(&input);
1103 Ok(match_nodes!(
1104 input.into_children();
1105 [at_attributes(attrs), stmt(stmt)..] => ast::Control::Seq {
1106 stmts: stmt.collect(),
1107 attributes: attrs.add_span(span),
1108 }
1109 ))
1110 }
1111
1112 fn static_seq(input: Node) -> ParseResult<ast::Control> {
1113 let span = Self::get_span(&input);
1114 Ok(match_nodes!(
1115 input.into_children();
1116 [at_attributes(attrs), static_optional_latency(latency) ,stmt(stmt)..] => ast::Control::StaticSeq {
1117 stmts: stmt.collect(),
1118 attributes: attrs.add_span(span),
1119 latency,
1120 }
1121 ))
1122 }
1123
1124 fn par(input: Node) -> ParseResult<ast::Control> {
1125 let span = Self::get_span(&input);
1126 Ok(match_nodes!(
1127 input.into_children();
1128 [at_attributes(attrs), stmt(stmt)..] => ast::Control::Par {
1129 stmts: stmt.collect(),
1130 attributes: attrs.add_span(span),
1131 }
1132 ))
1133 }
1134
1135 fn static_par(input: Node) -> ParseResult<ast::Control> {
1136 let span = Self::get_span(&input);
1137 Ok(match_nodes!(
1138 input.into_children();
1139 [at_attributes(attrs), static_optional_latency(latency) ,stmt(stmt)..] => ast::Control::StaticPar {
1140 stmts: stmt.collect(),
1141 attributes: attrs.add_span(span),
1142 latency,
1143 }
1144 ))
1145 }
1146
1147 fn port_with(input: Node) -> ParseResult<(ast::Port, Option<Id>)> {
1148 Ok(match_nodes!(
1149 input.into_children();
1150 [port(port), identifier(cond)] => (port, Some(cond)),
1151 [port(port)] => (port, None),
1152 ))
1153 }
1154
1155 fn if_stmt(input: Node) -> ParseResult<ast::Control> {
1156 let span = Self::get_span(&input);
1157 Ok(match_nodes!(
1158 input.into_children();
1159 [at_attributes(attrs), port_with((port, cond)), block(stmt)] => ast::Control::If {
1160 port,
1161 cond,
1162 tbranch: Box::new(stmt),
1163 fbranch: Box::new(ast::Control::Empty { attributes: Attributes::default() }),
1164 attributes: attrs.add_span(span),
1165 },
1166 [at_attributes(attrs), port_with((port, cond)), block(tbranch), block(fbranch)] =>
1167 ast::Control::If {
1168 port,
1169 cond,
1170 tbranch: Box::new(tbranch),
1171 fbranch: Box::new(fbranch),
1172 attributes: attrs.add_span(span),
1173 },
1174 [at_attributes(attrs), port_with((port, cond)), block(tbranch), if_stmt(fbranch)] =>
1175 ast::Control::If {
1176 port,
1177 cond,
1178 tbranch: Box::new(tbranch),
1179 fbranch: Box::new(fbranch),
1180 attributes: attrs.add_span(span),
1181 },
1182
1183 ))
1184 }
1185
1186 fn static_if_stmt(input: Node) -> ParseResult<ast::Control> {
1187 let span = Self::get_span(&input);
1188 Ok(match_nodes!(
1189 input.into_children();
1190 [at_attributes(attrs), static_optional_latency(latency), port(port), block(stmt)] => ast::Control::StaticIf {
1191 port,
1192 tbranch: Box::new(stmt),
1193 fbranch: Box::new(ast::Control::Empty { attributes: Attributes::default() }),
1194 attributes: attrs.add_span(span),
1195 latency,
1196 },
1197 [at_attributes(attrs), static_optional_latency(latency), port(port), block(tbranch), block(fbranch)] =>
1198 ast::Control::StaticIf {
1199 port,
1200 tbranch: Box::new(tbranch),
1201 fbranch: Box::new(fbranch),
1202 attributes: attrs.add_span(span),
1203 latency,
1204 },
1205 [at_attributes(attrs), static_optional_latency(latency), port(port), block(tbranch), static_if_stmt(fbranch)] =>
1206 ast::Control::StaticIf {
1207 port,
1208 tbranch: Box::new(tbranch),
1209 fbranch: Box::new(fbranch),
1210 attributes: attrs.add_span(span),
1211 latency,
1212 }
1213 ))
1214 }
1215
1216 fn while_stmt(input: Node) -> ParseResult<ast::Control> {
1217 let span = Self::get_span(&input);
1218 Ok(match_nodes!(
1219 input.into_children();
1220 [at_attributes(attrs), port_with((port, cond)), block(stmt)] => ast::Control::While {
1221 port,
1222 cond,
1223 body: Box::new(stmt),
1224 attributes: attrs.add_span(span),
1225 }
1226 ))
1227 }
1228
1229 fn repeat_stmt(input: Node) -> ParseResult<ast::Control> {
1230 let span = Self::get_span(&input);
1231 Ok(match_nodes!(
1232 input.into_children();
1233 [at_attributes(attrs), bitwidth(num_repeats) , block(stmt)] => ast::Control::Repeat {
1234 num_repeats,
1235 body: Box::new(stmt),
1236 attributes: attrs.add_span(span),
1237 },
1238 [at_attributes(attrs), static_word(_), bitwidth(num_repeats) , block(stmt)] => ast::Control::StaticRepeat {
1239 num_repeats,
1240 body: Box::new(stmt),
1241 attributes: attrs.add_span(span),
1242 }
1243 ))
1244 }
1245
1246 fn stmt(input: Node) -> ParseResult<ast::Control> {
1247 Ok(match_nodes!(
1248 input.into_children();
1249 [enable(data)] => data,
1250 [empty(data)] => data,
1251 [invoke(data)] => data,
1252 [static_invoke(data)] => data,
1253 [seq(data)] => data,
1254 [static_seq(data)] => data,
1255 [par(data)] => data,
1256 [static_par(data)] => data,
1257 [if_stmt(data)] => data,
1258 [static_if_stmt(data)] => data,
1259 [while_stmt(data)] => data,
1260 [repeat_stmt(data)] => data,
1261 ))
1262 }
1263
1264 fn block(input: Node) -> ParseResult<ast::Control> {
1265 Ok(match_nodes!(
1266 input.into_children();
1267 [stmt(stmt)] => stmt,
1268 [stmts_without_block(seq)] => seq,
1269 ))
1270 }
1271
1272 fn stmts_without_block(input: Node) -> ParseResult<ast::Control> {
1273 match_nodes!(
1274 input.clone().into_children();
1275 [stmt(stmt)..] => Ok(ast::Control::Seq {
1276 stmts: stmt.collect(),
1277 attributes: Attributes::default(),
1278 })
1279 )
1280 }
1281
1282 fn control(input: Node) -> ParseResult<ast::Control> {
1283 Ok(match_nodes!(
1284 input.into_children();
1285 [block(stmt)] => stmt,
1286 [] => ast::Control::empty()
1287 ))
1288 }
1289
1290 fn component(input: Node) -> ParseResult<ComponentDef> {
1291 let span = Self::get_span(&input);
1292 match_nodes!(
1293 input.clone().into_children();
1294 [
1295 comb_or_static(cs_res),
1296 name_with_attribute((name, attributes)),
1297 signature(sig),
1298 cells(cells),
1299 connections(connections)
1300 ] => {
1301 if cs_res.is_some() {
1302 Err(input.error("Static Component must have defined control"))?;
1303 }
1304 let (continuous_assignments, groups, static_groups, fsms) = connections;
1305 let sig = sig.into_iter().map(|pd| {
1306 if let Width::Const { value } = pd.width {
1307 Ok(PortDef::new(
1308 pd.name(),
1309 value,
1310 pd.direction,
1311 pd.attributes
1312 ))
1313 } else {
1314 Err(input.error("Components cannot use parameters"))
1315 }
1316 }).collect::<Result<_, _>>()?;
1317 Ok(ComponentDef {
1318 name,
1319 signature: sig,
1320 cells,
1321 groups,
1322 static_groups,
1323 fsms,
1324 continuous_assignments,
1325 control: Control::empty(),
1326 attributes: attributes.add_span(span),
1327 is_comb: true,
1328 latency: None,
1329 })
1330 },
1331 [
1332 name_with_attribute((name, attributes)),
1333 signature(sig),
1334 cells(cells),
1335 connections(connections),
1336 control(control)
1337 ] => {
1338 let (continuous_assignments, groups, static_groups, fsms) = connections;
1339 let sig = sig.into_iter().map(|pd| {
1340 if let Width::Const { value } = pd.width {
1341 Ok(PortDef::new(
1342 pd.name(),
1343 value,
1344 pd.direction,
1345 pd.attributes
1346 ))
1347 } else {
1348 Err(input.error("Components cannot use parameters"))
1349 }
1350 }).collect::<Result<_, _>>()?;
1351 Ok(ComponentDef {
1352 name,
1353 signature: sig,
1354 cells,
1355 groups,
1356 static_groups,
1357 fsms,
1358 continuous_assignments,
1359 control,
1360 attributes: attributes.add_span(span),
1361 is_comb: false,
1362 latency: None,
1363 })
1364 },
1365 [
1366 comb_or_static(cs_res),
1367 name_with_attribute((name, attributes)),
1368 signature(sig),
1369 cells(cells),
1370 connections(connections),
1371 control(control),
1372 ] => {
1373 let (continuous_assignments, groups, static_groups, fsms) = connections;
1374 let sig = sig.into_iter().map(|pd| {
1375 if let Width::Const { value } = pd.width {
1376 Ok(PortDef::new(
1377 pd.name(),
1378 value,
1379 pd.direction,
1380 pd.attributes
1381 ))
1382 } else {
1383 Err(input.error("Components cannot use parameters"))
1384 }
1385 }).collect::<Result<_, _>>()?;
1386 Ok(ComponentDef {
1387 name,
1388 signature: sig,
1389 cells,
1390 groups,
1391 static_groups,
1392 fsms,
1393 continuous_assignments,
1394 control,
1395 attributes: attributes.add_span(span),
1396 is_comb: cs_res.is_none(),
1397 latency: cs_res,
1398 })
1399 },
1400 )
1401 }
1402
1403 fn imports(input: Node) -> ParseResult<Vec<PosString>> {
1404 Ok(match_nodes!(
1405 input.into_children();
1406 [string_lit(path)..] => path.collect()
1407 ))
1408 }
1409
1410 fn ext(input: Node) -> ParseResult<(Option<PosString>, Vec<Primitive>)> {
1411 Ok(match_nodes!(
1412 input.into_children();
1413 [string_lit(file), primitive(prims)..] => (Some(file), prims.collect())
1414 ))
1415 }
1416
1417 fn prim_inline(input: Node) -> ParseResult<Primitive> {
1418 let span = Self::get_span(&input);
1419 Ok(match_nodes!(
1420 input.into_children();
1421 [name_with_attribute((name, attrs)), sig_with_params((p, s)), block_string(b)] => {
1422 Primitive {
1423 name,
1424 params: p,
1425 signature: s,
1426 attributes: attrs.add_span(span),
1427 is_comb: false,
1428 latency: None,
1429 body: Some(b),
1430 }},
1431 [comb_or_static(cs_res), name_with_attribute((name, attrs)), sig_with_params((p, s)), block_string(b)] => Primitive {
1432 name,
1433 params: p,
1434 signature: s,
1435 attributes: attrs.add_span(span),
1436 is_comb: cs_res.is_none(),
1437 latency: cs_res,
1438 body: Some(b),
1439 }
1440 ))
1441 }
1442
1443 fn extern_or_component(input: Node) -> ParseResult<ExtOrComp> {
1444 Ok(match_nodes!(
1445 input.into_children();
1446 [component(comp)] => ExtOrComp::Comp(comp),
1447 [ext(ext)] => ExtOrComp::Ext(ext),
1448 [prim_inline(prim_inline)] => ExtOrComp::PrimInline(prim_inline),
1449 ))
1450 }
1451
1452 fn externs_and_comps(
1453 input: Node,
1454 ) -> ParseResult<impl Iterator<Item = ExtOrComp>> {
1455 Ok(match_nodes!(input.into_children();
1456 [extern_or_component(e)..] => e
1457 ))
1458 }
1459
1460 fn any_char(input: Node) -> ParseResult<String> {
1461 Ok(input.as_str().into())
1462 }
1463
1464 fn metadata_char(input: Node) -> ParseResult<String> {
1465 Ok(match_nodes!(input.into_children();
1466 [any_char(c)] => c,
1467 ))
1468 }
1469
1470 fn metadata(input: Node) -> ParseResult<String> {
1471 Ok(match_nodes!(input.into_children();
1472 [metadata_char(c)..] => c.collect::<String>().trim().into()
1473 ))
1474 }
1475
1476 fn path_text(input: Node) -> ParseResult<PathBuf> {
1479 Ok(PathBuf::from(input.as_str().trim()))
1480 }
1481
1482 fn file_entry(input: Node) -> ParseResult<(MetadataFileId, PathBuf)> {
1483 Ok(match_nodes!(input.into_children();
1484 [bitwidth(n), path_text(p)] => (MetadataFileId::new(n.try_into().expect("file ids must fit in a u32")), p)
1485 ))
1486 }
1487
1488 fn file_header(_input: Node) -> ParseResult<()> {
1489 Ok(())
1490 }
1491
1492 fn file_table(
1493 input: Node,
1494 ) -> ParseResult<impl IntoIterator<Item = (MetadataFileId, PathBuf)>> {
1495 Ok(match_nodes!(input.into_children();
1496 [file_header(_), file_entry(e)..] => e))
1497 }
1498
1499 fn position_header(_input: Node) -> ParseResult<()> {
1500 Ok(())
1501 }
1502
1503 fn position_entry(
1504 input: Node,
1505 ) -> ParseResult<(PositionId, MetadataFileId, LineNum)> {
1506 Ok(match_nodes!(input.into_children();
1507 [bitwidth(pos_num), bitwidth(file_num), bitwidth(line_no)] => {
1508 let pos_num = pos_num.try_into().expect("position ids must fit in a u32");
1509 let file_num = file_num.try_into().expect("file ids must fit in a u32");
1510 let line_no = line_no.try_into().expect("line numbers must fit in a u32");
1511 (PositionId::new(pos_num), MetadataFileId::new(file_num), LineNum::new(line_no))}
1512 ))
1513 }
1514
1515 fn position_table(
1516 input: Node,
1517 ) -> ParseResult<
1518 impl IntoIterator<Item = (PositionId, MetadataFileId, LineNum)>,
1519 > {
1520 Ok(match_nodes!(input.into_children();
1521 [position_header(_), position_entry(e)..] => e))
1522 }
1523
1524 fn source_info_table(
1525 input: Node,
1526 ) -> ParseResult<SourceInfoResult<SourceInfoTable>> {
1527 Ok(match_nodes!(input.into_children();
1528 [file_table(f), position_table(p)] => SourceInfoTable::new(f, p)
1529 ))
1530 }
1531
1532 fn extra_info(
1535 input: Node,
1536 ) -> ParseResult<(Option<String>, Option<SourceInfoTable>)> {
1537 Ok(match_nodes!(input.into_children();
1538 [metadata(m)] => (Some(m), None),
1539 [source_info_table(s)] => {
1540 if let Ok(s) = s {
1541 (None, Some(s))
1542 } else {
1543 log::error!("{}", s.unwrap_err());
1544 (None, None)
1545 }
1546 },
1547 [metadata(m), source_info_table(s)] => {
1548 if let Ok(s) = s {
1549 (Some(m), Some(s))
1550 } else {
1551 log::error!("{}", s.unwrap_err());
1552 (Some(m), None)
1553 }
1554 },
1555 [source_info_table(s), metadata(m)] => {
1556 if let Ok(s) = s {
1557 (Some(m), Some(s))
1558 } else {
1559 log::error!("{}", s.unwrap_err());
1560 (Some(m), None)
1561 }
1562 }
1563 ))
1564 }
1565
1566 fn file(input: Node) -> ParseResult<ast::NamespaceDef> {
1567 Ok(match_nodes!(
1568 input.into_children();
1569 [imports(imports), externs_and_comps(mixed), extra_info(info), EOI(_)] => {
1572 let (mut metadata, source_info_table) = info;
1573 if let Some(m) = &metadata {
1575 if m.is_empty() {
1576 metadata = None;
1577 }
1578 }
1579
1580 let mut namespace =
1581 ast::NamespaceDef {
1582 imports,
1583 components: Vec::new(),
1584 externs: Vec::new(),
1585 metadata,
1586 source_info_table
1587 };
1588 for m in mixed {
1589 match m {
1590 ExtOrComp::Ext(ext) => namespace.externs.push(ext),
1591 ExtOrComp::Comp(comp) => namespace.components.push(comp),
1592 ExtOrComp::PrimInline(prim) => {
1593 if let Some((_, prim_inlines)) = namespace.externs.iter_mut().find(|(filename, _)| filename.is_none()) {
1594 prim_inlines.push(prim)
1595 }
1596 else{
1597 namespace.externs.push((None, vec![prim]));
1598 }
1599 },
1600 }
1601 }
1602 namespace
1603 },
1604 [imports(imports), externs_and_comps(mixed), EOI(_)] => {
1605 let mut namespace =
1606 ast::NamespaceDef {
1607 imports,
1608 components: Vec::new(),
1609 externs: Vec::new(),
1610 metadata: None,
1611 source_info_table: None
1612 };
1613 for m in mixed {
1614 match m {
1615 ExtOrComp::Ext(ext) => namespace.externs.push(ext),
1616 ExtOrComp::Comp(comp) => namespace.components.push(comp),
1617 ExtOrComp::PrimInline(prim) => {
1618 if let Some((_, prim_inlines)) = namespace.externs.iter_mut().find(|(filename, _)| filename.is_none()) {
1619 prim_inlines.push(prim)
1620 }
1621 else{
1622 namespace.externs.push((None, vec![prim]));
1623 }
1624 },
1625 }
1626 }
1627 namespace
1628 },
1629
1630 ))
1631 }
1632}