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