Skip to content

Commit 4873d73

Browse files
committed
Rewrote parse tree to engine tree converter
Updated testpad UI
1 parent 681c793 commit 4873d73

File tree

2 files changed

+138
-72
lines changed

2 files changed

+138
-72
lines changed

src/parser.js

Lines changed: 87 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,14 +1446,91 @@ function QMLBinding(src, tree) {
14461446
}
14471447

14481448

1449-
// Function to parse qml and output tree expected by engine
1450-
function parseQML(src) {
1451-
var parsetree = qmlparse(src);
1452-
1449+
// Convert parser tree to the format understood by engine
1450+
function convertToEngine(tree) {
1451+
1452+
// Help logger
14531453
function amIn(str, tree) {
1454-
console.log(str); if (tree) console.log(JSON.stringify(tree, null, " "));
1454+
console.log(str);
1455+
if (tree) console.log(JSON.stringify(tree, null, " "));
14551456
}
14561457

1458+
var walkers = {
1459+
"toplevel": function(statements) {
1460+
var item = { $class: "QMLDocument" };
1461+
// todo: imports etc
1462+
item.$children = [ walk(statements[0]) ];
1463+
return item;
1464+
},
1465+
"qmlelem": function(elem, statements) {
1466+
var item = { $class: elem,
1467+
$children: [],
1468+
$functions: {},
1469+
$properties: {} };
1470+
1471+
for (var i in statements) {
1472+
var statement = statements[i],
1473+
name = statement[1],
1474+
val = walk(statement);
1475+
switch (statement[0]) {
1476+
case "qmlprop":
1477+
item[name] = val;
1478+
break;
1479+
case "qmlelem":
1480+
item.$children.push(val);
1481+
break;
1482+
case "qmlmethod":
1483+
item.$functions[name] = val;
1484+
break;
1485+
case "qmlobjdef":
1486+
// Create object to item
1487+
item[name] = item[name] || {};
1488+
item[name][statement[2]] = val;
1489+
break;
1490+
case "qmlpropdef":
1491+
item.$properties[statement[2]] = val;
1492+
break;
1493+
default:
1494+
console.log("Unknown statement", statement);
1495+
1496+
}
1497+
}
1498+
1499+
return item;
1500+
},
1501+
"qmlprop": function(name, tree, src) {
1502+
if (name == "id") {
1503+
// id property
1504+
return tree[1][1];
1505+
}
1506+
return bindout(tree, src);
1507+
},
1508+
"qmlobjdef": function(name, property, tree, src) {
1509+
return bindout(tree, src);
1510+
},
1511+
"qmlmethod": function(name, tree, src) {
1512+
return src;
1513+
},
1514+
"qmlpropdef": function(name, type, tree) {
1515+
// todo: bindings are not detected
1516+
return { type: name,
1517+
value: tree[1] };
1518+
}
1519+
};
1520+
1521+
function walk(tree) {
1522+
var type = tree[0];
1523+
var walker = walkers[type];
1524+
if (!walker) {
1525+
console.log("No walker for " + type);
1526+
return;
1527+
} else {
1528+
return walker.apply(type, tree.slice(1));
1529+
}
1530+
}
1531+
1532+
return walk(tree);
1533+
14571534
function process(tree) {
14581535
var objs = {
14591536
toplevel: toplevel,
@@ -1490,72 +1567,12 @@ function parseQML(src) {
14901567
}
14911568
}
14921569

1493-
function qmlobjdef(tree) {
1494-
return bindout(tree[3], tree[4]);
1495-
}
1496-
1497-
function qmlprop(tree) {
1498-
// Special massage for id
1499-
if (tree[1] == "id") {
1500-
return tree[2][1][1];
1501-
}
1502-
return bindout(tree[2], tree[3]);
1503-
}
1504-
1505-
function qmlmethod(tree) {
1506-
return tree[3];
1507-
}
1508-
1509-
function qmlpropdef(tree) {
1510-
// TODO: bindings
1511-
return { type: tree[1],
1512-
value: tree[3][1] };
1513-
}
1514-
1515-
function qmlelem(tree, parent) {
1516-
var item = {
1517-
$class: tree[1],
1518-
$children: [],
1519-
$functions: {},
1520-
$properties: {} };
1521-
1522-
for (var i in tree[2]) {
1523-
var t = tree[2][i];
1524-
switch(t[0]) {
1525-
case "qmlprop":
1526-
item[t[1]] = process(t);
1527-
break;
1528-
case "qmlelem":
1529-
item.$children.push(process(t));
1530-
break;
1531-
case "qmlmethod":
1532-
item.$functions[t[1]] = process(t);
1533-
break;
1534-
case "qmlobjdef":
1535-
// Create object to item
1536-
item[t[1]] = item[t[1]] || {};
1537-
item[t[1]][t[2]] = process(t);
1538-
break;
1539-
case "qmlpropdef":
1540-
// Property definition
1541-
item.$properties[t[2]] = qmlpropdef(t);
1542-
break;
1543-
default:
1544-
console.log("Unknown element", t[0]);
1545-
}
1546-
}
1570+
}
15471571

1548-
return item;
1549-
}
1550-
1551-
function toplevel(tree, parent) {
1552-
var item = { $class: "QMLDocument" };
1553-
// only parse first element
1554-
item.$children = [ process(tree[1][0]) ];
1555-
return item;
1556-
}
1557-
1558-
return process(parsetree);
1572+
// Function to parse qml and output tree expected by engine
1573+
function parseQML(src) {
1574+
var parsetree = qmlparse(src);
1575+
return convertToEngine(parsetree);
15591576
}
15601577

15611578

test/testpad/testpad.html

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
<script src="../../src/parser.js"></script>
33
<script src="../../src/import.js"></script>
44
<script src="../../src/qtcore.js"></script>
5+
<style>
6+
.hidden {
7+
display: none;
8+
}
9+
</style>
510
</head>
611
<body>
712
<canvas id="canvas" style="border: 1px solid black"></canvas><br/>
@@ -13,6 +18,7 @@
1318

1419
Or write QML to textbox and
1520
<input type="button" onclick="loadFromSrcEl()" value="Run"/>
21+
<input type="button" onclick="toggleClass(srcEl, 'hidden')" value="Toggle source"/>
1622

1723
<td>
1824
<button onclick="document.location.href = 'viewer.html' + document.location.hash">View current file in QML viewer</button><br/>
@@ -37,10 +43,14 @@
3743
</table>
3844
<textarea id="src" rows=24 style="width: 100%"></textarea>
3945
<br/>
46+
4047
QML console.log:
48+
<input type="button" onclick="toggleClass(logEl, 'hidden')" value="Toggle log"/>
4149
<br/>
4250
<textarea id="log" rows=10 style="width: 100%" disabled></textarea>
51+
4352
Debug parse tree:
53+
<input type="button" onclick="toggleClass(treeEl, 'hidden')" value="Toggle tree"/>
4454
<br/>
4555
<textarea id="tree" rows=24 style="width: 100%" disabled></textarea>
4656
<script>
@@ -94,14 +104,49 @@
94104

95105
document.getElementById("browserId").innerHTML = navigator.userAgent;
96106

107+
// CSS class helpers
108+
function addClass(el, name) {
109+
var classes = el.className.split(" "),
110+
at = classes.indexOf(name);
111+
if (at == -1) {
112+
classes.push(name);
113+
el.className = classes.join(" ");
114+
}
115+
}
116+
function remClass(el, name) {
117+
var classes = el.className.split(" "),
118+
at = classes.indexOf(name);
119+
if (at != -1) {
120+
classes.splice(at, 1);
121+
el.className = classes.join(" ");
122+
}
123+
}
124+
function toggleClass(el, name) {
125+
(el.className.split(" ").indexOf(name) == -1
126+
? addClass
127+
: remClass)(el, name);
128+
}
129+
130+
131+
// Shows parser output in debug parse tree
97132
function ugparse() {
98-
treeEl.value = JSON.stringify(qmlparse(srcEl.value), null, " ");
133+
var out = qmlparse(srcEl.value),
134+
json = JSON.stringify(out, null, " ");
135+
console.log("Parse tree", out);
136+
console.log(json);
137+
treeEl.value = json;
99138
}
100139

140+
// Shows source tree in debug parse tree
101141
function parsetree() {
102-
treeEl.value = JSON.stringify(parseQML(srcEl.value), null, " ");
142+
var out = parseQML(srcEl.value),
143+
json = JSON.stringify(out, null, " ");
144+
console.log("Engine tree", out);
145+
console.log(json);
146+
treeEl.value = json;
103147
}
104148

149+
// Populates list of qml examples from files.json
105150
function populateQmlList() {
106151
var list = JSON.parse(getUrlContents("files.json"));
107152
var qmlList = document.getElementById("qmlList");
@@ -130,6 +175,7 @@
130175
}
131176
populateQmlList();
132177

178+
// Performance: draw to dummy canvas
133179
function dummyDraw() {
134180
function noop(){};
135181
var canvas = {
@@ -155,6 +201,7 @@
155201
alert("Elapsed: " + elapsed + " ms (" + (1000/(elapsed/1000)) + " fps)");
156202
}
157203

204+
// Performance: Draw to real canvas
158205
function basicDraw() {
159206
var started = new Date().getTime();
160207
for (var i = 0; i < 1000; i++) {
@@ -164,6 +211,8 @@
164211
alert("Elapsed: " + elapsed + " ms (" + (1000/(elapsed/1000)) + " fps)");
165212
}
166213

214+
// Performance: asynchronic draw
215+
// noDraw: true to measure asynchronic call rate only, false to draw, too.
167216
function asyncDraw(noDraw) {
168217
var started = new Date().getTime();
169218
var i = 0;

0 commit comments

Comments
 (0)