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