Permalink
Browse files

new one-step parser

  • Loading branch information...
1 parent 17a1063 commit 9674958ae82d6f63cd2f7e2ff9af35bbb820a510 @lvivski committed Oct 3, 2012
View
@@ -1,3 +1,2 @@
/node_modules
-/lib/boss
-/lib/css
+/lib/parser.js
View
@@ -1,9 +1,2 @@
build:
- @mkdir -p lib/{boss,css}
- @node_modules/.bin/ometajs2js -b -i src/boss/parser.ometajs > lib/boss/parser.js
- @node_modules/.bin/ometajs2js -b -i src/boss/transformer.ometajs > lib/boss/transformer.js
- @node_modules/.bin/ometajs2js -b -i src/boss/translator.ometajs > lib/boss/translator.js
-
- @node_modules/.bin/ometajs2js -b -i src/css/parser.ometajs > lib/css/parser.js
- @node_modules/.bin/ometajs2js -b -i src/css/transformer.ometajs > lib/css/transformer.js
- @node_modules/.bin/ometajs2js -b -i src/css/translator.ometajs > lib/css/translator.js
+ @node_modules/.bin/ometajs2js -b -i lib/parser.ometajs > lib/parser.js
View
@@ -1,10 +1,4 @@
-var Parser = exports.Parser = require('./boss/parser').BOSSParser
-
-var Transformer = exports.Transformer = require('./boss/transformer').BOSSTransformer
-
-var Translator = exports.Translator = require('./boss/translator').BOSSTranslator
-
-var inspect = require('util').inspect
+var Parser = require('./parser').BOSSParser
, q = require('q')
, fs = require('fs')
, Env = require('./env')
@@ -27,9 +21,7 @@ exports.run = function run(options) {
}
var parse = exports.parse = function parse(source) {
- var ast = Parser.matchAll(source, "stylesheet")
- ast = Transformer.match(ast, "stylesheet")
- return Translator.match(ast, "stylesheet")
+ return Parser.matchAll(source, "stylesheet")
}
function mixin(filename) {
View
@@ -1,5 +1,5 @@
var BinOp = module.exports = function BinOp(op, left, right) {
- this.op = '' + op
+ this.op = op
this.left = left
this.right = right
}
View
@@ -22,6 +22,12 @@ var coercion = {
, s: {
ms: 1 / 1000
}
+ , rad: {
+ deg: Math.PI / 180
+ }
+ , deg: {
+ rad: 180 / Math.PI
+ }
}
Dimension.prototype = {
View
@@ -0,0 +1,284 @@
+var nodes = require('./nodes');
+
+ometa BOSSParser {
+
+ // Macros
+
+ m_comment = seq('/*') (~seq('*/') char)*:x seq('*/') -> ('/*' + x.join('') + '*/'),
+
+ m_ident = '-' (char:x m_nmstart(x) -> x):x (escape | :y m_nmchar(y) -> y)*:z -> ('-' + x + z.join(''))
+ | (char:x m_nmstart(x) -> x):x (escape | :y m_nmchar(y) -> y)*:z -> (x + z.join('')),
+
+ escape = '\\' char:x -> ('\\' + x),
+
+ m_name = (:x m_nmchar(x) -> x)+:xx -> xx.join(''),
+
+ m_name2 = (:x m_nmchar2(x) -> x)+:xx -> xx.join(''),
+
+ m_number = digit+:x '.' digit+:y -> (x.join('') + '.' + y.join(''))
+ | '.' digit+:x -> ('.' + x.join(''))
+ | digit+:x -> x.join(''),
+
+ m_string = '"' (m_string_nl1 | ~'"' char)*:s '"' -> ('"' + s.join('') + '"')
+ | '\'' (m_string_nl2 | ~'\'' char)*:s '\'' -> ('\'' + s.join('') + '\''),
+
+ m_string_nl1 = ('\n' | '\r' | seq('\\"')):x -> x,
+ m_string_nl2 = ('\n' | '\r' | seq('\\\'')):x -> x,
+
+ m_nmstart :x = ?BOSSParser._m_nmstart(x),
+ m_unicode :x = ?BOSSParser._m_unicode(x),
+ m_escape :x = ?BOSSParser._m_escape(x),
+ m_nmchar :x = ?BOSSParser._m_nmchar(x),
+ m_nmchar2 :x = ?BOSSParser._m_nmchar2(x),
+ m_nl :x = ?BOSSParser._m_nl(x),
+ m_w :x = ?BOSSParser._m_w(x),
+
+ // Tokens
+
+ ident = m_ident:x -> new nodes.Ident(x),
+
+ atkeyword = '@' ident:x -> '@' + x,
+
+ string = m_string:x -> new nodes.String(x.slice(1, -1), x[0]),
+
+ shash = '#' m_name:x -> '#' + x,
+
+ vhash = '#' m_name2:x -> new nodes.Color(x),
+
+ number = m_number:x -> new nodes.Dimension(x),
+
+ percentage = m_number:x '%' -> new nodes.Dimension(x, '%'),
+
+ dimension = m_number:x m_name2:y -> new nodes.Dimension(x, y),
+
+ cdo = seq('<!--') -> '<!--',
+ cdc = seq('-->') -> '-->',
+
+ s = (:x m_w(x) -> x)+:xx -> xx.join(''),
+
+ attrselector = (seq('=') | seq('~=') | seq('^=') | seq('$=') | seq('*=') | seq('|=')):x -> x,
+
+ delim = ',' -> ',',
+
+ comment = seq('/*') (~seq('*/') char)*:x seq('*/') -> new nodes.Comment(x.join('')),
+
+ sc = s | comment,
+
+ tset = vhash | any | sc | operator,
+
+ stylesheet = (cdo | cdc | sc | statement)*:x -> new nodes.Stylesheet( BOSSParser.filter(x) ),
+
+ definition = ident:x '(' functionBody:y ')' sc* block:z -> new nodes.Definition(x.name, y, z),
+
+ assignment = property:p '=' value:v decldelim? sc* -> new nodes.Ident(p, v),
+
+ variable = '$' ident:x -> x,
+
+ statement = definition | ruleset | atrule | assignment,
+
+ atrulerq = tset*:ap -> ap.join(''),
+
+ atruleb = atkeyword:ak atrulerq:aq block:b -> new nodes.Atrule(ak + aq, b),
+
+ atrules = atkeyword:ak atrulerq:aq ';' -> new nodes.Atrule(ak + aq),
+
+ atrule = atruleb | atrules,
+
+ blockdecl = sc* (filter | declaration):x decldelim? sc* -> x
+ | sc* ruleset:x sc* -> x
+ | sc* decldelim sc* -> ' '
+ | sc+:s0 -> ' ',
+
+ decldelim = ';' -> ';',
+
+ block = '{' blockdecl*:x '}' -> new nodes.Block(x),
+
+ ruleset = selector:s block:b -> new nodes.Ruleset(s, b),
+
+ combinator = ('+' | '>' | '~' | '&'):x -> x,
+
+ attrib = '[' sc* ident:x sc* attrselector:a sc* (ident | string):y sc* ']' -> '[' + [x, a, y].join('') + ']'
+ | '[' sc* ident:x sc* ']' -> '[' + x.join('') + ']',
+
+ clazz = '.' ident:x -> '.' + x,
+
+ pseudoe = seq('::') ident:x -> '::' + x,
+
+ pseudoc = ':' (pseudof | ident):x -> ':' + x,
+
+ pseudof = ident:x '(' pseudofBody:y ')' -> new nodes.Call(x.name, y),
+
+ pseudofBody = (simpleselector)*:x -> BOSSParser.createExpression( BOSSParser.filter(x) , true),
+
+ pseudo = pseudoe | pseudoc,
+
+ nthf = ':' seq('nth-'):x (seq('child') | seq('last-child') | seq('of-type') | seq('last-of-type')):y -> x + y,
+
+ nth = (digit | 'n')+:x -> x.join('')
+ | (seq('even') | seq('odd')):x -> x,
+
+ nthselector = nthf:x '(' (sc | ('+' | '-'):op -> new nodes.Literal(op) | nth)*:y ')'
+ -> ':' + new nodes.Ident(x) + '(' +y.join('') + ')',
+
+ namespace = '|' -> '|',
+
+ simpleselector = (nthselector | combinator | attrib | pseudo | clazz | shash | any | sc | namespace)+:x
+ -> new nodes.Selector(x),
+
+ selector = (simpleselector | delim)+:x -> x.filter(function (selector) { return selector !== ',' }),
+
+ declaration = property:x ':' value:y -> new nodes.Declaration(x, y),
+
+ filterp = (seq('-filter') | seq('_filter') | seq('*filter') | seq('-ms-filter') | seq('filter')):t sc*
+ -> new nodes.Ident(t),
+
+ progid = sc* seq('progid:DXImageTransform.Microsoft.'):x letter+:y '(' (m_string | m_comment | ~')' char)+:z ')' sc*
+ -> new nodes.Literal(x + y.join('') + '(' + z.join('') + ')'),
+
+ filterv = progid+:x -> x,
+
+ filter = filterp:x ':' filterv:y -> new nodes.Declaration(p, v),
+
+ property = (ident | variable):x sc* -> x.toString(),
+
+ important = '!' sc* seq('important') -> new nodes.Literal('!important'),
+
+ primary = percentage | dimension | number,
+
+ unary = ('-' | '+'):op primary:x -> x.operate('*', new nodes.Dimension(op + 1))
+ | primary,
+
+ multiplicative = multiplicative:x sc+ ('*' | '/' | '%'):op sc+ unary:y -> new nodes.BinOp(op, x, y)
+ | unary,
+
+ additive = additive:x sc+ ('+' | '-'):op sc+ multiplicative:y -> new nodes.BinOp(op, x, y)
+ | multiplicative,
+
+ expression = additive,
+
+ operator = ('/' | ',' | ':' | '='):x -> new nodes.Literal(x),
+
+ uri = seq('url(') sc* string:x sc* ')' -> new nodes.Call('url', new nodes.Arguments(false, [x]))
+ | seq('url(') sc* (~')' ~m_w char)*:x sc* ')'
+ -> new nodes.Call('url', new nodes.Arguments(false, [new nodes.Literal(x.join(''))])),
+
+ value = (sc | vhash | any | block | atkeyword | operator | important)+:x
+ -> BOSSParser.createExpression( BOSSParser.filter(x) ),
+
+ funktion = ident:x '(' functionBody:y ')' -> new nodes.Call(x.name, y),
+
+ functionBody = (tset | clazz)*:x -> BOSSParser.createExpression( BOSSParser.filter(x) , true),
+
+ braces = '(' tset*:x ')' -> '(' + x.join('') + ')'
+ | '[' tset*:x ']' -> '[' + x.join('') + ']',
+
+// Don't reuse CSS-grammar elements to parse JS-grammar basics!
+
+ jsLT = '\n' | '\r',
+
+ jsComment = jsMLComment | jsSLComment,
+
+ jsMLComment = ``/*'' (~``*/'' char)*:x ``*/'' -> ('/*' + x.join('') + '*/'),
+
+ jsSLComment = ``//'' (~jsLT char)*:x -> ('//' + x.join('')),
+
+ jsString = '"' jsDSChar*:x '"' -> ('"' + x.join('') + '"')
+ | '\'' jsSSChar*:x '\'' -> ('\'' + x.join('') + '\''),
+
+ jsDSChar = ~'"' ~'\\' ~jsLT char
+ | jsEscapeChar
+ | jsLineContinuation,
+
+ jsSSChar = ~'\'' ~'\\' ~jsLT char
+ | jsEscapeChar
+ | jsLineContinuation,
+
+ jsLineContinuation = '\\' jsLT*:x -> ('\\' + x.join('')),
+
+ jsEscapeChar = '\\' char:x -> ('\\' + x),
+
+ jsInBraceChar = ~'(' ~')' char:x -> x,
+
+ jsBracesContent = (jsComment | jsString | jsEscapeChar | jsInBraceChar)+:x -> x.join(''),
+
+ functionExpressionBody = '(' jsBracesContent*:x (
+ functionExpressionBody:y jsBracesContent*:z -> (y + z.join(''))
+ )*:xx
+ ')' -> ('(' + x.join('') + xx.join('') + ')')
+ | jsBracesContent*:x functionExpressionBody:y jsBracesContent*:z -> (x.join('') + y + z.join(''))
+ | jsBracesContent+:x -> x.join(''),
+
+ functionExpression = ``expression('' functionExpressionBody*:x ')' -> 'expression(' + x.join('') + ')',
+
+ any = braces | string | expression | uri | functionExpression | funktion | ident | variable
+}
+
+BOSSParser.concat = function() {
+ var x = [];
+ for (var i in arguments) {
+ x = x.concat(arguments[i]);
+ };
+
+ return x;
+};
+
+// CSS 2.1 / 4.1.1 Tokenization / macro section
+
+// [_a-z]|{nonascii}|{escape}
+BOSSParser._m_nmstart = function(x) {
+ return /^[_a-zA-Z\*]+$/.test(x) || this._m_escape(x);
+};
+
+// \\[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
+BOSSParser._m_unicode = function(x) {
+ return /^\\[0-9a-fA-F]{1,6}(\r\n|[ \n\r\t\f])?$/.test(x);
+};
+
+// {unicode}|\\[^\n\r\f0-9a-f]
+BOSSParser._m_escape = function(x) {
+ return this._m_unicode(x) || /^\\[^\n\r\f0-9a-fA-F]+$/.test(x);
+}
+
+// [_a-z0-9-]|{nonascii}|{escape}
+BOSSParser._m_nmchar = function(x) {
+ return /^[_a-zA-Z0-9\-]+$/.test(x) || this._m_escape(x);
+};
+
+// [a-z0-9]|{nonascii}|{escape}
+BOSSParser._m_nmchar2 = function(x) {
+ return /^[a-zA-Z0-9]+$/.test(x) || this._m_escape(x);
+};
+
+// [\n\r\f]
+BOSSParser._m_nl = function(x) {
+ return /^[\n\r\f]+$/.test(x);
+};
+
+// [ \t\r\n\f]*
+BOSSParser._m_w = function(x) {
+ return /^[ \t\r\n\f]+$/.test(x);
+};
+
+BOSSParser.createExpression = function (x, isArgs) {
+ var ctor = isArgs ? 'Arguments' : 'Expression',
+ expr = new nodes[ctor],
+ list = isArgs ? new nodes[ctor](true) : undefined;
+
+ x.forEach(function (node) {
+ if (node.value === ',') {
+ list = list || new nodes[ctor](true);
+ list.push(expr);
+ expr = new nodes.Expression;
+ return;
+ }
+ expr.push(node);
+ })
+
+ list && list.push(expr);
+
+ return list || expr;
+}
+
+BOSSParser.filter = function (arr) {
+ return arr.filter(function (any) { return !(typeof any === 'string' && /^[\n\s]+$/.test(any)) })
+}
View
@@ -1,51 +0,0 @@
-var CSSParser = require('../css/parser').CSSParser;
-
-ometa BOSSParser <: CSSParser {
-
- statement = definition | ruleset | atrule | assignment,
-
- definition = ident:x '(' functionBody:y ')' sc* block:z -> [#definition, x, y, z],
-
- string = m_string:x -> [#string, x.slice(1, -1), x[0]],
-
- variable = '$' ident:x -> [#variable, x],
-
- combinator = ('+' | '>' | '~' | '&'):x -> [#combinator, x],
-
- property = (ident | variable):x sc* -> [#property, x],
-
- assignment = property:p '=' value:v decldelim? sc* -> [#assignment, p, v],
-
- important = '!' sc* seq('important') -> [#important],
-
- primary = percentage | dimension | number,
-
- unary = ('-' | '+'):op primary:x -> [#unary, [#operator, op], x]
- | primary,
-
- multiplicative = multiplicative:x sc+ ('*' | '/' | '%'):op sc+ unary:y -> [#binary, [#operator, op], x, y]
- | unary,
-
- additive = additive:x sc+ ('+' | '-'):op sc+ multiplicative:y -> [#binary, [#operator, op], x, y]
- | multiplicative,
-
- expression = additive,
-
- nthselector = nthf:x '(' (sc | ('+' | '-'):op -> [#operator, op] | nth)*:y ')' -> [#nthselector, [#ident, x]].concat(y),
-
- blockdecl = sc* (filter | declaration):x decldelim? sc* -> [x]
- | sc* ruleset:x sc* -> [x]
- | sc* decldelim sc* -> []
- | sc+:s0 -> [],
-
- uri = seq('url(') sc* string:x sc* ')' -> CSSParser.concat([#uri], [x])
- | seq('url(') sc* (~')' ~m_w char)*:x sc* ')' -> CSSParser.concat([#uri], [[#raw, x.join('')]]),
-
- pseudoc = ':' (pseudof | ident):x -> [#pseudoc, x],
-
- pseudof = ident:x '(' pseudofBody:y ')' -> [#funktion, x, y],
-
- pseudofBody = (simpleselector)*:x -> [#functionBody].concat(x),
-
- any = braces | string | expression | uri | functionExpression | funktion | ident | variable
-}
Oops, something went wrong.

0 comments on commit 9674958

Please sign in to comment.