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.getId(), s.getVisual(), 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 = 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 { trans = [:t ] -> ans, a :id interp:t -> 'AA', b :id interp:t -> 'BB', c :id interp:t -> 'CC', d :id interp:t -> 'DD' } /*x = XmlParser.matchAll('foothis is d', "document"); */ x = XmlParser.matchAll('', "document"); code = CodeTranslator.match(x, "trans");