You should be able to achieve it with a finite state machine, hand rolled lexer or even a regular expression (rather long regular expression). But I will throw in a quick and easy overkill solution. There is a project called "jison" which is like Bison, but for JavaScript (https://github.com/zaach/jison). It is a parser generator.
Here is a grammar you can use to strip comments everywhere except in strings:
/* description: Scripts comments from JavaScript code. 251
*/
/* lexical grammar */
%lex
%%
\/\* return 'BLOCK_COMMENT_START'
\*\/ return 'BLOCK_COMMENT_END'
\/\/ return 'LINE_COMMENT_START'
\" return 'DOUBLE_QUOTE'
' return 'SINGLE_QUOTE'
\\" return 'ESCAPED_DOUBLE_QUOTE'
\\' return 'ESCAPED_SINGLE_QUOTE'
\\\\ return 'ESCAPED_BACKSLASH'
\n return 'NEW_LINE'
<<EOF>> return 'EOF'
. return 'OTHER'
/lex
%start code
%% /* language grammar */
code
: c EOF
{ typeof console !== 'undefined' ? console.log($1) : print($1);
return $1; }
| c LINE_COMMENT_START c3 EOF
{ typeof console !== 'undefined' ? console.log($1) : print($1);
return $1; }
;
c
: c OTHER {$$ = $1 + $2}
| c BLOCK_COMMENT_START c2 BLOCK_COMMENT_END
| c LINE_COMMENT_START c3 NEW_LINE
| c DOUBLE_QUOTE c4 DOUBLE_QUOTE { $$ = $1 + $2 + $3 + $4 }
| c SINGLE_QUOTE c5 SINGLE_QUOTE { $$ = $1 + $2 + $3 + $4 }
| {$$ = ""}
;
c2
: c2 any_except_block_comment_end
|
;
c3
: c3 any_except_new_line
|
;
c4
: c4 any_except_double_quote { $$ = $1 + $2 }
|
;
c5
: c5 any_except_single_quote { $$ = $1 + $2 }
|
;
any_except_block_comment_end
: BLOCK_COMMENT_START
| LINE_COMMENT_START
| DOUBLE_QUOTE
| SINGLE_QUOTE
| ESCAPED_DOUBLE_QUOTE
| ESCAPED_SINGLE_QUOTE
| ESCAPED_BACKSLASH
| NEW_LINE
| EOF
| OTHER
;
any_except_new_line
: BLOCK_COMMENT_START
| BLOCK_COMMENT_END
| LINE_COMMENT_START
| DOUBLE_QUOTE
| SINGLE_QUOTE
| ESCAPED_DOUBLE_QUOTE
| ESCAPED_SINGLE_QUOTE
| ESCAPED_BACKSLASH
| EOF
| OTHER
;
any_except_double_quote
: BLOCK_COMMENT_START
| BLOCK_COMMENT_END
| LINE_COMMENT_START
| SINGLE_QUOTE
| ESCAPED_DOUBLE_QUOTE
| ESCAPED_SINGLE_QUOTE
| ESCAPED_BACKSLASH
| NEW_LINE
| EOF
| OTHER
;
any_except_single_quote
: BLOCK_COMMENT_START
| BLOCK_COMMENT_END
| LINE_COMMENT_START
| DOUBLE_QUOTE
| ESCAPED_DOUBLE_QUOTE
| ESCAPED_SINGLE_QUOTE
| ESCAPED_BACKSLASH
| NEW_LINE
| EOF
| OTHER
;
Once again. Super overkill, but does the job. It generates an LR parser and since all recursions can be left-recursive, it will use constant stack space. And it will also run in linear time with regards to length of input.
The reason it should be achievable with just a finite state machine or regexp is that all the grammar can be rewritten to be using either just all left or just all right recursion. 268