Flex 匹配 JavaScript 注释笔记

这里的 Flex 是指著名此法分析器 lex 的开源版本,而不是指 ActionScript 技术的开源版本,参见 Wikipedia

背景

JavaScript 经常需要压缩,压缩的一个重要环节就是去除注释。不过如果当“/*”和“*/”同时在字符串里;或是“//”在字符串里时,一般的正则表达式难以处理。但是如果事先将字符串过滤掉,就有机会在匹配到所有注释的同时,不错误地匹配到字符串。

比如说以下 JS 示例文件,Flex 在处理正则表达式匹配注释时,恰是这样的。

(function(undefined) {
  'use strict';

  /**
   * a block comment
   */

  // a comment

  "/* Not a comment */";

  '// Not a comment ';

}(undefined));

实现

comments.l

%{
  /**
   * comments.l
   *
   * @author YanWen <i@yanwen.email>
   * @modified 2018-03-29
   * @ref https://blog.ostermiller.org/find-comment
   */

  #include "comments.h"
%}

%option nounput yylineno

%%

(?:/*(?:[^*]|(?:*+[^*/]))**+/)|(?://.*) {
  return COMMENT;
}

('([^'nr]*)')|("([^"nr]*)")   return STRING;

.                                   return NORMAL;

n                                               ;

%%

int yywrap() {
  //  scanning terminates 
  return 1;
}

comments.h

/**
 * comments.h
 *
 * @author YanWen <i@yanwen.email>
 * @modified 2018-03-29
 */

#ifndef _COMMENTS_H
#define _COMMENTS_H

#define COMMENT   1
#define STRING    2
#define NORMAL    3

#endif

comments.c

/**
 * comments.c
 *
 * @author YanWen <i@yanwen.email>
 * @modified 2018-03-29
 */

#include <stdio.h>
#include "comments.h"

extern int yylex();
extern int yylineno;
extern char* yytext;

const char *code_type[] = {
  NULL,
  "comment",
  "string",
  "normal"
};

int main(int argc, char const *argv[]) {
  for (int vtoken, ntoken = yylex(); ntoken; ntoken = yylex()) {
    if (ntoken == NORMAL) continue;
    // Print the parsed result
    printf("line - No.%d, type - %s: n%sn", yylineno,
      code_type[ntoken], yytext);
    puts("------------------------n");
  }

  return 0;
}

效果:

 

参考:

  1. blog.ostermiller.org/find-comment
  2. dinosaur.compilertools.net/flex/manpage.html
  3. Wikipedia – Flex

作者: YanWen

Web 开发者

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

You are commenting using your WordPress.com account. Log Out /  更改 )

Google photo

You are commenting using your Google account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

Connecting to %s