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)