include_checked_in_lalrpop_parser!(
#[allow(
clippy::empty_line_after_outer_attr,
clippy::type_complexity,
clippy::result_large_err
)]
sequence_grammar,
"sequence_grammar.rs"
);
const LINETYPE_NOTE: i32 = 2;
const LINETYPE_LOOP_START: i32 = 10;
const LINETYPE_LOOP_END: i32 = 11;
const LINETYPE_ALT_START: i32 = 12;
const LINETYPE_ALT_ELSE: i32 = 13;
const LINETYPE_ALT_END: i32 = 14;
const LINETYPE_OPT_START: i32 = 15;
const LINETYPE_OPT_END: i32 = 16;
const LINETYPE_ACTIVE_START: i32 = 17;
const LINETYPE_ACTIVE_END: i32 = 18;
const LINETYPE_PAR_START: i32 = 19;
const LINETYPE_PAR_AND: i32 = 20;
const LINETYPE_PAR_END: i32 = 21;
const LINETYPE_RECT_START: i32 = 22;
const LINETYPE_RECT_END: i32 = 23;
const LINETYPE_AUTONUMBER: i32 = 26;
const LINETYPE_CRITICAL_START: i32 = 27;
const LINETYPE_CRITICAL_OPTION: i32 = 28;
const LINETYPE_CRITICAL_END: i32 = 29;
const LINETYPE_BREAK_START: i32 = 30;
const LINETYPE_BREAK_END: i32 = 31;
const LINETYPE_PAR_OVER_START: i32 = 32;
const LINETYPE_CENTRAL_CONNECTION: i32 = 59;
const LINETYPE_CENTRAL_CONNECTION_REVERSE: i32 = 60;
const LINETYPE_CENTRAL_CONNECTION_DUAL: i32 = 61;
const PLACEMENT_LEFT_OF: i32 = 0;
const PLACEMENT_RIGHT_OF: i32 = 1;
const PLACEMENT_OVER: i32 = 2;
mod ast;
mod db;
mod lexer;
mod parse;
mod render_model;
use ast::Action;
pub(crate) use lexer::{LexError, Tok};
pub(crate) use parse::parse_sequence_json_and_editor_facts;
pub(crate) use parse::{parse_sequence, parse_sequence_model_for_render};
#[cfg(test)]
pub(crate) use parse::{
reset_sequence_syntax_construction_count, sequence_syntax_construction_count,
};
pub(crate) use render_model::render_model_to_compat_json;
pub use render_model::{
SequenceActor, SequenceAutonumber, SequenceBox, SequenceDiagramRenderModel, SequenceMessage,
SequenceMessagePayload, SequenceNote,
};
#[cfg(test)]
mod tests {
use super::render_model_to_compat_json;
use crate::{Engine, ParseOptions, RenderSemanticModel};
#[test]
fn parser_preserves_bracketed_block_titles_for_the_renderer() {
let parsed = Engine::new()
.parse_diagram_for_render_model_sync(
r#"sequenceDiagram
par [Action 1]
Alice->>Bob: First
and [Action 2]
Bob-->>Alice: Second
end"#,
ParseOptions::strict(),
)
.expect("parse should succeed")
.expect("sequence diagram should be detected");
let RenderSemanticModel::Sequence(model) = parsed.model() else {
panic!("expected typed Sequence render model");
};
assert_eq!(model.messages[0].message_text(), "[Action 1]");
assert_eq!(model.messages[2].message_text(), "[Action 2]");
}
#[test]
fn typed_render_model_projects_exact_compatibility_json() {
let source = r#"sequenceDiagram
title: Delivery
accTitle: Delivery sequence
autonumber 10 5
participant Alice
actor Bob
box rgb(240,240,240) Team
participant Carol
end
Alice->>Bob: Request
Note over Alice,Bob: Review
create participant Worker
Bob->>Worker: Start
destroy Worker
Worker-->>Bob: Done"#;
let engine = crate::Engine::new();
let compat = engine
.parse_diagram_sync(source, crate::ParseOptions::strict())
.unwrap()
.unwrap();
let typed = engine
.parse_diagram_for_render_model_sync(source, crate::ParseOptions::strict())
.unwrap()
.unwrap();
let crate::RenderSemanticModel::Sequence(model) = typed.model() else {
panic!("expected Sequence render model");
};
assert_eq!(
render_model_to_compat_json(model, typed.metadata()).unwrap(),
compat.model
);
}
}