syntax validator for a less file

1.3k Views Asked by At

I need a validator for a less file. I need to validate a single less file, at only syntax level.

I can't get the validator to follow the dependencies or detect if a mixin is declared or not. That is my real problem.

I have found a lot of less processors which fail because the file has dependencies that i can't provide in this point of the process.

npm package would be perfect.

1

There are 1 best solutions below

3
On BEST ANSWER

Finally, I decided to use antlr4

Steps:

  • install antlr in the computer or add to the deployment process
  • get the grammar for your language (less is already done)
  • get the npm package to process the grammar
  • Use it in your app

The configuration is:

$ cd /usr/local/lib
$ sudo curl -O http://www.antlr.org/download/antlr-4.5-complete.jar
$ export CLASSPATH=".:/usr/local/lib/antlr-4.5-complete.jar:$CLASSPATH"
$ alias antlr4='java -jar /usr/local/lib/antlr-4.5-complete.jar'
$ alias grun='java org.antlr.v4.runtime.misc.TestRig

This info is directly from the web page.

Now you can get the grammar from https://github.com/antlr/grammars-v4

At this point you can generate the javascript version of your grammar

In my case, I created a directory, I downloaded the files and coded all my tests inside:

antlr4 -Dlanguage=JavaScript LessParser.g4
antlr4 -Dlanguage=JavaScript LessLexer.g4

This process generates a javascript file that you will use, but you need the antlr lib for use this files in your node program.

npm link antlr4

Ant now starts to code:

var antlr4 = require('antlr4/index');
var MyGrammarLexer = require('./LessLexer.js');
var MyGrammarParser = require('./LessParser.js');
var input = "html{ .hey(); color: @light-blue; background:#333}";
var chars = new antlr4.InputStream(input);
var lexer = new MyGrammarLexer.LessLexer(chars);
var tokens  = new antlr4.CommonTokenStream(lexer);
var parser = new MyGrammarParser.LessParser(tokens);
parser.buildParseTrees = true;


var ErrorListener = antlr4.error.ErrorListener;
function CustomErrorListener() {
   ErrorListener.call(this);
   return this;
}

CustomErrorListener.prototype = Object.create(ErrorListener.prototype);
CustomErrorListener.prototype.constructor = CustomErrorListener;
CustomErrorListener.prototype.syntaxError = function(recognizer, offendingSymbol, line, column, msg, e) {
    throw ('throw a simple exception');
};

parser.addErrorListener(new CustomErrorListener());

try{
  var tree = parser.stylesheet();
} catch (e){
  console.log('I catch you!!!')
}

The important parts in this code are the function lessLexer, lessParser, and parser.stylesheet(); This are different per grammar. The last one is difficult to know, but it is the point in the grammar that you want to validate. In my case, I get the file LessParser.g4, and you have the different node in the grammar in the definition:

parser grammar LessParser;

options { tokenVocab=LessLexer; }

stylesheet
  : statement*
  ;

statement
  : importDeclaration
  | ruleset
  | variableDeclaration ';'
  | mixinDefinition
  ;

variableName
  : AT variableName
  | AT Identifier
  ;

commandStatement
  : (expression+) mathStatement?
  ;

mathCharacter
  : TIMES | PLUS | DIV | MINUS | PERC
  ;

In this case, you can validate the string like a stylesheet, statement, variableName ...

The last interesting point is the Error Validation, I use it to stop the validation in the first error, my case is very simple, but you can improve this point