| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- // Package parser provides the main parser router for all diagram types
- package parser
- import (
- "fmt"
- "strings"
- "mermaid-go/pkg/ast"
- )
- // MermaidParser is the main parser that routes to specific diagram parsers
- type MermaidParser struct{}
- // NewMermaidParser creates a new main mermaid parser
- func NewMermaidParser() *MermaidParser {
- return &MermaidParser{}
- }
- // Parse parses a mermaid diagram string and returns the appropriate AST
- func (p *MermaidParser) Parse(input string) (ast.Diagram, error) {
- // Detect diagram type from the input
- diagramType := p.detectDiagramType(input)
- switch diagramType {
- case ast.DiagramTypeFlowchart:
- parser := NewFlowchartParser()
- return parser.Parse(input)
- case ast.DiagramTypeSequence:
- parser := NewSequenceParser()
- return parser.Parse(input)
- case ast.DiagramTypeClassDiagram:
- parser := NewClassParser()
- return parser.Parse(input)
- case ast.DiagramTypeStateDiagram:
- parser := NewStateParser()
- return parser.Parse(input)
- case ast.DiagramTypePie:
- parser := NewPieParser()
- return parser.Parse(input)
- case ast.DiagramTypeERDiagram:
- parser := NewERParser()
- return parser.Parse(input)
- case ast.DiagramTypeGantt:
- parser := NewGanttParser()
- return parser.Parse(input)
- case ast.DiagramTypeTimeline:
- parser := NewTimelineParser()
- return parser.Parse(input)
- case ast.DiagramTypeUserJourney:
- parser := NewJourneyParser()
- return parser.Parse(input)
- case ast.DiagramTypeArchitecture:
- parser := NewArchitectureParser()
- return parser.Parse(input)
- case ast.DiagramTypeOrganization:
- parser := NewOrganizationParser()
- return parser.Parse(input)
- case ast.DiagramTypeBPMN:
- parser := NewBPMNParser()
- return parser.Parse(input)
- default:
- return nil, fmt.Errorf("unsupported diagram type: %s", diagramType)
- }
- }
- // detectDiagramType analyzes the input to determine the diagram type
- func (p *MermaidParser) detectDiagramType(input string) ast.DiagramType {
- // Clean input and get first meaningful line
- lines := strings.Split(input, "\n")
- for _, line := range lines {
- line = strings.TrimSpace(line)
- if line == "" || strings.HasPrefix(line, "%%") {
- continue // Skip empty lines and comments
- }
- // Check for explicit diagram type declarations
- lowerLine := strings.ToLower(line)
- if strings.HasPrefix(lowerLine, "sequencediagram") {
- return ast.DiagramTypeSequence
- }
- if strings.HasPrefix(lowerLine, "classdiagram") {
- return ast.DiagramTypeClassDiagram
- }
- if strings.HasPrefix(lowerLine, "statediagram") {
- return ast.DiagramTypeStateDiagram
- }
- if strings.HasPrefix(lowerLine, "flowchart") ||
- strings.HasPrefix(lowerLine, "graph") {
- return ast.DiagramTypeFlowchart
- }
- if strings.HasPrefix(lowerLine, "erdiagram") {
- return ast.DiagramTypeERDiagram
- }
- if strings.HasPrefix(lowerLine, "journey") {
- return ast.DiagramTypeUserJourney
- }
- if strings.HasPrefix(lowerLine, "timeline") {
- return ast.DiagramTypeTimeline
- }
- if strings.HasPrefix(lowerLine, "gantt") {
- return ast.DiagramTypeGantt
- }
- if strings.HasPrefix(lowerLine, "pie") {
- return ast.DiagramTypePie
- }
- if strings.HasPrefix(lowerLine, "quadrantchart") {
- return ast.DiagramTypeQuadrant
- }
- if strings.HasPrefix(lowerLine, "requirementdiagram") {
- return ast.DiagramTypeRequirement
- }
- if strings.HasPrefix(lowerLine, "block") {
- return ast.DiagramTypeBlock
- }
- if strings.HasPrefix(lowerLine, "architecture") {
- return ast.DiagramTypeArchitecture
- }
- if strings.HasPrefix(lowerLine, "organization") || strings.HasPrefix(lowerLine, "orgchart") {
- return ast.DiagramTypeOrganization
- }
- if strings.HasPrefix(lowerLine, "bpmn") {
- return ast.DiagramTypeBPMN
- }
- // If no explicit type found, try to infer from content
- // This is a fallback for diagrams without explicit type declarations
- // Look for sequence diagram patterns
- if strings.Contains(lowerLine, "participant") ||
- strings.Contains(lowerLine, "actor") ||
- strings.Contains(lowerLine, "-->") ||
- strings.Contains(lowerLine, "->>") {
- return ast.DiagramTypeSequence
- }
- // Look for class diagram patterns
- if strings.Contains(lowerLine, "class ") ||
- strings.Contains(lowerLine, "--|>") ||
- strings.Contains(lowerLine, "--*") ||
- strings.Contains(lowerLine, "--o") {
- return ast.DiagramTypeClassDiagram
- }
- // Look for state diagram patterns
- if strings.Contains(lowerLine, "[*]") ||
- strings.Contains(lowerLine, "state ") {
- return ast.DiagramTypeStateDiagram
- }
- // Default to flowchart for backwards compatibility
- break
- }
- // Default fallback
- return ast.DiagramTypeFlowchart
- }
- // ParseWithType forces parsing with a specific diagram type
- func (p *MermaidParser) ParseWithType(input string, diagramType ast.DiagramType) (ast.Diagram, error) {
- switch diagramType {
- case ast.DiagramTypeFlowchart:
- parser := NewFlowchartParser()
- return parser.Parse(input)
- case ast.DiagramTypeSequence:
- parser := NewSequenceParser()
- return parser.Parse(input)
- case ast.DiagramTypeClassDiagram:
- parser := NewClassParser()
- return parser.Parse(input)
- case ast.DiagramTypeStateDiagram:
- parser := NewStateParser()
- return parser.Parse(input)
- case ast.DiagramTypePie:
- parser := NewPieParser()
- return parser.Parse(input)
- case ast.DiagramTypeERDiagram:
- parser := NewERParser()
- return parser.Parse(input)
- case ast.DiagramTypeGantt:
- parser := NewGanttParser()
- return parser.Parse(input)
- case ast.DiagramTypeTimeline:
- parser := NewTimelineParser()
- return parser.Parse(input)
- case ast.DiagramTypeUserJourney:
- parser := NewJourneyParser()
- return parser.Parse(input)
- case ast.DiagramTypeArchitecture:
- parser := NewArchitectureParser()
- return parser.Parse(input)
- case ast.DiagramTypeOrganization:
- parser := NewOrganizationParser()
- return parser.Parse(input)
- case ast.DiagramTypeBPMN:
- parser := NewBPMNParser()
- return parser.Parse(input)
- default:
- return nil, fmt.Errorf("unsupported diagram type: %s", diagramType)
- }
- }
|