зеркало из https://github.com/mozilla/pjs.git
1434 строки
41 KiB
C++
1434 строки
41 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#include "IdlScanner.h"
|
|
#include <fstream.h>
|
|
#include <ctype.h>
|
|
|
|
#ifdef XP_MAC
|
|
#pragma warn_possunwant off
|
|
#endif
|
|
|
|
IdlScanner::IdlScanner()
|
|
{
|
|
mFileName = (char*)0;
|
|
mInputFile = new ifstream();
|
|
mToken1 = new Token();
|
|
mToken2 = new Token();
|
|
mCurrentToken = (Token*)0;
|
|
mTokenPeeked = 0;
|
|
mLineNumber = 1;
|
|
for (int i = 0; i < MAX_ID_LENGHT; i++) mTokenName[i] = 0;
|
|
}
|
|
|
|
IdlScanner::~IdlScanner()
|
|
{
|
|
if (mFileName) {
|
|
delete mFileName;
|
|
}
|
|
|
|
delete mInputFile;
|
|
delete mToken1;
|
|
delete mToken2;
|
|
}
|
|
|
|
char* IdlScanner::GetFileName()
|
|
{
|
|
return mFileName;
|
|
}
|
|
|
|
void IdlScanner::SetFileName(char *aFileName)
|
|
{
|
|
if (mFileName) {
|
|
delete mFileName;
|
|
mFileName = (char*)0;
|
|
}
|
|
|
|
if (aFileName) {
|
|
size_t length = strlen(aFileName) + 1;
|
|
mFileName = new char[length];
|
|
strcpy(mFileName, aFileName);
|
|
}
|
|
}
|
|
|
|
long IdlScanner::GetLineNumber()
|
|
{
|
|
return mLineNumber;
|
|
}
|
|
|
|
int IdlScanner::Open(char *aFileName)
|
|
{
|
|
mInputFile->close();
|
|
mInputFile->clear();
|
|
#ifdef XP_MAC
|
|
mInputFile->open(aFileName, ios::in); // no 'nocreate' flag on Mac?
|
|
#else
|
|
mInputFile->open(aFileName, ios::in | ios::nocreate);
|
|
#endif
|
|
SetFileName(aFileName);
|
|
return mInputFile->is_open();
|
|
}
|
|
|
|
int IdlScanner::CanReadMoreData()
|
|
{
|
|
#ifndef XP_MAC
|
|
return !(mInputFile->eof());
|
|
#else
|
|
return !(mInputFile->fail()); // not sure why EOF does not work
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// Read the next token and return it.
|
|
// The difference with NextToken is that consecutive calls to PeekToken
|
|
// return the same token.
|
|
// PeekToken is reset when NextToken is called.
|
|
// This way PeekToken acts like the single token look ahead needed by the parser
|
|
// in order to disambiguate the grammar in some situation.
|
|
// A sequence like - NextToken, PeekToken -
|
|
// returns two different tokens the parser can hold on to decide what to do.
|
|
//
|
|
Token* IdlScanner::PeekToken()
|
|
{
|
|
if (mTokenPeeked == 0) {
|
|
NextToken();
|
|
mTokenPeeked = 1;
|
|
}
|
|
|
|
return mCurrentToken;
|
|
}
|
|
|
|
//
|
|
// Read the next token and return it.
|
|
//
|
|
Token* IdlScanner::NextToken()
|
|
{
|
|
if (mTokenPeeked) {
|
|
mTokenPeeked = 0;
|
|
}
|
|
else {
|
|
SetCurrentToken();
|
|
|
|
int c = EatWhiteSpace();
|
|
if (EOF != c) {
|
|
for (int i = 1; i < MAX_ID_LENGHT; i++) mTokenName[i] = 0;
|
|
mTokenName[0] = c;
|
|
|
|
mCurrentToken->SetToken(ERROR_TOKEN);
|
|
|
|
switch(c) {
|
|
case '(':
|
|
mCurrentToken->SetToken(FUNC_PARAMS_SPEC_BEGIN_TOKEN);
|
|
break;
|
|
case ')':
|
|
mCurrentToken->SetToken(FUNC_PARAMS_SPEC_END_TOKEN);
|
|
break;
|
|
case ',':
|
|
mCurrentToken->SetToken(SEPARATOR_TOKEN);
|
|
break;
|
|
case '/':
|
|
Comment(mTokenName + 1, mCurrentToken); // could be a comment
|
|
break;
|
|
case ':':
|
|
mCurrentToken->SetToken(INHERITANCE_SPEC_TOKEN);
|
|
break;
|
|
case ';':
|
|
mCurrentToken->SetToken(TERMINATOR_TOKEN);
|
|
break;
|
|
case '{':
|
|
mCurrentToken->SetToken(BEGIN_BLOCK_TOKEN);
|
|
break;
|
|
case '}':
|
|
mCurrentToken->SetToken(END_BLOCK_TOKEN);
|
|
break;
|
|
case '=':
|
|
mCurrentToken->SetToken(ASSIGNEMENT_TOKEN);
|
|
break;
|
|
case 'a':
|
|
AKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'b':
|
|
BKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'c':
|
|
CKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'd':
|
|
case 'D':
|
|
DKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'e':
|
|
EKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'f':
|
|
FKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'i':
|
|
IKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'l':
|
|
LKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'n':
|
|
NKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'o':
|
|
OKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'r':
|
|
RKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 's':
|
|
SKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 't':
|
|
TKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'u':
|
|
UKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'v':
|
|
VKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'w':
|
|
WKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case 'x':
|
|
XKeywords(mTokenName + 1, mCurrentToken);
|
|
break;
|
|
case '"':
|
|
String(c, mCurrentToken); // has to be a string
|
|
break;
|
|
case '\'':
|
|
Char(c, mCurrentToken); // has to be a char
|
|
break;
|
|
default:
|
|
if (isalpha(c) || c == '_') {
|
|
Identifier(mTokenName + 1, mCurrentToken); // has to be an identifier
|
|
}
|
|
else if (isdigit(c) || c == '-' || c == '.' || c == '+') {
|
|
Number(c, mCurrentToken); // has to be some sort of number
|
|
}
|
|
else {
|
|
// what to do? throw and exception?
|
|
//throw ScannerUnknownCharacter("Unknow character");
|
|
mCurrentToken->SetToken(ERROR_TOKEN);
|
|
}
|
|
} // switch
|
|
}
|
|
else {
|
|
mCurrentToken->SetToken(EOF_TOKEN);
|
|
}
|
|
}
|
|
|
|
return mCurrentToken;
|
|
}
|
|
|
|
void IdlScanner::SetCurrentToken()
|
|
{
|
|
if (mCurrentToken) {
|
|
if (mCurrentToken == mToken1) {
|
|
mCurrentToken = mToken2;
|
|
return;
|
|
}
|
|
}
|
|
|
|
mCurrentToken = mToken1;
|
|
}
|
|
|
|
//
|
|
// Move to the first usable character and return it.
|
|
// Keep the line number up to date.
|
|
//
|
|
int IdlScanner::EatWhiteSpace()
|
|
{
|
|
int c;
|
|
c = mInputFile->get();
|
|
while (EOF != c) {
|
|
if (isspace(c)) {
|
|
// increment line counter
|
|
if (c == '\n')
|
|
mLineNumber++;
|
|
|
|
c = mInputFile->get();
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return c;
|
|
}
|
|
|
|
//
|
|
// 'attribute' is the only keyword starting with 'a'.
|
|
// If that is not it, it must be an identifier
|
|
//
|
|
void IdlScanner::AKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 't' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 't' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'r' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'i' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'b' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'u' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 't' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'e' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(ATTRIBUTE_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(ATTRIBUTE_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 'boolean' is the only keyword starting with 'b'.
|
|
// If that is not it, it must be an identifier
|
|
//
|
|
void IdlScanner::BKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'l' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'e' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'a' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(BOOLEAN_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(BOOLEAN_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// It's either 'char' or 'const' if it's a keyword
|
|
// otherwise must be an identifier
|
|
//
|
|
void IdlScanner::CKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
char *startPos = aCurrentPos;
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 'h' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'a' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'r' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(CHAR_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(CHAR_TOKEN);
|
|
}
|
|
}
|
|
else if (aCurrentPos == startPos &&
|
|
c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 's' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 't' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(CONST_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(CONST_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 'double' and 'DOMString' are the only keyword starting with 'd'.
|
|
// If that is not it, it must be an identifier
|
|
//
|
|
void IdlScanner::DKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'u' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'b' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'l' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'e' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(DOUBLE_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(DOUBLE_TOKEN);
|
|
}
|
|
}
|
|
else if (c != EOF && c == 'O' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'M' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'S' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 't' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'r' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'i' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'g' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(STRING_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(STRING_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// It's either 'enum' or 'exception' if it's a keyword
|
|
// otherwise must be an identifier
|
|
//
|
|
void IdlScanner::EKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
char *startPos = aCurrentPos;
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 'n' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'u' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'm' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(ENUM_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(ENUM_TOKEN);
|
|
}
|
|
}
|
|
else if (aCurrentPos == startPos &&
|
|
c != EOF && c == 'x' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'c' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'e' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'p' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 't' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'i' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(EXCEPTION_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(EXCEPTION_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 'float' is the only keyword starting with 'f'.
|
|
// If that is not it, it must be an identifier
|
|
//
|
|
void IdlScanner::FKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 'l' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'a' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 't' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(FLOAT_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(FLOAT_TOKEN);
|
|
}
|
|
}
|
|
else if (c != EOF && c == 'u' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'c' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 't' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'i' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(FUNC_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(FUNC_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// One among - 'in' 'inout' 'int' 'interface' - or an identifier
|
|
//
|
|
void IdlScanner::IKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
enum {
|
|
INITIAL_STATE = 0,
|
|
INOUT_O_STATE,
|
|
INOUT_U_STATE,
|
|
INTERFACE_E_STATE,
|
|
INTERFACE_R_STATE,
|
|
INTERFACE_F_STATE,
|
|
INTERFACE_A_STATE,
|
|
INTERFACE_C_STATE,
|
|
|
|
IN_KEYWORD = 100,
|
|
INT_KEYWORD,
|
|
INOUT_KEYWORD,
|
|
INTERFACE_KEYWORD
|
|
};
|
|
int state = INITIAL_STATE; // initial state
|
|
|
|
int c = mInputFile->get();
|
|
while (c != EOF && isalpha(c)) {
|
|
|
|
*aCurrentPos++ = c;
|
|
switch (c) {
|
|
|
|
case 'n':
|
|
if (state == INITIAL_STATE) {
|
|
state = IN_KEYWORD;
|
|
aToken->SetToken(INPUT_PARAM_TOKEN);
|
|
}
|
|
else {
|
|
Identifier(aCurrentPos, aToken);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case 't':
|
|
if (state == IN_KEYWORD) {
|
|
state = INT_KEYWORD;
|
|
aToken->SetToken(INT_TOKEN);
|
|
}
|
|
else if (state == INOUT_U_STATE) {
|
|
state = INOUT_KEYWORD;
|
|
aToken->SetToken(INOUT_PARAM_TOKEN);
|
|
}
|
|
else {
|
|
Identifier(aCurrentPos, aToken);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case 'e':
|
|
if (state == INT_KEYWORD) {
|
|
state = INTERFACE_E_STATE;
|
|
}
|
|
else if (state == INTERFACE_C_STATE) {
|
|
state = INTERFACE_KEYWORD;
|
|
aToken->SetToken(INTERFACE_TOKEN);
|
|
}
|
|
else {
|
|
Identifier(aCurrentPos, aToken);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case 'r':
|
|
if (state == INTERFACE_E_STATE) {
|
|
state = INTERFACE_R_STATE;
|
|
}
|
|
else {
|
|
Identifier(aCurrentPos, aToken);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case 'f':
|
|
if (state == INTERFACE_R_STATE) {
|
|
state = INTERFACE_F_STATE;
|
|
}
|
|
else {
|
|
Identifier(aCurrentPos, aToken);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case 'a':
|
|
if (state == INTERFACE_F_STATE) {
|
|
state = INTERFACE_A_STATE;
|
|
}
|
|
else {
|
|
Identifier(aCurrentPos, aToken);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case 'c':
|
|
if (state == INTERFACE_A_STATE) {
|
|
state = INTERFACE_C_STATE;
|
|
}
|
|
else {
|
|
Identifier(aCurrentPos, aToken);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case 'o':
|
|
if (state == IN_KEYWORD) {
|
|
state = INOUT_O_STATE;
|
|
}
|
|
else {
|
|
Identifier(aCurrentPos, aToken);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case 'u':
|
|
if (state == IN_KEYWORD) {
|
|
state = INOUT_U_STATE;
|
|
}
|
|
else {
|
|
Identifier(aCurrentPos, aToken);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Identifier(aCurrentPos, aToken);
|
|
return;
|
|
}
|
|
|
|
c = mInputFile->get();
|
|
}
|
|
|
|
if (c == EOF) {
|
|
if (state < IN_KEYWORD) {
|
|
// end of file, return the identifier
|
|
aToken->SetToken(IDENTIFIER_TOKEN, mTokenName);
|
|
}
|
|
}
|
|
// if it is a digit or an underscore the token is
|
|
// not terminated yet
|
|
else if (isdigit(c) || c == '_') {
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 'long' is the only keyword starting with 'l'.
|
|
// If that is not it, it must be an identifier
|
|
//
|
|
void IdlScanner::LKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'g' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(LONG_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(LONG_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 'noscript' is the only keyword starting with 'nl'.
|
|
// If that is not it, it must be an identifier
|
|
//
|
|
void IdlScanner::NKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 's' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'c' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'r' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'i' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'p' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 't' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(NOSCRIPT_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(NOSCRIPT_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 'out' is the only keyword starting with 'o'.
|
|
// If that is not it, it must be an identifier
|
|
//
|
|
void IdlScanner::OKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 'u' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 't' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(OUTPUT_PARAM_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(OUTPUT_PARAM_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// it's either 'readonly' or 'raises' if it is a keyword.
|
|
// Otherwise, it must be an identifier
|
|
//
|
|
void IdlScanner::RKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 'e' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'a' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'd' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'l' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'y' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(READONLY_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(READONLY_TOKEN);
|
|
}
|
|
}
|
|
else if (c != EOF && c == 'a' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'i' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 's' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'e' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 's' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(RAISES_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(RAISES_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// One among - 'short' 'string' 'struct' - or an identifier
|
|
//
|
|
void IdlScanner::SKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
char *startPos = aCurrentPos;
|
|
int c = mInputFile->get();
|
|
// chaeck for 'tr'
|
|
if (c != EOF && c == 't' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'r' && (*aCurrentPos++ = c) && (c = mInputFile->get())) {
|
|
|
|
if (c != EOF && c == 'i' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'g' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(STRING_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(STRING_TOKEN);
|
|
}
|
|
}
|
|
else if (aCurrentPos == startPos + 2 &&
|
|
c != EOF && c == 'u' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'c' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 't' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(STRUCT_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(STRUCT_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
else if (aCurrentPos == startPos &&
|
|
c != EOF && c == 'h' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'r' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 't' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(SHORT_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(SHORT_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 'typedef' is the only keyword starting with 't'.
|
|
// If that is not it, it must be an identifier
|
|
//
|
|
void IdlScanner::TKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 'y' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'p' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'e' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'd' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'e' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'f' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(TYPEDEF_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(TYPEDEF_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// It's either 'union', 'unsigned' or 'unknown' if it's a keyword
|
|
// otherwise must be an identifier
|
|
//
|
|
void IdlScanner::UKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
char *startPos = aCurrentPos;
|
|
int c = mInputFile->get();
|
|
// 'n' must follow
|
|
if (c != EOF && c == 'n' && (*aCurrentPos++ = c) && (c = mInputFile->get())) {
|
|
|
|
if (c != EOF && c == 'i' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(UNION_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(UNION_TOKEN);
|
|
}
|
|
}
|
|
else if (aCurrentPos == startPos + 1 &&
|
|
c != EOF && c == 's' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'i' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'g' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'e' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'd' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
// find out what kind of "unsigned type" is
|
|
SetCurrentToken(); // this is just to make sure next call uses the same token
|
|
NextToken();
|
|
if (SHORT_TOKEN == mCurrentToken->id) {
|
|
aToken->SetToken(USHORT_TOKEN);
|
|
}
|
|
else if (INT_TOKEN == mCurrentToken->id) {
|
|
aToken->SetToken(UINT_TOKEN);
|
|
}
|
|
else if (LONG_TOKEN == mCurrentToken->id) {
|
|
aToken->SetToken(ULONG_TOKEN);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (aCurrentPos == startPos + 1 &&
|
|
c != EOF && c == 'k' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'w' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(UNKNOWN_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(UNION_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 'void' is the only keyword starting with 'v'.
|
|
// If that is not it, it must be an identifier
|
|
//
|
|
void IdlScanner::VKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 'o' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'i' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'd' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(VOID_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(VOID_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 'wstring' is the only keyword starting with 'w'.
|
|
// If that is not it, it must be an identifier
|
|
//
|
|
void IdlScanner::WKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 's' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 't' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'r' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'i' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'n' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'g' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(STRING_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(STRING_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Either 'xpidl' or an identifier
|
|
//
|
|
void IdlScanner::XKeywords(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int c = mInputFile->get();
|
|
if (c != EOF && c == 'p' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'i' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'd' && (*aCurrentPos++ = c) && (c = mInputFile->get()) &&
|
|
c != EOF && c == 'l' && (*aCurrentPos++ = c)) {
|
|
// if terminated is a keyword
|
|
c = mInputFile->get();
|
|
if (c != EOF) {
|
|
if (isalpha(c) || isdigit(c) || c == '_') {
|
|
// more characters, it must be an identifier
|
|
*aCurrentPos++ = c;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it is a keyword
|
|
aToken->SetToken(XPIDL_TOKEN);
|
|
mInputFile->putback(c);
|
|
}
|
|
}
|
|
else {
|
|
aToken->SetToken(XPIDL_TOKEN);
|
|
}
|
|
}
|
|
else {
|
|
// it must be an identifier
|
|
KeywordMismatch(c, aCurrentPos, aToken);
|
|
}
|
|
}
|
|
|
|
void IdlScanner::Identifier(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int index = aCurrentPos - mTokenName;
|
|
int c = mInputFile->get();
|
|
|
|
while (isalpha(c) || isdigit(c) || c == '_') {
|
|
if (index > 254) {
|
|
//XXX throw exception?
|
|
}
|
|
else {
|
|
mTokenName[index++] = c;
|
|
}
|
|
c = mInputFile->get();
|
|
}
|
|
|
|
if (c != EOF) {
|
|
mInputFile->putback(c);
|
|
}
|
|
|
|
aToken->SetToken(IDENTIFIER_TOKEN, mTokenName);
|
|
}
|
|
|
|
void IdlScanner::Number(int aStartChar, Token *aToken)
|
|
{
|
|
long sign = 1;
|
|
long value = 0;
|
|
|
|
if (aStartChar == '-') {
|
|
sign = -1;
|
|
aStartChar = mInputFile->get();
|
|
}
|
|
else if (aStartChar == '.') {
|
|
// double. Deal with it later
|
|
aStartChar = mInputFile->get();
|
|
}
|
|
|
|
if (isdigit(aStartChar)) {
|
|
long base = 10;
|
|
if ('0' == aStartChar) {
|
|
aStartChar = mInputFile->get();
|
|
if (('x' == aStartChar) || ('X' == aStartChar)) {
|
|
base = 16;
|
|
aStartChar = mInputFile->get();
|
|
}
|
|
else if (isdigit(aStartChar)) {
|
|
base = 8;
|
|
}
|
|
else {
|
|
mInputFile->putback(aStartChar);
|
|
aStartChar = '0';
|
|
}
|
|
}
|
|
|
|
do {
|
|
long digit;
|
|
if (isdigit(aStartChar)) {
|
|
digit = aStartChar - '0';
|
|
}
|
|
else if ((aStartChar >= 'a') && (aStartChar <= 'f')) {
|
|
digit = 10 + (aStartChar - 'a');
|
|
}
|
|
else if ((aStartChar >= 'A') && (aStartChar <= 'F')) {
|
|
digit = 10 + (aStartChar - 'A');
|
|
}
|
|
|
|
value = value * base + digit;
|
|
aStartChar = mInputFile->get();
|
|
} while (isdigit(aStartChar) || ((aStartChar >= 'a') && (aStartChar <= 'f')) || ((aStartChar >= 'A') && (aStartChar <= 'F')));
|
|
|
|
if (aStartChar == '.') {
|
|
// double. Deal with it later
|
|
}
|
|
else {
|
|
mInputFile->putback(aStartChar);
|
|
}
|
|
|
|
aToken->SetTokenValue(INTEGER_CONSTANT, value * sign);
|
|
}
|
|
}
|
|
|
|
void IdlScanner::String(int aStartChar, Token *aToken)
|
|
{
|
|
}
|
|
|
|
void IdlScanner::Char(int aStartChar, Token *aToken)
|
|
{
|
|
}
|
|
|
|
#define DEFAULT_COMMENT_SIZE 512
|
|
static char *kOptionalStr = "/* optional ";
|
|
static char *kEllipsisStr = "/* ... ";
|
|
static char *kIIDStr = "/* IID:";
|
|
|
|
void IdlScanner::Comment(char *aCurrentPos, Token *aToken)
|
|
{
|
|
int bufferSize = DEFAULT_COMMENT_SIZE;
|
|
char *aCommentBuffer = new char[bufferSize];
|
|
aCommentBuffer[0] = '/'; // that's why we are here
|
|
aCommentBuffer[1] = mInputFile->get();
|
|
|
|
// c++ comment style
|
|
if (aCommentBuffer[1] == '/') {
|
|
aCommentBuffer[2] = mInputFile->get();
|
|
char *pos = aCommentBuffer + 2; // point to the current char
|
|
// untill end of line
|
|
while (*pos++ != '\n') {
|
|
if (pos - aCommentBuffer == bufferSize) {
|
|
// grow the size of the buffer
|
|
*pos = '\0';
|
|
bufferSize *= 2;
|
|
char *newBuffer = new char[bufferSize];
|
|
strcpy(newBuffer, aCommentBuffer);
|
|
delete[] aCommentBuffer;
|
|
aCommentBuffer = newBuffer;
|
|
pos = aCommentBuffer + bufferSize / 2;
|
|
}
|
|
*pos = mInputFile->get();
|
|
}
|
|
// go back one and terminate the string
|
|
*--pos = '\0';
|
|
// increment line count
|
|
mLineNumber++;
|
|
|
|
aToken->SetToken(COMMENT_TOKEN, aCommentBuffer);
|
|
}
|
|
// c comment style
|
|
else if (aCommentBuffer[1] == '*') {
|
|
aCommentBuffer[2] = mInputFile->get();
|
|
aCommentBuffer[3] = mInputFile->get();
|
|
char *pos = aCommentBuffer + 3; // point to the current char
|
|
// untill end of comment
|
|
while (*(pos - 1) != '*' && *pos++ != '/') {
|
|
if (pos - aCommentBuffer == bufferSize) {
|
|
// grow the size of the buffer
|
|
*pos = '\0';
|
|
bufferSize *= 2;
|
|
char *newBuffer = new char[bufferSize];
|
|
strcpy(newBuffer, aCommentBuffer);
|
|
delete[] aCommentBuffer;
|
|
aCommentBuffer = newBuffer;
|
|
pos = aCommentBuffer + bufferSize / 2;
|
|
}
|
|
*pos = mInputFile->get();
|
|
// increment line counter
|
|
if (*pos == '\n')
|
|
mLineNumber++;
|
|
}
|
|
// go back one and terminate the string
|
|
*--pos = '\0';
|
|
|
|
if (strcmp(aCommentBuffer, kOptionalStr) == 0) {
|
|
aToken->SetToken(OPTIONAL_TOKEN, aCommentBuffer);
|
|
}
|
|
else if (strcmp(aCommentBuffer, kEllipsisStr) == 0) {
|
|
aToken->SetToken(ELLIPSIS_TOKEN, aCommentBuffer);
|
|
}
|
|
else if (strncmp(aCommentBuffer, kIIDStr, strlen(kIIDStr)) == 0) {
|
|
aToken->SetToken(IID_TOKEN, aCommentBuffer + strlen(kIIDStr));
|
|
}
|
|
else {
|
|
aToken->SetToken(COMMENT_TOKEN, aCommentBuffer);
|
|
}
|
|
}
|
|
else {
|
|
// don't deal with it for now. It will report an error
|
|
}
|
|
|
|
delete[] aCommentBuffer;
|
|
}
|
|
|
|
void IdlScanner::KeywordMismatch(int aChar, char *aCurrentPos, Token *aToken)
|
|
{
|
|
if (aChar != EOF) {
|
|
// we did not read a keyword, must be an identifier
|
|
if (isalpha(aChar) || isdigit(aChar) || aChar == '_') {
|
|
// finish reading the identifier
|
|
*aCurrentPos++ = aChar;
|
|
Identifier(aCurrentPos, aToken);
|
|
}
|
|
else {
|
|
// it's some terminator character, return the identifier
|
|
aToken->SetToken(IDENTIFIER_TOKEN, mTokenName);
|
|
mInputFile->putback(aChar);
|
|
}
|
|
}
|
|
else {
|
|
// end of file, return the identifier
|
|
aToken->SetToken(IDENTIFIER_TOKEN, mTokenName);
|
|
}
|
|
}
|
|
|