Module: MendixBridge::MdlParser

Defined in:
lib/mendix_bridge/mdl_parser.rb

Overview

Parses the widget tree out of a Mendix page MDL string.

Each widget node is a Hash:

{
"type"       => "dataview",          # MDL keyword (lowercase)
"name"       => "dv1",               # widget identifier (nil if anonymous)
"properties" => { "DataSource" => "$Customer", "Class" => "..." },
"children"   => [ ...widget nodes... ]
}

Usage:

tree  = MdlParser.parse_page_widgets(full_mdl_string)
names = MdlParser.flat_widget_names(tree)

Constant Summary collapse

STATEMENT_KEYWORDS =

Words that open MDL statements and are never widget type keywords.

%w[
  create or modify alter grant revoke drop select
].to_set.freeze
MULTI_WORD_QUALIFIERS =

Value qualifiers: first word of a multi-word property value.

%w[
  microflow nanoflow database association xpath show_page open_page
].to_set.freeze

Class Method Summary collapse

Class Method Details

.flat_widget_names(tree) ⇒ Object

Return a flat array of all named widget identifiers in the tree (DFS).



64
65
66
67
68
69
# File 'lib/mendix_bridge/mdl_parser.rb', line 64

def self.flat_widget_names(tree)
  tree.flat_map do |node|
    named = node["name"] ? [node["name"]] : []
    named + flat_widget_names(node["children"] || [])
  end
end

.flat_widgets(tree) ⇒ Object

Return a flat array of all widget nodes (named and anonymous), DFS.



72
73
74
75
76
# File 'lib/mendix_bridge/mdl_parser.rb', line 72

def self.flat_widgets(tree)
  tree.flat_map do |node|
    [node] + flat_widgets(node["children"] || [])
  end
end

.parse_page_widgets(full_mdl) ⇒ Object

Parse the full MDL of a page (including its CREATE / MODIFY header) and return the top-level widget tree extracted from the page body { }.



32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/mendix_bridge/mdl_parser.rb', line 32

def self.parse_page_widgets(full_mdl)
  sc = StringScanner.new(full_mdl.to_s)
  # Advance past 'page Module.Name ('
  unless sc.skip_until(/\bpage\s+[\w.]+\s*\(/i)
    return []
  end
  # Consume balanced settings (...) — opening ( already consumed by skip_until
  collect_balanced(sc, "(", ")")
  sc.skip(/\s*/)
  return [] unless sc.scan(/\{/)
  body = collect_balanced(sc, "{", "}")
  parse_widget_tree(body)
end

.parse_widget_tree(source) ⇒ Object

Parse a raw MDL body (content between outer braces) into a widget tree.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/mendix_bridge/mdl_parser.rb', line 47

def self.parse_widget_tree(source)
  sc = StringScanner.new(source.to_s)
  nodes = []
  until sc.eos?
    skip_ws_and_comments(sc)
    break if sc.eos?
    node = parse_widget_node(sc)
    if node
      nodes << node
    else
      sc.getch # skip unknown char and keep going
    end
  end
  nodes
end