Exemple #1
0
static int get_next_char()
{
    int c, nxt;
    c = fileGetc();
    if (c == EOF)
	return c;
    nxt = fileGetc();
    if (nxt == EOF)
	return c;
    fileUngetc(nxt);
    
    if (c == '-' && nxt == '-') {
	skip_rest_of_line();
	return get_next_char();
    }
    if (c == '{' && nxt == '-') {
	int last = '\0';
	do {
	    last = c;
	    c = get_next_char();
	} while (! (c == EOF || (last == '-' && c == '}')));
	return get_next_char();
    }
    return c;
}
Exemple #2
0
static vString *parseNumeric (int c)
{
    static vString *string = NULL;

    if (string == NULL)
        string = vStringNew ();
    vStringCopy (string, parseInteger (c));

    c = fileGetc ();
    if (c == '.')
    {
        vStringPut (string, c);
        vStringCat (string, parseInteger ('\0'));
        c = fileGetc ();
    }
    if (tolower (c) == 'e')
    {
        vStringPut (string, c);
        vStringCat (string, parseInteger ('\0'));
    }
    else if (!isspace (c))
        fileUngetc (c);

    vStringTerminate (string);

    return string;
}
Exemple #3
0
static int vGetc (void)
{
    int c;
    if (Ungetc == '\0')
	c = fileGetc ();
    else
    {
		c = Ungetc;
		Ungetc = '\0';
    }
    if (c == '-')
    {
		int c2 = fileGetc ();
		if (c2 == EOF)
			longjmp (Exception, (int) ExceptionEOF);
		else if (c2 == '-')   /* strip comment until end-of-line */
		{
			do
			c = fileGetc ();
			while (c != '\n'  &&  c != EOF);
		}
		else
			Ungetc = c2;
	}
    if (c == EOF)
		longjmp (Exception, (int) ExceptionEOF);
	return c;
}
Exemple #4
0
/*  If a numeric is passed in 'c', this is used as the first digit of the
 *  numeric being parsed.
 */
static vString *parseInteger (int c)
{
    static vString *string = NULL;

    if (string == NULL)
        string = vStringNew ();
    vStringClear (string);

    if (c == '\0')
        c = fileGetc ();
    if (c == '-')
    {
        vStringPut (string, c);
        c = fileGetc ();
    }
    else if (! isdigit (c))
        c = fileGetc ();
    while (c != EOF  &&  (isdigit (c)  ||  c == '_'))
    {
        vStringPut (string, c);
        c = fileGetc ();
    }
    vStringTerminate (string);
    fileUngetc (c);

    return string;
}
Exemple #5
0
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);
}
Exemple #6
0
static int nextChar (void)
{
	int c = fileGetc ();
	if (c == '\\')
	{
		c = fileGetc ();
		if (c == '\n')
			c = nextChar ();
	}
	return c;
}
Exemple #7
0
static int parseEscapedCharacter (void)
{
	int d = '\0';
	int c = fileGetc ();

	switch (c)
	{
		case 'A':  d = '@';   break;
		case 'B':  d = '\b';  break;
		case 'C':  d = '^';   break;
		case 'D':  d = '$';   break;
		case 'F':  d = '\f';  break;
		case 'H':  d = '\\';  break;
		case 'L':  d = '~';   break;
		case 'N':  d = '\n';  break;
#ifdef QDOS
		case 'Q':  d = 0x9F;  break;
#else
		case 'Q':  d = '`';   break;
#endif
		case 'R':  d = '\r';  break;
		case 'S':  d = '#';   break;
		case 'T':  d = '\t';  break;
		case 'U':  d = '\0';  break;
		case 'V':  d = '|';   break;
		case '%':  d = '%';   break;
		case '\'': d = '\'';  break;
		case '"':  d = '"';   break;
		case '(':  d = '[';   break;
		case ')':  d = ']';   break;
		case '<':  d = '{';   break;
		case '>':  d = '}';   break;

		case '\n': skipToCharacter ('%'); break;

		case '/':
		{
			vString *string = parseInteger ('\0');
			const char *value = vStringValue (string);
			const unsigned long ascii = atol (value);
			vStringDelete (string);

			c = fileGetc ();
			if (c == '/'  &&  ascii < 256)
				d = ascii;
			break;
		}

		default: break;
	}
	return d;
}
Exemple #8
0
static int parseCharacter (void)
{
    int c = fileGetc ();
    int result = c;

    if (c == '%')
        result = parseEscapedCharacter ();

    c = fileGetc ();
    if (c != '\'')
        skipToCharacter ('\n');

    return result;
}
Exemple #9
0
static void skip_rest_of_line()
{
    int c;
    do {
	c = fileGetc();
    } while (c != EOF && c != '\n');
}
Exemple #10
0
static int skipToCharacter (const int c)
{
	int d;
	do
	{
		d = fileGetc ();
	} while (d != EOF  &&  d != c);
	return d;
}
Exemple #11
0
static int get_token(char *token, int n)
{
    int c = fileGetc();
    int i = n;
    while (c != EOF && isident(c) && i < 1000) {
	token[i] = c;
	i++;
	c = fileGetc();
    }
    if (c == EOF)
	return 0;
    if (i != n) {
	token[i] = '\0';
	fileUngetc(c);
	return 1;
    } else {
	return 0;
    }
}
Exemple #12
0
static void parseTemplateString (vString *const string)
{
	int c;
	do
	{
		c = fileGetc ();
		if (c == '`')
			break;
		vStringPut (string, c);
		if (c == '\\')
		{
			c = fileGetc();
			vStringPut(string, c);
		}
		else if (c == '$')
		{
			c = fileGetc ();
			if (c != '{')
				fileUngetc (c);
			else
			{
				int depth = 1;
				/* we need to use the real token machinery to handle strings,
				 * comments, regexes and whatnot */
				tokenInfo *token = newToken ();
				LastTokenType = TOKEN_UNDEFINED;
				vStringPut(string, c);
				do
				{
					readTokenFull (token, FALSE, string);
					if (isType (token, TOKEN_OPEN_CURLY))
						depth++;
					else if (isType (token, TOKEN_CLOSE_CURLY))
						depth--;
				}
				while (! isType (token, TOKEN_EOF) && depth > 0);
				deleteToken (token);
			}
		}
	}
	while (c != EOF);
	vStringTerminate (string);
}
Exemple #13
0
static int vGetc (void)
{
	int c;
	if (Ungetc == '\0')
		c = fileGetc ();
	else
	{
		c = Ungetc;
		Ungetc = '\0';
	}
	if (c == '/')
	{
		int c2 = fileGetc ();
		if (c2 == EOF)
			longjmp (Exception, (int) ExceptionEOF);
		else if (c2 == '/')  /* strip comment until end-of-line */
		{
			do
				c = fileGetc ();
			while (c != '\n'  &&  c != EOF);
		}
		else if (c2 == '*')  /* strip block comment */
		{
			c = skipOverCComment();
		}
		else
		{
			fileUngetc (c2);
		}
	}
	else if (c == '"')  /* strip string contents */
	{
		int c2;
		do
			c2 = fileGetc ();
		while (c2 != '"'  &&  c2 != EOF);
		c = '@';
	}
	if (c == EOF)
		longjmp (Exception, (int) ExceptionEOF);
	return c;
}
Exemple #14
0
static void parseString (vString * const string, const int delimiter)
{
	boolean end = FALSE;
	while (!end)
	{
		int c = fileGetc ();
		if (c == EOF)
			end = TRUE;
		else if (c == '\\')
		{
			c = fileGetc ();	/* This maybe a ' or ". */
			vStringPut (string, c);
		}
		else if (c == delimiter)
			end = TRUE;
		else
			vStringPut (string, c);
	}
	vStringTerminate (string);
}
Exemple #15
0
static void parseIdentifier (vString *const string, const int firstChar)
{
	int c = firstChar;
	do
	{
		vStringPut (string, c);
		c = fileGetc ();
	} while (isIdentChar (c));
	vStringTerminate (string);
	fileUngetc (c);		/* always unget, LF might add a semicolon */
}
Exemple #16
0
static void parseSelector (vString *const string, const int firstChar)
{
	int c = firstChar;
	do
	{
		vStringPut (string, (char) c);
		c = fileGetc ();
	} while (isSelectorChar (c));
	fileUngetc (c);
	vStringTerminate (string);
}
Exemple #17
0
static int get_line(char *buf)
{
    int i = 0;
    int c;
    do {
        c = fileGetc();
	buf[i++] = c;
    } while (c != EOF && c != '\n' && i < 1000);
    buf[i] = '\0';
    return i;
}
Exemple #18
0
static void parseString (vString *const string, const int delimiter)
{
	boolean end = FALSE;
	while (! end)
	{
		int c = fileGetc ();
		if (c == EOF)
			end = TRUE;
		else if (c == '\\')
		{
			/* Eat the escape sequence (\", \', etc).  We properly handle
			 * <LineContinuation> by eating a whole \<CR><LF> not to see <LF>
			 * as an unescaped character, which is invalid and handled below.
			 * Also, handle the fact that <LineContinuation> produces an empty
			 * sequence.
			 * See ECMA-262 7.8.4 */
			c = fileGetc();
			if (c != '\r' && c != '\n')
				vStringPut(string, c);
			else if (c == '\r')
			{
				c = fileGetc();
				if (c != '\n')
					fileUngetc (c);
			}
		}
		else if (c == delimiter)
			end = TRUE;
		else if (c == '\r' || c == '\n')
		{
			/* those are invalid when not escaped */
			end = TRUE;
			/* we don't want to eat the newline itself to let the automatic
			 * semicolon insertion code kick in */
			fileUngetc (c);
		}
		else
			vStringPut (string, c);
	}
	vStringTerminate (string);
}
Exemple #19
0
/*	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 (isIdentChar (c));
	do
	{
		vStringPut (string, c);
		c = fileGetc ();
	} while (isIdentChar (c));
	vStringTerminate (string);
	fileUngetc (c);		/* unget non-identifier character */
}
Exemple #20
0
static void parseString (vString *const string, const int delimiter)
{
	boolean end = FALSE;
	while (!end)
	{
		int c = fileGetc ();
		if (c == EOF)
			end = TRUE;
		else if (c == '\\' && delimiter != '`')
		{
			c = fileGetc ();
			if (c != '\'' && c != '\"')
				vStringPut (string, '\\');
			vStringPut (string, c);
		}
		else if (c == delimiter)
			end = TRUE;
		else
			vStringPut (string, c);
	}
	vStringTerminate (string);
}
Exemple #21
0
static void parseFreeOperator (vString *const string, const int firstChar)
{
    int c = firstChar;

    do
    {
        vStringPut (string, c);
        c = fileGetc ();
    } while (c > ' ');

    vStringTerminate (string);
    if (!isspace (c))
        fileUngetc (c);  /* unget non-identifier character */
}
Exemple #22
0
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);
}
Exemple #23
0
static int vGetc (void)
{
    int c;
    if (Ungetc == '\0')
	c = fileGetc ();
    else
    {
	c = Ungetc;
	Ungetc = '\0';
    }
    if (c == '/')
    {
	int c2 = fileGetc ();
	if (c2 == EOF)
	    longjmp (Exception, (int) ExceptionEOF);
	else if (c2 == '/')   /* strip comment until end-of-line */
	{
	    do
		c = fileGetc ();
	    while (c != '\n'  &&  c != EOF);
	}
	else if (c2 == '*')    /* strip block comment */
	{
	    do
	    {
		do
		    c = fileGetc ();
		while (c != '*'  &&  c != EOF);
		if (c != EOF)
		    c = fileGetc ();
	    } while (c != '/'  &&  c != EOF);
	    if (c != EOF)
		c = ' ';      /* comment equivalent to white space */
	}
	else
	    Ungetc = c2;
    }
    else if (c == '"')        /* strip string contents */
    {
	int c2;
	do
	    c2 = fileGetc ();
	while (c2 != '"'  &&  c2 != EOF);
	c = '@';
    }
    if (c == EOF)
	longjmp (Exception, (int) ExceptionEOF);
    return c;
}
Exemple #24
0
static int inside_datatype(vString *name)
{
    enum Find_State st = Find_Eq;
    int c;
    char token[1001];

    while (1) {
	if (st == Find_Eq)
	{
	    do {
		c = get_next_char();
		if (c == '\n') {
		    c = get_next_char();
		    if (! (c == ' ' || c == '\t')) {
			return c;
		    }
		}
	    } while (c != '=');
	    st = Find_Constr;
	}
	else if (st == Find_Constr)
	{
	    do {
		c = get_next_char();
	    } while (isspace(c));
	    if (!isupper(c)) {
		    skip_rest_of_line();
		    return '\n';
	    }
	    token[0] = c;
	    if (!get_token(token, 1))
		return '\n';
	    add_tag(token, K_CONSTRUCTOR, name);
	    st = Find_Extr;
	}
	else if (st == Find_Extr)
	{
	    c = get_next_char();
    	    if (c == '{')
		st = Get_Extr;
	    else if (c == '|')
		st = Find_Constr;
	    else if (c == '\n') {
		    c = get_next_char();
		    if (! (c == ' ' || c == '\t')) {
			return c;
		    }
	    }
	    else if (!isspace(c))
		st = Find_Bar;
	}
	else if (st == Get_Extr)
	{
	    do {
		c = fileGetc();
	    } while (isspace(c));
	    if (c == EOF)
		return c;
	    token[0] = c;
	    get_token(token, 1);
	    add_tag(token, K_FUNCTION, name);
	    do {
		c = get_next_char();
		if (c == '}') {
		    st = Find_Bar;
		    break;
		}
	    } while (c != ',');
	}
	else if (st == Find_Bar)
	{
	    do {
		c = get_next_char();
		if (c == '\n') {
		    c = get_next_char();
		    if (! (c == ' ' || c == '\t')) {
			return c;
		    }
		}
	    } while (c != EOF && c != '|');
	    st = Find_Constr;
	}
    }
    return '\n';
}
Exemple #25
0
static void readToken (tokenInfo *const token)
{
	int c;

	token->type			= TOKEN_UNDEFINED;
	token->keyword		= KEYWORD_NONE;
	vStringClear (token->string);

getNextChar:
	do
	{
		c = fileGetc ();
	}
	while (c == '\t'  ||  c == ' ' ||  c == '\n');

	token->lineNumber   = getSourceLineNumber ();
	token->filePosition = getInputFilePosition ();

	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 '\\':
				  c = fileGetc ();
				  if (c != '\\'  && c != '"'  &&  !isspace (c))
					  fileUngetc (c);
				  token->type = TOKEN_CHARACTER;
				  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? */
					  {
						  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
					  {
						  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 (! isIdentChar (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;
	}

	LastTokenType = token->type;
}
Exemple #26
0
static void readTokenFull (tokenInfo *const token, boolean include_newlines, vString *const repr)
{
	int c;
	int i;

	token->type			= TOKEN_UNDEFINED;
	token->keyword		= KEYWORD_NONE;
	vStringClear (token->string);

getNextChar:
	i = 0;
	do
	{
		c = fileGetc ();
		i++;
	}
	while (c == '\t'  ||  c == ' ' ||
		   ((c == '\r' || c == '\n') && ! include_newlines));

	token->lineNumber   = getSourceLineNumber ();
	token->filePosition = getInputFilePosition ();

	if (repr)
	{
		if (i > 1)
			vStringPut (repr, ' ');
		vStringPut (repr, c);
	}

	switch (c)
	{
		case EOF: token->type = TOKEN_EOF;					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 '-':
			{
				int d = fileGetc ();
				if (d == c) /* ++ or -- */
					token->type = TOKEN_POSTFIX_OPERATOR;
				else
				{
					fileUngetc (d);
					token->type = TOKEN_BINARY_OPERATOR;
				}
				break;
			}

		case '*':
		case '%':
		case '?':
		case '>':
		case '<':
		case '^':
		case '|':
		case '&':
			token->type = TOKEN_BINARY_OPERATOR;
			break;

		case '\r':
		case '\n':
			/* This isn't strictly correct per the standard, but following the
			 * real rules means understanding all statements, and that's not
			 * what the parser currently does.  What we do here is a guess, by
			 * avoiding inserting semicolons that would make the statement on
			 * the left invalid.  Hopefully this should not have false negatives
			 * (e.g. should not miss insertion of a semicolon) but might have
			 * false positives (e.g. it will wrongfully emit a semicolon for the
			 * newline in "foo\n+bar").
			 * This should however be mostly harmless as we only deal with
			 * newlines in specific situations where we know a false positive
			 * wouldn't hurt too bad. */
			switch (LastTokenType)
			{
				/* these cannot be the end of a statement, so hold the newline */
				case TOKEN_EQUAL_SIGN:
				case TOKEN_COLON:
				case TOKEN_PERIOD:
				case TOKEN_FORWARD_SLASH:
				case TOKEN_BINARY_OPERATOR:
				/* and these already end one, no need to duplicate it */
				case TOKEN_SEMICOLON:
				case TOKEN_COMMA:
				case TOKEN_CLOSE_CURLY:
				case TOKEN_OPEN_CURLY:
					include_newlines = FALSE; /* no need to recheck */
					goto getNextChar;
					break;
				default:
					token->type = TOKEN_SEMICOLON;
			}
			break;

		case '\'':
		case '"':
				  token->type = TOKEN_STRING;
				  parseString (token->string, c);
				  token->lineNumber = getSourceLineNumber ();
				  token->filePosition = getInputFilePosition ();
				  if (repr)
				  {
					  vStringCat (repr, token->string);
					  vStringPut (repr, c);
				  }
				  break;

		case '\\':
				  c = fileGetc ();
				  if (c != '\\'  && c != '"'  &&  !isspace (c))
					  fileUngetc (c);
				  token->type = TOKEN_CHARACTER;
				  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? */
					  {
						  fileUngetc (d);
						  switch (LastTokenType)
						  {
							  case TOKEN_CHARACTER:
							  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
					  {
						  if (repr) /* remove the / we added */
							  repr->buffer[--repr->length] = 0;
						  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');
							  /* if we care about newlines, put it back so it is seen */
							  if (include_newlines)
								  fileUngetc ('\n');
							  goto getNextChar;
						  }
					  }
					  break;
				  }

		case '#':
				  /* skip shebang in case of e.g. Node.js scripts */
				  if (token->lineNumber > 1)
					  token->type = TOKEN_UNDEFINED;
				  else if ((c = fileGetc ()) != '!')
				  {
					  fileUngetc (c);
					  token->type = TOKEN_UNDEFINED;
				  }
				  else
				  {
					  skipToCharacter ('\n');
					  goto getNextChar;
				  }
				  break;

		default:
				  if (! isIdentChar (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;
					  if (repr && vStringLength (token->string) > 1)
						  vStringCatS (repr, vStringValue (token->string) + 1);
				  }
				  break;
	}

	LastTokenType = token->type;
}
Exemple #27
0
/* Reads a character from the file */
static void advanceChar (lexerState *lexer)
{
	lexer->cur_c = lexer->next_c;
	lexer->next_c = fileGetc();
}
Exemple #28
0
static void findBetaTags (void)
{
	vString *line = vStringNew ();
	boolean incomment = FALSE;
	boolean inquote = FALSE;
	boolean dovirtuals = BetaKinds [K_VIRTUAL].enabled;
	boolean dopatterns = BetaKinds [K_PATTERN].enabled;

	do
	{
		boolean foundfragmenthere = FALSE;
		/* find fragment definition (line that starts and ends with --) */
		int last;
		int first;
		int c;

		vStringClear (line);

		while ((c = fileGetc ()) != EOF && c != '\n' && c != '\r')
			vStringPut (line, c);

		vStringTerminate (line);

		last = vStringLength (line) - 1;
		first = 0;
		/* skip white space at start and end of line */
		while (last && isspace ((int) vStringChar (line, last))) last--;
		while (first < last && isspace ((int) vStringChar (line, first))) first++;
		/* if line still has a reasonable length and ... */
		if (last - first > 4 &&
			(vStringChar (line, first)     == '-' && 
			 vStringChar (line, first + 1) == '-' && 
			 vStringChar (line, last)      == '-' && 
			 vStringChar (line, last - 1)  == '-'))
		{
			if (!incomment && !inquote)
			{
				foundfragmenthere = TRUE;
				/* skip past -- and whitespace.  Also skip back past 'dopart'
				   or 'attributes' to the :.  We have to do this because there
				   is no sensible way to include whitespace in a ctags token
				   so the conventional space after the ':' would mess us up */
				last -= 2;
				first += 2;
				while (last && vStringChar (line, last) != ':') last--;
				while (last && (isspace ((int) vStringChar (line, last-1)))) last--;
				while (first < last &&
					   (isspace ((int) vStringChar (line, first)) ||
						vStringChar (line, first) == '-'))
					first++;
				/* If there's anything left it is a fragment title */
				if (first < last - 1)
				{
					vStringChar (line, last) = 0;
					if (strcasecmp ("LIB", vStringValue (line) + first) &&
						strcasecmp ("PROGRAM", vStringValue (line) + first))
					{
						makeBetaTag (vStringValue (line) + first, K_FRAGMENT);
					}
				}
			}
		} else {
			int pos = 0;
			int len = vStringLength (line);
			if (inquote) goto stringtext;
			if (incomment) goto commenttext;
		programtext:
			for ( ; pos < len; pos++)
			{
				if (vStringChar (line, pos) == '\'')
				{
					pos++;
					inquote = TRUE;
					goto stringtext;
				}
				if (vStringChar (line, pos) == '{')
				{
					pos++;
					incomment = TRUE;
					goto commenttext;
				}
				if (vStringChar (line, pos) == '(' && pos < len - 1 &&
					vStringChar (line, pos+1) == '*')
				{
					pos +=2;
					incomment = TRUE;
					goto commenttext;
				}
				/*
				 * SLOT definition looks like this: 
				 * <<SLOT nameofslot: dopart>> 
				 * or
				 * <<SLOT nameofslot: descriptor>> 
				 */
				if (!foundfragmenthere &&
					vStringChar (line, pos) == '<' &&
					pos+1 < len &&
					vStringChar (line, pos+1) == '<' &&
					strstr (vStringValue (line) + pos, ">>"))
				{
					/* Found slot name, get start and end */
					int eoname;
					char c2;
					pos += 2; /* skip past << */
					/* skip past space before SLOT */
					while (pos < len && isspace ((int) vStringChar (line, pos)))
						pos++;
					/* skip past SLOT */
					if (pos+4 <= len &&
						!strncasecmp (vStringValue(line) + pos, "SLOT", (size_t)4))
						pos += 4;
					/* skip past space after SLOT */
					while (pos < len && isspace ((int) vStringChar (line, pos)))
						pos++;
					eoname = pos;
					/* skip to end of name */
					while (eoname < len &&
							(c2 = vStringChar (line, eoname)) != '>' &&
							c2 != ':' &&
							!isspace ((int) c2))
						eoname++;
					if (eoname < len)
					{
						vStringChar (line, eoname) = 0;
						if (strcasecmp ("LIB", vStringValue (line) + pos) &&
							strcasecmp ("PROGRAM", vStringValue (line) + pos) &&
							strcasecmp ("SLOT", vStringValue (line) + pos))
						{
							makeBetaTag (vStringValue (line) + pos, K_SLOT);
						}
					}
					if (eoname+1 < len) {
						pos = eoname + 1;
					} else {
						pos = len;
						continue;
					}
				}
				/* Only patterns that are virtual, extensions of virtuals or
				 * final bindings are normally included so as not to overload
	             * totally.
				 * That means one of the forms name:: name:< or name::<
				 */
				if (!foundfragmenthere &&
					vStringChar (line, pos) == ':' &&
	                (dopatterns ||
					 (dovirtuals &&
					  (vStringChar (line, pos+1) == ':' ||
					   vStringChar (line, pos+1) == '<')
					 )
					)
	               )
				{
					/* Found pattern name, get start and end */
					int eoname = pos;
					int soname;
					while (eoname && isspace ((int) vStringChar (line, eoname-1)))
						eoname--;
				foundanothername:
					/* terminate right after name */
					vStringChar (line, eoname) = 0;
					soname = eoname;
					while (soname &&
						isbident (vStringChar (line, soname-1)))
					{
						soname--;
					}
					if (soname != eoname)
					{
						makeBetaTag (vStringValue (line) + soname, K_PATTERN);
						/* scan back past white space */
						while (soname &&
								isspace ((int) vStringChar (line, soname-1)))
							soname--;
						if (soname && vStringChar (line, soname-1) == ',')
						{
							/* we found a new pattern name before comma */
							eoname = soname;
							goto foundanothername;
						}
					}
				}
			}
			goto endofline;
		commenttext:
			for ( ; pos < len; pos++)
			{
				if (vStringChar (line, pos) == '*' && pos < len - 1 &&
					vStringChar (line, pos+1) == ')')
				{
					pos += 2;
					incomment = FALSE;
					goto programtext;
				}
				if (vStringChar (line, pos) == '}')
				{
					pos++;
					incomment = FALSE;
					goto programtext;
				}
			}
			goto endofline;
		stringtext:
			for ( ; pos < len; pos++)
			{
				if (vStringChar (line, pos) == '\\')
				{
					if (pos < len - 1) pos++;
				}
				else if (vStringChar (line, pos) == '\'')
				{
					pos++;
					/* support obsolete '' syntax */
					if (pos < len && vStringChar (line, pos) == '\'')
					{
						continue;
					}
					inquote = FALSE;
					goto programtext;
				}
			}
		}
		endofline:
		inquote = FALSE;  /* This shouldn't really make a difference */
	} while (!feof (File.fp));
}
Exemple #29
0
static void readToken (tokenInfo * const token)
{
	int c;

	token->type = TOKEN_NONE;
	token->keyword = KEYWORD_NONE;
	vStringClear (token->string);

  getNextChar:
	do
	{
		c = fileGetc ();
		token->lineNumber = getSourceLineNumber ();
		token->filePosition = getInputFilePosition ();
	}
	while (c == '\t' || c == ' ' || c == '\n');

	switch (c)
	{
	case EOF:
		token->type = TOKEN_EOF;
		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_PERIOD;
		break;
	case ',':
		token->type = TOKEN_COMMA;
		break;
	case '\'':	/* only single char are inside simple quotes */
		break;	/* or it is for attributes so we don't care */
	case '"':
		token->type = TOKEN_STRING;
		parseString (token->string, c);
		token->lineNumber = getSourceLineNumber ();
		token->filePosition = getInputFilePosition ();
		break;
	case '-':
		c = fileGetc ();
		if (c == '-')	/* start of a comment */
		{
			fileSkipToCharacter ('\n');
			goto getNextChar;
		}
		else
		{
			if (!isspace (c))
				fileUngetc (c);
			token->type = TOKEN_OPERATOR;
		}
		break;
	default:
		if (!isIdentChar1 (c))
			token->type = TOKEN_NONE;
		else
		{
			parseIdentifier (token->string, c);
			token->lineNumber = getSourceLineNumber ();
			token->filePosition = getInputFilePosition ();
			token->keyword = analyzeToken (token->string, Lang_vhdl);
			if (isKeyword (token, KEYWORD_NONE))
				token->type = TOKEN_IDENTIFIER;
			else
				token->type = TOKEN_KEYWORD;
		}
		break;
	}
}
Exemple #30
0
static void findHaskellTags (int is_literate)
{
    vString *name = vStringNew ();
    char token[1001], arg[1001];
    int c;
    int in_tex_lit_code = 0;
    c = get_next_char();

    while (c != EOF)
    {
	if (c == '\n') {
	    c = get_next_char();
	    continue;
	}

	if (isspace(c)) {
	    skip_rest_of_line();
	    c = get_next_char();
	    continue;
	}
        if (is_literate && !in_tex_lit_code) {
            if (c == '>') {
                c = fileGetc();
                if (c == ' ') {
                    c = get_next_char();
		    if (!isident(c)) {
			    skip_rest_of_line();
			    c = get_next_char();
			    continue;
		    }
                } else {
                    skip_rest_of_line();
                    c = get_next_char();
                    continue;
                }
            } else if (c == '\\') {
                int n = get_line(token);
                if (strncmp(token, "begin{code}", 11) == 0) {
                    in_tex_lit_code = 1;
                    c = get_next_char();
                    continue;
		} else {
		    if (n > 0 && token[n-1] != '\n')
			skip_rest_of_line();
		    else
			c = get_next_char();
		}
		continue;
            } else {
                skip_rest_of_line();
                c = get_next_char();
                continue;
            }   
        }
        if (is_literate && in_tex_lit_code && c == '\\') {
            if (strncmp(token, "end{code}", 9) == 0) {
                in_tex_lit_code = 0;
                c = get_next_char();
                continue;
            }
        }
	token[0] = c;
	token[1] = '\0';
	if (!isident(c)) {
		skip_rest_of_line();
		c = get_next_char();
		continue;
	}
	if (!get_token(token, 1)) {
		c = get_next_char();
		continue;
	}
	do {
	    if ((c = fileGetc()) == EOF)
		return;
	} while (c == ' ' || c == '\t');
	arg[0] = c;
	get_token(arg, 1);
	if (strcmp(token, "data") == 0 || strcmp(token, "newtype") == 0) {
	    add_tag(arg, K_TYPE, name);
	    c = inside_datatype(name);
	    continue;
	}
	if (strcmp(token, "type") == 0)
	    add_tag(arg, K_TYPE, name);
	else if (strcmp(token, "module") == 0)
	    add_tag(arg, K_MODULE, name);
	else if (strcmp(token, "instance") == 0 ||
		 strcmp(token, "foreign") == 0 ||
		 strcmp(token, "import") == 0)
	    ;
	else {
	    if (arg[0] != ':')
		add_tag(token, K_FUNCTION, name);
	}
	skip_rest_of_line();
	c = get_next_char();
    }
    vStringDelete(name);
}