⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jscript.c

📁 ctags的最新版5.7,可以比较5.6版看看,免费下载
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *	 $Id: jscript.c 587 2007-07-16 14:24:10Z dfishburn $ * *	 Copyright (c) 2003, Darren Hiebert * *	 This source code is released for free distribution under the terms of the *	 GNU General Public License. * *	 This module contains functions for generating tags for JavaScript language *	 files. * *	 This is a good reference for different forms of the function statement: *		 http://www.permadi.com/tutorial/jsFunc/ *//* *	 INCLUDE FILES */#include "general.h"	/* must always come first */#include <ctype.h>	/* to define isalpha () */#include <setjmp.h>#ifdef DEBUG#include <stdio.h>#endif#include "debug.h"#include "entry.h"#include "keyword.h"#include "parse.h"#include "read.h"#include "routines.h"#include "vstring.h"/* *	 MACROS */#define isType(token,t)		(boolean) ((token)->type == (t))#define isKeyword(token,k)	(boolean) ((token)->keyword == (k))/* *	 DATA DECLARATIONS */typedef enum eException { ExceptionNone, ExceptionEOF } exception_t;/* * Tracks class and function names already created */static stringList *ClassNames;static stringList *FunctionNames;/*	Used to specify type of keyword.*/typedef enum eKeywordId {	KEYWORD_NONE = -1,	KEYWORD_function,	KEYWORD_capital_function,	KEYWORD_object,	KEYWORD_capital_object,	KEYWORD_prototype,	KEYWORD_var,	KEYWORD_new,	KEYWORD_this,	KEYWORD_for,	KEYWORD_while,	KEYWORD_do,	KEYWORD_if,	KEYWORD_else,	KEYWORD_switch,	KEYWORD_try,	KEYWORD_catch,	KEYWORD_finally} keywordId;/*	Used to determine whether keyword is valid for the token language and *	what its ID is. */typedef struct sKeywordDesc {	const char *name;	keywordId id;} keywordDesc;typedef enum eTokenType {	TOKEN_UNDEFINED,	TOKEN_CHARACTER,	TOKEN_CLOSE_PAREN,	TOKEN_SEMICOLON,	TOKEN_COLON,	TOKEN_COMMA,	TOKEN_KEYWORD,	TOKEN_OPEN_PAREN,	TOKEN_OPERATOR,	TOKEN_IDENTIFIER,	TOKEN_STRING,	TOKEN_PERIOD,	TOKEN_OPEN_CURLY,	TOKEN_CLOSE_CURLY,	TOKEN_EQUAL_SIGN,	TOKEN_FORWARD_SLASH,	TOKEN_OPEN_SQUARE,	TOKEN_CLOSE_SQUARE} tokenType;typedef struct sTokenInfo {	tokenType		type;	keywordId		keyword;	vString *		string;	vString *		scope;	unsigned long 	lineNumber;	fpos_t 			filePosition;	int				nestLevel;	boolean			ignoreTag;} tokenInfo;/* *	DATA DEFINITIONS */static langType Lang_js;static jmp_buf Exception;typedef enum {	JSTAG_FUNCTION,	JSTAG_CLASS,	JSTAG_METHOD,	JSTAG_VARIABLE,	JSTAG_COUNT} jsKind;static kindOption JsKinds [] = {	{ TRUE,  'f', "function",	  "functions"			   },	{ TRUE,  'c', "class",		  "classes"			   },	{ TRUE,  'm', "method",		  "methods"			   },	{ TRUE,  'v', "variable",	  "global variables"	   }};static const keywordDesc JsKeywordTable [] = {	/* keyword		keyword ID */	{ "function",	KEYWORD_function			},	{ "Function",	KEYWORD_capital_function	},	{ "object",		KEYWORD_object				},	{ "Object",		KEYWORD_capital_object		},	{ "prototype",	KEYWORD_prototype			},	{ "var",		KEYWORD_var					},	{ "new",		KEYWORD_new					},	{ "this",		KEYWORD_this				},	{ "for",		KEYWORD_for					},	{ "while",		KEYWORD_while				},	{ "do",			KEYWORD_do					},	{ "if",			KEYWORD_if					},	{ "else",		KEYWORD_else				},	{ "switch",		KEYWORD_switch				},	{ "try",		KEYWORD_try					},	{ "catch",		KEYWORD_catch				},	{ "finally",	KEYWORD_finally				}};/* *	 FUNCTION DEFINITIONS *//* Recursive functions */static void parseFunction (tokenInfo *const token);static boolean parseBlock (tokenInfo *const token, tokenInfo *const parent);static boolean parseLine (tokenInfo *const token, boolean is_inside_class);static boolean isIdentChar1 (const int c){	/*	 * Other databases are less restrictive on the first character of	 * an identifier.	 * isIdentChar1 is used to identify the first character of an 	 * identifier, so we are removing some restrictions.	 */	return (boolean)		(isalpha (c) || c == '@' || c == '_' );}static boolean isIdentChar (const int c){	return (boolean)		(isalpha (c) || isdigit (c) || c == '$' || 		 c == '@' || c == '_' || c == '#');}static void buildJsKeywordHash (void){	const size_t count = sizeof (JsKeywordTable) /		sizeof (JsKeywordTable [0]);	size_t i;	for (i = 0	;  i < count  ;  ++i)	{		const keywordDesc* const p = &JsKeywordTable [i];		addKeyword (p->name, Lang_js, (int) p->id);	}}static tokenInfo *newToken (void){	tokenInfo *const token = xMalloc (1, tokenInfo);	token->type			= TOKEN_UNDEFINED;	token->keyword		= KEYWORD_NONE;	token->string		= vStringNew ();	token->scope		= vStringNew ();	token->nestLevel	= 0;	token->ignoreTag	= FALSE;	return token;}static void deleteToken (tokenInfo *const token){	vStringDelete (token->string);	vStringDelete (token->scope);	eFree (token);}/* *	 Tag generation functions */static void makeConstTag (tokenInfo *const token, const jsKind kind){	if (JsKinds [kind].enabled && ! token->ignoreTag )	{		const char *const name = vStringValue (token->string);		tagEntryInfo e;		initTagEntry (&e, name);		e.lineNumber   = token->lineNumber;		e.filePosition = token->filePosition;		e.kindName	   = JsKinds [kind].name;		e.kind		   = JsKinds [kind].letter;		makeTagEntry (&e);	}}static void makeJsTag (tokenInfo *const token, const jsKind kind){	vString *	fulltag;	if (JsKinds [kind].enabled && ! token->ignoreTag )	{		/*		 * If a scope has been added to the token, change the token		 * string to include the scope when making the tag.		 */		if ( vStringLength(token->scope) > 0 )		{			fulltag = vStringNew ();			vStringCopy(fulltag, token->scope);			vStringCatS (fulltag, ".");			vStringCatS (fulltag, vStringValue(token->string));			vStringTerminate(fulltag);			vStringCopy(token->string, fulltag);			vStringDelete (fulltag);		}		makeConstTag (token, kind);	}}static void makeClassTag (tokenInfo *const token){ 	if ( ! token->ignoreTag )	{		if ( ! stringListHas(ClassNames, vStringValue (token->string)) )		{			stringListAdd (ClassNames, vStringNewCopy (token->string));			makeJsTag (token, JSTAG_CLASS);		}	}}static void makeFunctionTag (tokenInfo *const token){ 	if ( ! token->ignoreTag )	{		if ( ! stringListHas(FunctionNames, vStringValue (token->string)) )		{			stringListAdd (FunctionNames, vStringNewCopy (token->string));			makeJsTag (token, JSTAG_FUNCTION);		}	}}/* *	 Parsing functions */static int skipToCharacter (const int c){	int d;	do	{		d = fileGetc ();	} while (d != EOF  &&  d != c);	return d;}static void parseString (vString *const string, const int delimiter){	boolean end = FALSE;	int c;	while (! end)	{		c = fileGetc ();		if (c == EOF)			end = TRUE;		else if (c == delimiter)			end = TRUE;		else			vStringPut (string, c);	}	vStringTerminate (string);}/*	Read a C identifier beginning with "firstChar" and places it into *	"name". */static void parseIdentifier (vString *const string, const int firstChar){	int c = firstChar;	Assert (isIdentChar1 (c));	do	{		vStringPut (string, c);		c = fileGetc ();	} while (isIdentChar (c));	vStringTerminate (string);	if (!isspace (c))		fileUngetc (c);		/* unget non-identifier character */}static keywordId analyzeToken (vString *const name){	vString *keyword = vStringNew ();	keywordId result;	vStringCopyToLower (keyword, name);	result = (keywordId) lookupKeyword (vStringValue (keyword), Lang_js);	vStringDelete (keyword);	return result;}static void readToken (tokenInfo *const token){	int c;	token->type			= TOKEN_UNDEFINED;	token->keyword		= KEYWORD_NONE;	vStringClear (token->string);getNextChar:	do	{		c = fileGetc ();		/* 		 * Added " to the list of ignores, not sure what this 		 * might break but it gets by this issue:		 *	  create table "t1" (...)		 */	}	while (c == '\t'  ||  c == ' ' ||  c == '\n');	switch (c)	{		case EOF: longjmp (Exception, (int)ExceptionEOF);	break;		case '(': token->type = TOKEN_OPEN_PAREN;			break;		case ')': token->type = TOKEN_CLOSE_PAREN;			break;		case ';': token->type = TOKEN_SEMICOLON;			break;		case ',': token->type = TOKEN_COMMA;				break;		case '.': token->type = TOKEN_PERIOD;				break;		case ':': token->type = TOKEN_COLON;				break;		case '{': token->type = TOKEN_OPEN_CURLY;			break;		case '}': token->type = TOKEN_CLOSE_CURLY;			break;		case '=': token->type = TOKEN_EQUAL_SIGN;			break;		case '[': token->type = TOKEN_OPEN_SQUARE;			break;		case ']': token->type = TOKEN_CLOSE_SQUARE;			break;		case '\'':		case '"':				  token->type = TOKEN_STRING;				  parseString (token->string, c);				  token->lineNumber = getSourceLineNumber ();				  token->filePosition = getInputFilePosition ();				  break;		case '/':				  {					  int d = fileGetc ();					  if ( (d != '*') &&		/* is this the start of a comment? */							  (d != '/') )		/* is a one line comment? */					  {						  token->type = TOKEN_FORWARD_SLASH;						  fileUngetc (d);					  }					  else					  {						  if (d == '*')						  {							  do							  {								  skipToCharacter ('*');								  c = fileGetc ();								  if (c == '/')									  break;								  else									  fileUngetc (c);							  } while (c != EOF && c != '\0');							  goto getNextChar;						  }						  else if (d == '/')	/* is this the start of a comment?  */						  {							  skipToCharacter ('\n');							  goto getNextChar;						  }					  }					  break;				  }		default:				  if (! isIdentChar1 (c))					  token->type = TOKEN_UNDEFINED;				  else				  {					  parseIdentifier (token->string, c);					  token->lineNumber = getSourceLineNumber ();					  token->filePosition = getInputFilePosition ();					  token->keyword = analyzeToken (token->string);					  if (isKeyword (token, KEYWORD_NONE))						  token->type = TOKEN_IDENTIFIER;					  else						  token->type = TOKEN_KEYWORD;				  }				  break;	}}static void copyToken (tokenInfo *const dest, tokenInfo *const src){	dest->nestLevel = src->nestLevel;	dest->lineNumber = src->lineNumber;	dest->filePosition = src->filePosition;	dest->type = src->type;	dest->keyword = src->keyword;	vStringCopy(dest->string, src->string);	vStringCopy(dest->scope, src->scope);}/* *	 Token parsing functions */static void skipArgumentList (tokenInfo *const token){	int nest_level = 0;	/*	 * Other databases can have arguments with fully declared	 * datatypes:	 *	 (	name varchar(30), text binary(10)  )	 * So we must check for nested open and closing parantheses	 */	if (isType (token, TOKEN_OPEN_PAREN))	/* arguments? */	{		nest_level++;		while (! (isType (token, TOKEN_CLOSE_PAREN) && (nest_level == 0)))		{			readToken (token);			if (isType (token, TOKEN_OPEN_PAREN))			{				nest_level++;			}			if (isType (token, TOKEN_CLOSE_PAREN))			{				if (nest_level > 0)				{					nest_level--;				}			}		} 		readToken (token);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -