[geany/geany] 4dafe0: JavaScript parser: properly parse regular expression literals

Colomban Wendling git-noreply at geany.org
Fri Oct 26 14:59:21 UTC 2012


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Fri, 26 Oct 2012 14:59:21
Commit:      4dafe0d8d30225be4cdecd36f2ee281f3d6326c9
             https://github.com/geany/geany/commit/4dafe0d8d30225be4cdecd36f2ee281f3d6326c9

Log Message:
-----------
JavaScript parser: properly parse regular expression literals

This prevents a regex pattern from fooling the parser if it contains
some recognized constructs, like comment or string literal starts.

Closes #2992393 and #3398636.


Modified Paths:
--------------
    tagmanager/ctags/js.c

Modified: tagmanager/ctags/js.c
54 files changed, 52 insertions(+), 2 deletions(-)
===================================================================
@@ -97,7 +97,8 @@
 	TOKEN_EQUAL_SIGN,
 	TOKEN_FORWARD_SLASH,
 	TOKEN_OPEN_SQUARE,
-	TOKEN_CLOSE_SQUARE
+	TOKEN_CLOSE_SQUARE,
+	TOKEN_REGEXP
 } tokenType;
 
 typedef struct sTokenInfo {
@@ -115,6 +116,8 @@
  *	DATA DEFINITIONS
  */
 
+static tokenType LastTokenType;
+
 static langType Lang_js;
 
 static jmp_buf Exception;
@@ -343,6 +346,32 @@ static void parseString (vString *const string, const int delimiter)
 	vStringTerminate (string);
 }
 
+static void parseRegExp (void)
+{
+	int c;
+	boolean in_range = FALSE;
+
+	do
+	{
+		c = fileGetc ();
+		if (! in_range && c == '/')
+		{
+			do /* skip flags */
+			{
+				c = fileGetc ();
+			} while (isalpha (c));
+			fileUngetc (c);
+			break;
+		}
+		else if (c == '\\')
+			c = fileGetc (); /* skip next character */
+		else if (c == '[')
+			in_range = TRUE;
+		else if (c == ']')
+			in_range = FALSE;
+	} while (c != EOF);
+}
+
 /*	Read a C identifier beginning with "firstChar" and places it into
  *	"name".
  */
@@ -426,8 +455,26 @@ static void readToken (tokenInfo *const token)
 					  if ( (d != '*') &&		/* is this the start of a comment? */
 							  (d != '/') )		/* is a one line comment? */
 					  {
-						  token->type = TOKEN_FORWARD_SLASH;
 						  fileUngetc (d);
+						  switch (LastTokenType)
+						  {
+							  case TOKEN_CHARACTER:
+							  case TOKEN_KEYWORD:
+							  case TOKEN_IDENTIFIER:
+							  case TOKEN_STRING:
+							  case TOKEN_CLOSE_CURLY:
+							  case TOKEN_CLOSE_PAREN:
+							  case TOKEN_CLOSE_SQUARE:
+								  token->type = TOKEN_FORWARD_SLASH;
+								  break;
+
+							  default:
+								  token->type = TOKEN_REGEXP;
+								  parseRegExp ();
+								  token->lineNumber = getSourceLineNumber ();
+								  token->filePosition = getInputFilePosition ();
+								  break;
+						  }
 					  }
 					  else
 					  {
@@ -469,6 +516,8 @@ static void readToken (tokenInfo *const token)
 				  }
 				  break;
 	}
+
+	LastTokenType = token->type;
 }
 
 static void copyToken (tokenInfo *const dest, tokenInfo *const src)
@@ -1626,6 +1675,7 @@ static void findJsTags (void)
 
 	ClassNames = stringListNew ();
 	FunctionNames = stringListNew ();
+	LastTokenType = TOKEN_UNDEFINED;
 
 	exception = (exception_t) (setjmp (Exception));
 	while (exception == ExceptionNone)



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: TBD).


More information about the Commits mailing list