Skip to content

Commit d63ca8d

Browse files
committed
Add trigger/complete expression language reference
Document the expression language used by the trigger and complete attributes as a dedicated, reference-level page in the User Manual. The specification is derived from the expression lexer/parser and the abstract syntax tree it produces, and covers the operands and operators, a two-layer (lexical and syntactic) EBNF grammar, operator precedence and associativity, and worked examples showing the fully-bracketed parse of representative expressions. Re ECFLOW-2112
1 parent b88d615 commit d63ca8d

5 files changed

Lines changed: 509 additions & 0 deletions

File tree

docs/_static/css/custom_style.css

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,26 @@ div.admonition.implementation > .admonition-title {
6767
background-color: #e0e0e0;
6868
color: #424242;
6969
}
70+
71+
/* Grammar (productionlist) blocks are rendered as a bare <pre> and can contain
72+
long lines; keep them within the content area by scrolling horizontally
73+
instead of overflowing past the right-hand border.
74+
The `grammar-pre` class is added by _static/js/grammar_terminals.js to the
75+
productionlist blocks only, so these rules do not affect other <pre> blocks. */
76+
.rst-content pre.grammar-pre {
77+
max-width: 100%;
78+
overflow-x: auto;
79+
white-space: pre;
80+
/* Match the size/metrics of code (highlight/literal) blocks: a bare <pre>
81+
(as produced by productionlist) otherwise renders at 1em, much larger. */
82+
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", Courier, monospace;
83+
font-size: 12px;
84+
line-height: 1.4;
85+
}
86+
87+
/* Terminal (quoted) symbols in the grammar productionlist blocks, wrapped by
88+
_static/js/grammar_terminals.js, are coloured blue to distinguish them from
89+
the non-terminals. */
90+
.rst-content pre.grammar-pre .grammar-terminal {
91+
color: #1565c0;
92+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Colourise terminal (quoted) symbols in grammar ``productionlist`` blocks.
2+
//
3+
// Sphinx renders a ``.. productionlist::`` as a bare <pre> in which the
4+
// non-terminals are <strong>/<a> elements but the terminal literals (e.g.
5+
// ":", "(", "and") are plain text with no markup to style. This script wraps
6+
// each double-quoted literal in a <span class="grammar-terminal"> so it can be
7+
// coloured via CSS, making terminals stand out from non-terminals.
8+
(function () {
9+
function colouriseTerminals(root) {
10+
var walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null);
11+
var textNodes = [];
12+
var node;
13+
while ((node = walker.nextNode())) {
14+
textNodes.push(node);
15+
}
16+
textNodes.forEach(function (textNode) {
17+
var text = textNode.nodeValue;
18+
if (text.indexOf('"') === -1) {
19+
return;
20+
}
21+
var frag = document.createDocumentFragment();
22+
var re = /"[^"]*"/g;
23+
var last = 0;
24+
var match;
25+
while ((match = re.exec(text)) !== null) {
26+
if (match.index > last) {
27+
frag.appendChild(document.createTextNode(text.slice(last, match.index)));
28+
}
29+
var span = document.createElement('span');
30+
span.className = 'grammar-terminal';
31+
span.textContent = match[0];
32+
frag.appendChild(span);
33+
last = re.lastIndex;
34+
}
35+
if (last < text.length) {
36+
frag.appendChild(document.createTextNode(text.slice(last)));
37+
}
38+
textNode.parentNode.replaceChild(frag, textNode);
39+
});
40+
}
41+
42+
function run() {
43+
var pres = document.querySelectorAll('.rst-content pre');
44+
Array.prototype.forEach.call(pres, function (pre) {
45+
// Only touch productionlist blocks (they contain grammar-token anchors).
46+
if (pre.querySelector('strong[id^="grammar-token"]')) {
47+
// Tag the block so the scoped CSS (see custom_style.css) applies to
48+
// grammar blocks only, not to every <pre> on the page.
49+
pre.classList.add('grammar-pre');
50+
colouriseTerminals(pre);
51+
}
52+
});
53+
}
54+
55+
if (document.readyState === 'loading') {
56+
document.addEventListener('DOMContentLoaded', run);
57+
} else {
58+
run();
59+
}
60+
})();

docs/conf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@
8484

8585
html_css_files = ["css/custom_style.css"]
8686

87+
html_js_files = ["js/grammar_terminals.js"]
88+
8789
html_logo = ""
8890

8991
highlight_language = "none"

docs/ug/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ User Manual
1515
user_manual/python_based_suite_definition/index.rst
1616
user_manual/node_attribute_overview
1717
user_manual/definition_file_format
18+
user_manual/expression_spec
1819
ecflow_ui/index.rst
1920
cookbook/index.rst
2021
elearning

0 commit comments

Comments
 (0)