use lalrpop_util::ErrorRecovery; use crate::{ CesFile, CesFileBlock, CesName, ImmediateDef, CesImmediate, CesInstance, PropBlock, PropValue, CapacitiesBlock, UnboundedBlock, WeightsBlock, InhibitorsBlock, HoldersBlock, Rex, ThinArrowRule, FatArrowRule, Polynomial, Node, BinOp, Literal, Token, AscesisError, AscesisErrorKind, }; grammar<'input, 'env>(errors: &'env mut Vec, AscesisError>>); // ces_file = { immediate_def | template_def | context_block } ; pub CesFile: CesFile = => <>.into(); pub CesFileBlock: CesFileBlock = { => <>.into(), => <>.into(), => <>.into(), => <>.into(), => <>.into(), => <>.into(), => <>.into(), ! => { errors.push(<>); CesFileBlock::Bad(AscesisErrorKind::ParsingFailure.into()) }, }; // Structure definition, immediate form // immediate_def = immediate_sig "{" { rex } "}" ; pub ImmediateDef: ImmediateDef = { "{" "}" => ImmediateDef::new(sig, Rex::new()), "{" "}" => ImmediateDef::new(sig, rex), }; // immediate_sig = "ces" identifier ; ImmediateSig: CesName = "ces" => CesName::from(<>); // Structure definition, template form // FIXME // template_def = template_sig "{" { rex } "}" ; // template_sig = "ces" identifier "(" { template_args } ")" ; // template_args = arg_decl { "," arg_decl } [ "," ] ; // arg_decl = identifier ":" ( "Node" | "CES" | "Size" | "String" ) ; // Structure instantiation // ces_immediate = identifier "(" ")" ; pub CesImmediate: CesImmediate = "(" ")" => CesImmediate::new(CesName::from(name)); // ces_instance = identifier "!" "(" { instance_args } ")" ; pub CesInstance: CesInstance = { "!" "(" ")" => CesInstance::new(CesName::from(name)), "!" "(" ")" => CesInstance::new(CesName::from(name)).with_args(args), }; // instance_args = arg_value { "," arg_value } [ "," ] ; InstanceArgs: Vec = { ","? => { let mut tail = tail; let mut result = vec![head]; result.append(&mut tail); result } }; CommaThenArgValue: String = "," ; // arg_value = identifier | size | string ; ArgValue: String = ; // Context // context_block = prop_block // | caps_block // | unbounded_block // | weights_block // | inhibit_block // | hold_block ; // prop_selector = "vis" | "sat" ; PropSelector: String = { "vis" => <>.into(), "sat" => <>.into(), }; // prop_block = prop_selector "{" { prop_list } "}" ; pub PropBlock: PropBlock = { "{" "}" => PropBlock::new().with_selector(sel), "{" "}" => blk.with_selector(sel), }; // prop_list = prop_field { "," prop_field } [ "," ] ; PropList: PropBlock = ","? => head.with_more(tail); CommaThenPropField: PropBlock = "," ; // prop_field = identifier ":" prop_value ; PropField: PropBlock = ":" => PropBlock::new().with_prop(key, value); // prop_value_array = prop_value { "," prop_value } [ "," ] ; PropValueArray: PropValue = ","? => head.into_array_with_more(tail); CommaThenPropValue: PropValue = "," ; // prop_value = name // | size_list // | node_list // | "[" prop_value_array "]" // | "{" prop_list "}" ; PropValue: PropValue = { =>? Ok(PropValue::new_name(<>)?), =>? Ok(PropValue::new_size_list(<>)?), =>? Ok(PropValue::new_node_list(<>)?), "[" "]" => <>.into(), "{" "}" => <>.into(), }; // caps_block = "caps" "{" { cap_list } "}" ; pub CapsBlock: CapacitiesBlock = { "caps" "{" "}" => CapacitiesBlock::new(), "caps" "{" ","? "}" => head.with_more(tail), }; // cap_list = cap_field { "," cap_field } [ "," ] ; CommaThenCapField: CapacitiesBlock = "," ; // cap_field = size node_list ; CapField: CapacitiesBlock = => CapacitiesBlock::new().with_nodes(size, nodes).unwrap(); // unbounded_block = "unbounded" "{" { node_list } "}" ; pub UnboundedBlock: UnboundedBlock = { "unbounded" "{" "}" => UnboundedBlock::new(), "unbounded" "{" "}" => UnboundedBlock::from_nodes(nodes).unwrap(), }; // weights_block = "weights" "{" { weight_list } "}" ; pub WeightsBlock: WeightsBlock = { "weights" "{" "}" => WeightsBlock::new(), "weights" "{" ","? "}" => head.with_more(tail), }; // weight_list = weight_field { "," weight_field } [ "," ] ; CommaThenWeightField: WeightsBlock = "," ; // weight_field = size node_list ( "->" | "<-" ) node_list ; WeightField: WeightsBlock = { "->" => WeightsBlock::new_effects(size, pre_nodes, post_set).unwrap(), "<-" => WeightsBlock::new_causes(size, post_nodes, pre_set).unwrap(), }; // inhibit_block = "inhibit" "{" { inhibit_list } "}" ; pub InhibitBlock: InhibitorsBlock = { "inhibit" "{" "}" => InhibitorsBlock::new(), "inhibit" "{" ","? "}" => head.with_more(tail), }; // inhibit_list = inhibit_field { "," inhibit_field } [ "," ] ; CommaThenInhibitField: InhibitorsBlock = "," ; // inhibit_field = node_list ( "->" | "<-" ) node_list ; InhibitField: InhibitorsBlock = { "->" => InhibitorsBlock::new_effects(pre_nodes, post_set).unwrap(), "<-" => InhibitorsBlock::new_causes(post_nodes, pre_set).unwrap(), }; // hold_block = "hold" "{" { hold_list } "}" ; pub HoldBlock: HoldersBlock = { "hold" "{" "}" => HoldersBlock::new(), "hold" "{" ","? "}" => head.with_more(tail), }; // hold_list = hold_field { "," hold_field } [ "," ] ; CommaThenHoldField: HoldersBlock = "," ; // hold_field = node_list ( "->" | "<-" ) node_list ; HoldField: HoldersBlock = { "->" => HoldersBlock::new_effects(pre_nodes, post_set).unwrap(), "<-" => HoldersBlock::new_causes(post_nodes, pre_set).unwrap(), }; // Rule expression // rex = thin_arrow_rule // | fat_arrow_rule // | rex_term { [ "+" ] rex_term } ; pub Rex: Rex = { => <>.into(), => <>.into(), )*> => head.with_more(tail), }; // rex_term = ces_immediate | ces_instance | "{" rex "}" ; RexTerm: Rex = { => <>.into(), => <>.into(), "{" "}", }; // Arrow rules // thin_arrow_rule = e_rule | c_rule | ec_rule | ce_rule | fw_rule | bw_rule ; // e_rule = node_list "->" polynomial ; // c_rule = node_list "<-" polynomial ; // ec_rule = node_list "->" polynomial "<-" polynomial ; // ce_rule = node_list "<-" polynomial "->" polynomial ; // fw_rule = "+" plain_polynomial "->" node_list "->" polynomial ; // bw_rule = "+" plain_polynomial "<-" node_list "<-" polynomial ; pub ThinArrowRule: ThinArrowRule = { // effect-only rule "->" => { ThinArrowRule::new().with_nodes(nodes).unwrap().with_effect(effect) }, // cause-only rule "<-" => { ThinArrowRule::new().with_nodes(nodes).unwrap().with_cause(cause) }, // effect-then-cause rule "->" "<-" => { ThinArrowRule::new().with_nodes(nodes).unwrap().with_cause(cause).with_effect(effect) }, // cause-then-effect rule "<-" "->" => { ThinArrowRule::new().with_nodes(nodes).unwrap().with_cause(cause).with_effect(effect) }, // forward rule "->" "->" => { ThinArrowRule::new().with_nodes(nodes).unwrap().with_cause(cause).with_effect(effect) }, // backward rule "<-" "<-" => { ThinArrowRule::new().with_nodes(nodes).unwrap().with_cause(cause).with_effect(effect) }, }; // fat_arrow_rule = polynomial ( "=>" | "<=" | "<=>" ) polynomial { ( "=>" | "<=" | "<=>" ) polynomial } ; pub FatArrowRule: FatArrowRule = )+> => FatArrowRule::from_parts(head, tail); // Polynomial // polynomial = [ [ polynomial ] "+" ] poly_term { poly_term } ; pub Polynomial: Polynomial = { AddOp? => head.with_product_multiplied(tail), AddOp => head.with_product_added(tail), }; // poly_term = identifier | "(" polynomial ")" ; #[inline] PolyTerm: Polynomial = { => Polynomial::from(Node::from(<>)), "(" ")", }; NodeList: Polynomial = ; // Operators AddOp: BinOp = "+" => BinOp::Add; ThinOp: BinOp = { "->" => BinOp::ThinTx, "<-" => BinOp::ThinRx }; FatOp: BinOp = { "=>" => BinOp::FatTx, "<=" => BinOp::FatRx, "<=>" => BinOp::FatDx }; // Identifiers IdentifierList: Vec = ; Identifier: String = r"[A-Za-z_][A-Za-z0-9_-]*" => <>.to_owned(); // Literals SizeList: Vec = ; FiniteSize: Literal = r"[0-9]+" => Literal::from_digits(<>).unwrap(); Omega: Literal = r"[Ωω]" => Literal::omega(); Theta: Literal = r"[Θθ]" => Literal::theta(); Size: Literal = { FiniteSize, Omega }; Name: Literal = r#""[^"]*""# => Literal::from_quoted_str(<>).unwrap(); extern { type Location = usize; type Error = AscesisError; enum Token<'input> { r"///.*\n" => Token::DocComment(<&'input str>), r"[A-Za-z_][A-Za-z0-9_-]*" => Token::Identifier(<&'input str>), r"[0-9]+" => Token::LiteralFiniteSize(<&'input str>), r#""[^"]*""# => Token::LiteralName(<&'input str>), r"[Ωω]" => Token::Omega, r"[Θθ]" => Token::Theta, ";" => Token::Semicolon, "," => Token::Comma, ":" => Token::Colon, "{" => Token::OpenCurly, "}" => Token::CloseCurly, "(" => Token::OpenParen, ")" => Token::CloseParen, "[" => Token::OpenBracket, "]" => Token::CloseBracket, "+" => Token::Add, "->" => Token::ThinArrow, "<-" => Token::ThinBackArrow, "=>" => Token::FatArrow, "<=" => Token::FatBackArrow, "<=>" => Token::FatTwowayArrow, "!" => Token::Bang, "ces" => Token::Ces, "vis" => Token::Vis, "sat" => Token::Sat, "caps" => Token::Caps, "unbounded" => Token::Unbounded, "weights" => Token::Weights, "inhibit" => Token::Inhibit, "hold" => Token::Hold, } }