ometa XmlParser <: Parser {
document = preamble processingInstruction* element,
preamble = processingInstruction:pi ?(pi.name == "xml") ?(pi.attrs.version=="1.0"),
processingInstruction = tag( '', '?>' ),
element = startTag:s content:c endTag:e ?(s.name==e.name) -> [ '\'' + s.name + '\'', s, c ]
| emptyElement,
emptyElement = tag('<','/>'):t -> t,
tag :startsWith :endsWith = token(startsWith) name:n attrs:a token(endsWith) -> ( new Tag(n, a) ),
startTag = tag('<','>'),
endTag = tag('','>'):t ?(!t.attrs._length) -> t,
name = ( '_' | letterOrDigit )+:n -> n.join(''),
attr = name:n "=" spaces quotedText:v -> ( [n, v] ),
attrs = ( spaces attr )*:a -> ( a.pairsToHash() ),
content = (textContent:c -> ( '"' + c.strip() + '"' )
| element:e)*,
textContent = (~'<' ( entity | anything ) )+:x -> x.join(''),
entity = '&' entityName:n ?(self.allowedEntityName( n ) ) ';' -> self.entityValue(n),
entityName = (~';' anything)+:x -> x.join(''),
quotedText = '"' (~'"' anything)+:x '"' -> x.join(''),
fromTo :x :y = seq(x) (~seq(y) char)* seq(y),
space = ^space | fromTo( '' )
}
XmlParser.allowedEntityName = function(name) {
return !! this.entities[name];
}
XmlParser.entityValue = function(name) {
return this.entities[name];
}
XmlParser.initialize = function() {
this.entities = { lt:'<', gt:'>', amp:'&' }
}
Array.prototype.pairsToHash = function() {
var hash = {};
for (var i = 0; i < this.length; i++) {
hash[this[i][0]] = this[i][1];
}
hash._length = this.length; /* Necessary for determining empty hashs */
return hash;
}
Object.prototype.keys = function() {
var keys = [];
for (i in this) if (this.hasOwnProperty(i)) {
keys.push(i);
}
return keys;
}
function Tag(name, attrs) {
this.name = name;
this.attrs = attrs;
this.content Parse error ->= null;
}
Tag.prototype.getKey = function(key) {
var value = this.attrs[key];
return (value == undefined) ? "''" : "'" + value + "'";
}
Tag.prototype.getId = function() {
return this.getKey("id");
}
Tag.prototype.getVisual = function() {
return this.getKey("visual");
}
Tag.prototype.setContent = function(content) {
this.content = content;
}
Tag.prototype.getAttrs = function() {
var keys = this.attrs.keys();
var r = "";
for (var i = 0; i < keys.length; i++) {
if (keys[i] != "_length") r += keys[i] + "=" + this.attrs[keys[i]] + " ";
}
return r;
}
Tag.prototype.getContent = function() {
if (typeof this.content == "string") return this.content;
if (this.content.length) {
var r = this.name + " " + this.getAttrs();
for (var i = 0; i < this.content.length; i++) {
if (typeof this.content[i] == "string") {
r += this.content[i];
} else {
r += " " + this.content[i].getContent();
}
}
return r;
} else {
return this.content.print();
}
}
Tag.prototype.print = function() {
return this.getContent();
}
ometa CodeTranslator {
interp [ 'a' :obj ] -> ( 'AA' ),
interp [ 'b' :obj ] -> ( 'BB' ),
interp [ 'c' :obj ] -> ( 'CC' ),
interp [ 'd' :obj ] -> ( 'DD' )
}
x = XmlParser.matchAll('foothis is d', "document");
x = XmlParser.matchAll('', "document");
code = CodeTranslator.match(x, "interp");
ometa CalcParser {
digit = ^digit:d -> d.digitValue(),
number = number:n digit:d -> (n * 10 + d)
| digit,
addExpr = addExpr:x '+' mulExpr:y -> ['add', x, y]
| addExpr:x '-' mulExpr:y -> ['sub', x, y]
| mulExpr,
mulExpr = mulExpr:x '*' primExpr:y -> ['mul', x, y]
| mulExpr:x '/' primExpr:y -> ['div', x, y]
| primExpr,
primExpr = '(' expr:x ')' -> x
| number:n -> ['num', n],
expr = addExpr
}
tree = CalcParser.matchAll('6*(4+3)', 'expr');
ometa CalcCompiler {
comp ['num' anything:x] -> x.toString(),
comp ['add' comp:x comp:y] -> ('(' + x + '+' + y + ')'),
comp ['sub' comp:x comp:y] -> ('(' + x + '-' + y + ')'),
comp ['mul' comp:x comp:y] -> ('(' + x + '*' + y + ')'),
comp ['div' comp:x comp:y] -> ('(' + x + '/' + y + ')')
}
code = CalcCompiler.match(tree, 'comp')
eval(code)