mirror of https://github.com/Kitware/CMake.git
Browse Source
ENH: Using lex-based tokenizer and a simple recursive-descent parser in place of the old hand-coded parser for CMake listfiles.
pull/1/head
ENH: Using lex-based tokenizer and a simple recursive-descent parser in place of the old hand-coded parser for CMake listfiles.
pull/1/head

6 changed files with 2719 additions and 230 deletions
-
1Source/CMakeLists.txt
-
327Source/cmListFileCache.cxx
-
19Source/cmListFileCache.h
-
2216Source/cmListFileLexer.c
-
60Source/cmListFileLexer.h
-
326Source/cmListFileLexer.l
2216
Source/cmListFileLexer.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,60 @@ |
|||
/*========================================================================= |
|||
|
|||
Program: CMake - Cross-Platform Makefile Generator |
|||
Module: $RCSfile$ |
|||
Language: C++ |
|||
Date: $Date$ |
|||
Version: $Revision$ |
|||
|
|||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. |
|||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. |
|||
|
|||
This software is distributed WITHOUT ANY WARRANTY; without even |
|||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
|||
PURPOSE. See the above copyright notices for more information. |
|||
|
|||
=========================================================================*/ |
|||
#ifndef cmListFileLexer_h |
|||
#define cmListFileLexer_h |
|||
|
|||
typedef enum cmListFileLexer_Type_e |
|||
{ |
|||
cmListFileLexer_Token_None, |
|||
cmListFileLexer_Token_Newline, |
|||
cmListFileLexer_Token_Identifier, |
|||
cmListFileLexer_Token_ParenLeft, |
|||
cmListFileLexer_Token_ParenRight, |
|||
cmListFileLexer_Token_ArgumentUnquoted, |
|||
cmListFileLexer_Token_ArgumentQuoted, |
|||
cmListFileLexer_Token_Error |
|||
} cmListFileLexer_Type; |
|||
|
|||
typedef struct cmListFileLexer_Token_s cmListFileLexer_Token; |
|||
struct cmListFileLexer_Token_s |
|||
{ |
|||
cmListFileLexer_Type type; |
|||
char* text; |
|||
int length; |
|||
int line; |
|||
int column; |
|||
}; |
|||
|
|||
typedef struct cmListFileLexer_s cmListFileLexer; |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" |
|||
{ |
|||
#endif |
|||
|
|||
cmListFileLexer* cmListFileLexer_New(); |
|||
int cmListFileLexer_SetFileName(cmListFileLexer*, const char*); |
|||
cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer*); |
|||
long cmListFileLexer_GetCurrentLine(cmListFileLexer*); |
|||
long cmListFileLexer_GetCurrentColumn(cmListFileLexer*); |
|||
void cmListFileLexer_Delete(cmListFileLexer*); |
|||
|
|||
#ifdef __cplusplus |
|||
} /* extern "C" */ |
|||
#endif |
|||
|
|||
#endif |
@ -0,0 +1,326 @@ |
|||
%{ |
|||
/*========================================================================= |
|||
|
|||
Program: CMake - Cross-Platform Makefile Generator |
|||
Module: $RCSfile$ |
|||
Language: C++ |
|||
Date: $Date$ |
|||
Version: $Revision$ |
|||
|
|||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. |
|||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. |
|||
|
|||
This software is distributed WITHOUT ANY WARRANTY; without even |
|||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
|||
PURPOSE. See the above copyright notices for more information. |
|||
|
|||
=========================================================================*/ |
|||
/* |
|||
|
|||
This file must be translated to C and modified to build everywhere. |
|||
|
|||
Run flex like this: |
|||
|
|||
flex -ocmListFileLexer.c cmListFileLexer.l |
|||
|
|||
Modify cmListFileLexer.c: |
|||
- remove TABs |
|||
- remove the yyunput function |
|||
- add a statement "(void)yyscanner;" to the top of these methods: |
|||
yy_fatal_error, yyalloc, yyrealloc, yyfree |
|||
|
|||
*/ |
|||
|
|||
/* Disable features we do not need. */ |
|||
#define YY_NEVER_INTERACTIVE 1 |
|||
#define YY_NO_UNPUT 1 |
|||
#define ECHO |
|||
|
|||
/* Setup the proper yylex declaration. */ |
|||
#define YY_DECL int yylex (yyscan_t yyscanner, cmListFileLexer* lexer) |
|||
|
|||
/* Disable some warnings. */ |
|||
#if defined(_MSC_VER) |
|||
# pragma warning ( disable : 4127 ) |
|||
# pragma warning ( disable : 4131 ) |
|||
# pragma warning ( disable : 4244 ) |
|||
# pragma warning ( disable : 4251 ) |
|||
# pragma warning ( disable : 4267 ) |
|||
# pragma warning ( disable : 4305 ) |
|||
# pragma warning ( disable : 4309 ) |
|||
# pragma warning ( disable : 4706 ) |
|||
# pragma warning ( disable : 4786 ) |
|||
#endif |
|||
|
|||
#include "cmListFileLexer.h" |
|||
|
|||
/*--------------------------------------------------------------------------*/ |
|||
struct cmListFileLexer_s |
|||
{ |
|||
cmListFileLexer_Token token; |
|||
int line; |
|||
int column; |
|||
int size; |
|||
FILE* file; |
|||
yyscan_t scanner; |
|||
}; |
|||
|
|||
static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text, |
|||
int length); |
|||
static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text, |
|||
int length); |
|||
|
|||
/*--------------------------------------------------------------------------*/ |
|||
%} |
|||
|
|||
%option reentrant |
|||
%option yylineno |
|||
%option noyywrap |
|||
%pointer |
|||
%x STRING |
|||
|
|||
%% |
|||
|
|||
\n { |
|||
lexer->token.type = cmListFileLexer_Token_Newline; |
|||
cmListFileLexerSetToken(lexer, yytext, yyleng); |
|||
++lexer->line; |
|||
lexer->column = 1; |
|||
return 1; |
|||
} |
|||
|
|||
#.* { |
|||
lexer->column += yyleng; |
|||
} |
|||
|
|||
\( { |
|||
lexer->token.type = cmListFileLexer_Token_ParenLeft; |
|||
cmListFileLexerSetToken(lexer, yytext, yyleng); |
|||
lexer->column += yyleng; |
|||
return 1; |
|||
} |
|||
|
|||
\) { |
|||
lexer->token.type = cmListFileLexer_Token_ParenRight; |
|||
cmListFileLexerSetToken(lexer, yytext, yyleng); |
|||
lexer->column += yyleng; |
|||
return 1; |
|||
} |
|||
|
|||
[A-Za-z_][A-Za-z0-9_]+ { |
|||
lexer->token.type = cmListFileLexer_Token_Identifier; |
|||
cmListFileLexerSetToken(lexer, yytext, yyleng); |
|||
lexer->column += yyleng; |
|||
return 1; |
|||
} |
|||
|
|||
([^ \t\r\n\(\)\"\\]|\\.)+ { |
|||
lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted; |
|||
cmListFileLexerSetToken(lexer, yytext, yyleng); |
|||
lexer->column += yyleng; |
|||
return 1; |
|||
} |
|||
|
|||
\" { |
|||
lexer->token.type = cmListFileLexer_Token_ArgumentQuoted; |
|||
cmListFileLexerSetToken(lexer, "", 0); |
|||
lexer->column += yyleng; |
|||
BEGIN(STRING); |
|||
} |
|||
|
|||
<STRING>([^\\\n\"]|\\(.|\n))+ { |
|||
cmListFileLexerAppend(lexer, yytext, yyleng); |
|||
lexer->column += yyleng; |
|||
} |
|||
|
|||
<STRING>\n { |
|||
cmListFileLexerAppend(lexer, yytext, yyleng); |
|||
++lexer->line; |
|||
lexer->column = 1; |
|||
} |
|||
|
|||
<STRING>\" { |
|||
lexer->column += yyleng; |
|||
BEGIN(INITIAL); |
|||
return 1; |
|||
} |
|||
|
|||
<STRING>. { |
|||
cmListFileLexerAppend(lexer, yytext, yyleng); |
|||
lexer->column += yyleng; |
|||
} |
|||
|
|||
[ \t\r] { |
|||
lexer->column += yyleng; |
|||
} |
|||
|
|||
. { |
|||
lexer->token.type = cmListFileLexer_Token_Error; |
|||
cmListFileLexerSetToken(lexer, yytext, yyleng); |
|||
lexer->column += yyleng; |
|||
return 1; |
|||
} |
|||
|
|||
<<EOF>> { |
|||
lexer->token.type = cmListFileLexer_Token_None; |
|||
cmListFileLexerSetToken(lexer, 0, 0); |
|||
return 0; |
|||
} |
|||
|
|||
%% |
|||
|
|||
/*--------------------------------------------------------------------------*/ |
|||
void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text, |
|||
int length) |
|||
{ |
|||
/* Set the token line and column number. */ |
|||
lexer->token.line = lexer->line; |
|||
lexer->token.column = lexer->column; |
|||
|
|||
/* Use the same buffer if possible. */ |
|||
if(lexer->token.text) |
|||
{ |
|||
if(text && length < lexer->size) |
|||
{ |
|||
strcpy(lexer->token.text, text); |
|||
lexer->token.length = length; |
|||
return; |
|||
} |
|||
free(lexer->token.text); |
|||
lexer->token.text = 0; |
|||
lexer->size = 0; |
|||
} |
|||
|
|||
/* Need to extend the buffer. */ |
|||
if(text) |
|||
{ |
|||
lexer->token.text = strdup(text); |
|||
lexer->token.length = length; |
|||
lexer->size = length+1; |
|||
} |
|||
else |
|||
{ |
|||
lexer->token.length = 0; |
|||
} |
|||
} |
|||
|
|||
/*--------------------------------------------------------------------------*/ |
|||
void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text, |
|||
int length) |
|||
{ |
|||
char* temp; |
|||
int newSize; |
|||
|
|||
/* If the appended text will fit in the buffer, do not reallocate. */ |
|||
newSize = lexer->token.length + length + 1; |
|||
if(lexer->token.text && newSize <= lexer->size) |
|||
{ |
|||
strcpy(lexer->token.text+lexer->token.length, text); |
|||
lexer->token.length += length; |
|||
return; |
|||
} |
|||
|
|||
/* We need to extend the buffer. */ |
|||
temp = malloc(newSize); |
|||
if(lexer->token.text) |
|||
{ |
|||
memcpy(temp, lexer->token.text, lexer->token.length); |
|||
free(lexer->token.text); |
|||
} |
|||
memcpy(temp+lexer->token.length, text, length); |
|||
temp[lexer->token.length+length] = 0; |
|||
lexer->token.text = temp; |
|||
lexer->token.length += length; |
|||
lexer->size = newSize; |
|||
} |
|||
|
|||
/*--------------------------------------------------------------------------*/ |
|||
cmListFileLexer* cmListFileLexer_New() |
|||
{ |
|||
cmListFileLexer* lexer = (cmListFileLexer*)malloc(sizeof(cmListFileLexer)); |
|||
if(!lexer) |
|||
{ |
|||
return 0; |
|||
} |
|||
memset(lexer, 0, sizeof(*lexer)); |
|||
lexer->line = 1; |
|||
lexer->column = 1; |
|||
return lexer; |
|||
} |
|||
|
|||
/*--------------------------------------------------------------------------*/ |
|||
void cmListFileLexer_Delete(cmListFileLexer* lexer) |
|||
{ |
|||
cmListFileLexer_SetFileName(lexer, 0); |
|||
free(lexer); |
|||
} |
|||
|
|||
/*--------------------------------------------------------------------------*/ |
|||
int cmListFileLexer_SetFileName(cmListFileLexer* lexer, const char* name) |
|||
{ |
|||
int result = 1; |
|||
if(lexer->file) |
|||
{ |
|||
yylex_destroy(lexer->scanner); |
|||
fclose(lexer->file); |
|||
lexer->file = 0; |
|||
} |
|||
if(name) |
|||
{ |
|||
lexer->file = fopen(name, "r"); |
|||
if(!lexer->file) |
|||
{ |
|||
result = 0; |
|||
} |
|||
} |
|||
if(lexer->file) |
|||
{ |
|||
yylex_init(&lexer->scanner); |
|||
yyset_in(lexer->file, lexer->scanner); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
/*--------------------------------------------------------------------------*/ |
|||
cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer) |
|||
{ |
|||
if(!lexer->file) |
|||
{ |
|||
return 0; |
|||
} |
|||
if(yylex(lexer->scanner, lexer)) |
|||
{ |
|||
return &lexer->token; |
|||
} |
|||
else |
|||
{ |
|||
cmListFileLexer_SetFileName(lexer, 0); |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
/*--------------------------------------------------------------------------*/ |
|||
long cmListFileLexer_GetCurrentLine(cmListFileLexer* lexer) |
|||
{ |
|||
if(lexer->file) |
|||
{ |
|||
return lexer->line; |
|||
} |
|||
else |
|||
{ |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
/*--------------------------------------------------------------------------*/ |
|||
long cmListFileLexer_GetCurrentColumn(cmListFileLexer* lexer) |
|||
{ |
|||
if(lexer->file) |
|||
{ |
|||
return lexer->column; |
|||
} |
|||
else |
|||
{ |
|||
return 0; |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue