calyx_frontend/
parser.rs

1#![allow(clippy::upper_case_acronyms)]
2
3//! Parser for Calyx programs.
4use 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
33/// Holds the results from parsing the `wires` section of a Calyx program.
34type ParsedConnections = (
35    Vec<ast::Wire>,
36    Vec<ast::Group>,
37    Vec<ast::StaticGroup>,
38    Vec<ast::Fsm>,
39);
40
41/// Data associated with parsing the file.
42#[derive(Clone)]
43struct UserData {
44    /// Index to the current file
45    pub file: FileIdx,
46}
47
48// user data is the input program so that we can create Id's
49// that have a reference to the input string
50type Node<'i> = pest_consume::Node<'i, Rule, UserData>;
51
52// include the grammar file so that Cargo knows to rebuild this file on grammar changes
53const _GRAMMAR: &str = include_str!("syntax.pest");
54
55// Define the precedence of binary operations. We use `lazy_static` so that
56// this is only ever constructed once.
57lazy_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    /// Parse a Calyx program into an AST representation.
70    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        // Add a new file to the position table
79        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        // Parse the file
89        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        // Save the input string to the position table
120        let file = GlobalPositionTable::add_file("<stdin>".to_string(), buf);
121        let user_data = UserData { file };
122        let content = GlobalPositionTable::get_source(file);
123
124        // Parse the input
125        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    /// A test helper for parsing the new metadata table
211    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    // ================ Literals =====================
267    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    // Floats are parsed as strings and converted within the float_const rule.
335    // This is so that we can check and see if the number can be represented
336    // exactly with the given bitwidth.
337    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        // the below cast is safe since the width must be less than 64 for
373        // the given literal to be unrepresentable
374        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    // ================ Attributes =====================
406    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    // ================ Signature =====================
487    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            // NOTE(rachit): We expect the signature to be extended to have `go`,
556            // `done`, `reset,`, and `clk`.
557            [] => 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    // ==============Primitives=====================
567    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    // ================ Cells =====================
602    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    // ================ Wires =====================
676    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    /// Parses in the state indices, which are unsigned integers in range `0..n`
885    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    /// Parses the conditional transitions, which are of form `GuardExpr ->` state index,
893    /// or the default case, `default ->` state index. The conditional transitions
894    /// are evaluated sequentially, so the default case is treated like an `else` or
895    /// like the default case of a verilog case statement.
896    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)] => { // guard branch
902                let guard = Some(*guard_expr);
903                (guard, state)
904            },
905            [state_idx(state)] => { // default branch
906                let guard = None; // default case has no guard, just true value 1'b1
907                (guard, state)
908            }
909        ))
910    }
911
912    /// Parses the transition block, which comes after the `=>` in the state.
913    /// Transitions are either `Unconditional` (will always transition to a future state
914    /// no matter the assignments) or `Conditional` (with boolean expressions denoted a
915    /// `guard_state_pair` and a default)
916    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                // collects the pairs in the order the parser reads them
928                ast::Transition::Conditional(pairs.collect())
929            }
930        ))
931    }
932
933    /// Parses a single state within the `fsm` block. A state is denoted with its
934    /// respective unsigned integer state index, which is is enumerated from `0..n`
935    /// States have assignments, which is a vector of `Wire`s, and transitions.
936    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) // we collect the state_idxs to use for sorting later
946            }
947        ))
948    }
949
950    /// Parses the `fsm` block to pull out the fsm block name, attributes, and list of rules.
951    /// A rule is the set of assignments and transitions each state within the `fsm` is assigned to.
952    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                // make sure to sort the rules by index to access the vector by state index.
967                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    /// Parses all the connections within the `wires` block of a Calyx program.
980    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    // ================ Control program =====================
1000    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    // Source Info Table
1480
1481    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    // end new metadata
1767
1768    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            // There really seems to be no straightforward way to resolve this
1804            // duplication
1805            [imports(imports), externs_and_comps(mixed), extra_info(info), EOI(_)] => {
1806                let (mut metadata, source_info_table) = info;
1807                // remove empty metadata strings
1808                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}