Skip to content

Instantly share code, notes, and snippets.

@anko
Created June 15, 2016 00:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anko/1ef6db3b757f73a828e55f97da598575 to your computer and use it in GitHub Desktop.
Save anko/1ef6db3b757f73a828e55f97da598575 to your computer and use it in GitHub Desktop.
eslisp SXML macro implementation example

eslisp SXML macro implementation example

The module eslsxml.js exports a macro that reads its arguments as SXML syntax (partially implemented), and outputs a string with the equivalent XML.

This eslisp code (with the first SXML example from Wikipedia)—

(macro sxml (require "./eslsxml.js"))

((. console log)
 (sxml
  (tag (@ (attr1 "value1")
          (attr2 "value2"))
       (nested "Text node")
       (empty))))

—compiles to JavaScript as—

console.log('<tag attr1="value1" attr2="value2"><nested>Text node</nested><empty></empty></tag>');

Implementation hints for compiling to virtual DOM instead of a string

The example code could be adapted to return estree objects representing the appropriate function calls at line 41. Eslisp understands the more complex estree spec just as well as its own dead-simple {type: "string", value: 'whatever'} S-expression AST type.

function convertToplevel(node) {
switch (node.type) {
case 'string':
return node.value
case 'list':
var name = node.values[0].value
var rest = node.values.slice(1)
var attributes = []
var childNodes = []
rest.forEach(function(x) {
if ((x.type === 'list')
&& (x.values[0].value === '@')
&& (x.values[0].type === 'atom')) {
x.values.slice(1).forEach(function(attrPair) {
var key = attrPair.values[0].value
var value = attrPair.values[1].value
attributes.push(key + '="' + value + '"')
})
} else {
childNodes.push(convertToplevel(x))
}
})
var attributesString = attributes.join(' ')
var opening = '<' + name
+ (attributesString.length === 0 ? '' : ' ')
+ attributesString + '>'
var closing = '</' + name + '>'
return opening + childNodes.join('') + closing
}
}
module.exports = function() {
var args = Array.prototype.slice.call(arguments)
var stringified = args.map(convertToplevel).join('')
return {
type: 'string',
value: stringified
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment