mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-23 20:42:24 +00:00
- Undid some of the changes from lempar.c v1.30->v1.31, because it broke
error handling. - Fixed: dehsupp/scanner.re defined "}" as the token RPAREN. dehsupp/parse.y also defined action_list_def as needing a RBARCE. I'm surprised it worked at all before. I guess Lemon really was too accepting. - Changed the way that xlatcc handles include statements so that I don't need to modify the logic of lempar.c. I also discovered that the grammar was improperly defined and only accepted the first statement. It worked before because Lemon used to accept multiple times before reaching the EOF token. I have also verified that it is still generating the proper lumps. - Removed some unused wadsrc files from the repository. - Fixed my re2c upgrade. - Updated lemon.c to v1.53. SVN r711 (trunk)
This commit is contained in:
parent
e5572a1c4e
commit
ec17f5a5b9
46 changed files with 9134 additions and 8988 deletions
|
@ -1,4 +1,22 @@
|
|||
January 25, 2008
|
||||
- Undid some of the changes from lempar.c v1.30->v1.31, because it broke
|
||||
error handling.
|
||||
- Fixed: dehsupp/scanner.re defined "}" as the token RPAREN. dehsupp/parse.y
|
||||
also defined action_list_def as needing a RBARCE. I'm surprised it worked
|
||||
at all before. I guess Lemon really was too accepting. I have verified that
|
||||
the lump it outputs is unchanged from before.
|
||||
- Changed the way that xlatcc handles include statements so that I don't need
|
||||
to modify the logic of lempar.c. I also discovered that the grammar was
|
||||
improperly defined and only accepted the first statement. It worked before
|
||||
because Lemon used to accept multiple times before reaching the EOF token.
|
||||
I have also verified that it is still generating the proper lumps.
|
||||
- Removed some unused wadsrc files from the repository.
|
||||
- Fixed my re2c upgrade.
|
||||
- Back to lemon.c v1.53 now. The bad change was v1.51: "Changes lemon so
|
||||
that the generated parser does not accept prior to seeing the EOF token."
|
||||
This seems like a valid change, which means I need to rethink my strategy
|
||||
for handling include statements, since this change breaks what I was
|
||||
doing before.
|
||||
- Lemon is now producing parsers that don't accept anything, so I'm going
|
||||
back to v1.43 and trying each intermediate version to see where things
|
||||
went wrong.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Generated by re2c 0.10.5 */
|
||||
/* Generated by re2c 0.12.3 */
|
||||
#line 1 "src/sc_man_scanner.re"
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR cursor
|
||||
|
@ -42,7 +42,7 @@ std2:
|
|||
|
||||
if((YYLIMIT - YYCURSOR) < 18) YYFILL(18);
|
||||
yych = *YYCURSOR;
|
||||
switch(yych){
|
||||
switch(yych) {
|
||||
case 0x09:
|
||||
case 0x0B:
|
||||
case 0x0C:
|
||||
|
@ -181,7 +181,7 @@ yy5:
|
|||
#line 182 "src/sc_man_scanner.h"
|
||||
yy6:
|
||||
yych = *++YYCURSOR;
|
||||
switch(yych){
|
||||
switch(yych) {
|
||||
case 'A':
|
||||
case 'a': goto yy536;
|
||||
case 'H':
|
||||
|
@ -309,7 +309,7 @@ yy12:
|
|||
goto yy174;
|
||||
yy13:
|
||||
yych = *++YYCURSOR;
|
||||
switch(yych){
|
||||
switch(yych) {
|
||||
case 'B':
|
||||
case 'b': goto yy346;
|
||||
case 'E':
|
||||
|
@ -330,7 +330,7 @@ yy13:
|
|||
}
|
||||
yy14:
|
||||
yych = *++YYCURSOR;
|
||||
switch(yych){
|
||||
switch(yych) {
|
||||
case 'I':
|
||||
case 'i': goto yy326;
|
||||
case 'L':
|
||||
|
|
|
@ -48,6 +48,9 @@ int main (int argc, char **argv)
|
|||
printf ("Could not open %s\n", argv[1]);
|
||||
return -2;
|
||||
}
|
||||
#if !defined(NDEBUG) && 0
|
||||
ParseTrace(fopen("trace.txt", "w"), "");
|
||||
#endif
|
||||
SourceLine = 1;
|
||||
yyparse ();
|
||||
fclose (Source);
|
||||
|
|
|
@ -424,7 +424,7 @@
|
|||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="Creating scanner.c from scanner.re"
|
||||
CommandLine="..\re2c\re2c -s -o "scanner.c" "$(InputFileName)"
"
|
||||
CommandLine="..\re2c\re2c -s --no-generation-date -o "scanner.c" "$(InputFileName)"
"
|
||||
Outputs="$(InputDir)scanner.c"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
|
@ -444,7 +444,7 @@
|
|||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="Creating scanner.c from scanner.re"
|
||||
CommandLine="..\re2c\re2c -s -o "scanner.c" "$(InputFileName)"
"
|
||||
CommandLine="..\re2c\re2c -s --no-generation-date -o "scanner.c" "$(InputFileName)"
"
|
||||
Outputs="$(InputDir)scanner.c"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,14 +21,13 @@
|
|||
#define SYM 21
|
||||
#define OrgHeights 22
|
||||
#define ActionList 23
|
||||
#define RBARCE 24
|
||||
#define CodePConv 25
|
||||
#define OrgSprNames 26
|
||||
#define StateMap 27
|
||||
#define FirstState 28
|
||||
#define SpawnState 29
|
||||
#define DeathState 30
|
||||
#define SoundMap 31
|
||||
#define InfoNames 32
|
||||
#define ThingBits 33
|
||||
#define RenderStyles 34
|
||||
#define CodePConv 24
|
||||
#define OrgSprNames 25
|
||||
#define StateMap 26
|
||||
#define FirstState 27
|
||||
#define SpawnState 28
|
||||
#define DeathState 29
|
||||
#define SoundMap 30
|
||||
#define InfoNames 31
|
||||
#define ThingBits 32
|
||||
#define RenderStyles 33
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
%token_type {struct Token}
|
||||
|
||||
%syntax_error { yyerror("Syntax error"); }
|
||||
|
||||
%token_destructor { if ($$.string) free($$.string); }
|
||||
|
||||
%left OR.
|
||||
|
@ -60,6 +62,7 @@ exp(A) ::= LPAREN exp(B) RPAREN. { A = B; }
|
|||
|
||||
|
||||
actions_def ::= Actions LBRACE actions_list RBRACE SEMICOLON.
|
||||
actions_def ::= Actions LBRACE error RBRACE SEMICOLON.
|
||||
|
||||
actions_list ::= . /* empty */
|
||||
actions_list ::= SYM(A). { AddAction (A.string); }
|
||||
|
@ -67,13 +70,15 @@ actions_list ::= actions_list COMMA SYM(A). { AddAction (A.string); }
|
|||
|
||||
|
||||
org_heights_def ::= OrgHeights LBRACE org_heights_list RBRACE SEMICOLON.
|
||||
org_heights_def ::= OrgHeights LBRACE error RBRACE SEMICOLON.
|
||||
|
||||
org_heights_list ::= . /* empty */
|
||||
org_heights_list ::= exp(A). { AddHeight (A); }
|
||||
org_heights_list ::= org_heights_list COMMA exp(A). { AddHeight (A); }
|
||||
|
||||
|
||||
action_list_def ::= ActionList LBRACE action_list_list RBARCE SEMICOLON.
|
||||
action_list_def ::= ActionList LBRACE action_list_list RBRACE SEMICOLON.
|
||||
action_list_def ::= ActionList LBRACE error RBRACE SEMICOLON.
|
||||
|
||||
action_list_list ::= . /* empty */
|
||||
action_list_list ::= SYM(A). { AddActionMap (A.string); }
|
||||
|
@ -81,6 +86,7 @@ action_list_list ::= action_list_list COMMA SYM(A). { AddActionMap (A.string); }
|
|||
|
||||
|
||||
codep_conv_def ::= CodePConv LBRACE codep_conv_list RBRACE SEMICOLON.
|
||||
codep_conv_def ::= CodePConv LBRACE error RBRACE SEMICOLON.
|
||||
|
||||
codep_conv_list ::= . /* empty */
|
||||
codep_conv_list ::= exp(A). { AddCodeP (A); }
|
||||
|
@ -88,6 +94,7 @@ codep_conv_list ::= codep_conv_list COMMA exp(A). { AddCodeP (A); }
|
|||
|
||||
|
||||
org_spr_names_def ::= OrgSprNames LBRACE org_spr_names_list RBRACE SEMICOLON.
|
||||
org_spr_names_def ::= OrgSprNames LBRACE error RBRACE SEMICOLON.
|
||||
|
||||
org_spr_names_list ::= . /* empty */
|
||||
org_spr_names_list ::= SYM(A). { AddSpriteName (A.string); }
|
||||
|
@ -95,6 +102,7 @@ org_spr_names_list ::= org_spr_names_list COMMA SYM(A). { AddSpriteName (A.strin
|
|||
|
||||
|
||||
state_map_def ::= StateMap LBRACE state_map_list RBRACE SEMICOLON.
|
||||
state_map_def ::= StateMap LBRACE error RBRACE SEMICOLON.
|
||||
|
||||
state_map_list ::= . /* empty */
|
||||
state_map_list ::= state_map_entry.
|
||||
|
@ -109,6 +117,7 @@ state_type(A) ::= DeathState. { A = 2; }
|
|||
|
||||
|
||||
sound_map_def ::= SoundMap LBRACE sound_map_list RBRACE SEMICOLON.
|
||||
sound_map_def ::= SoundMap LBRACE error RBRACE SEMICOLON.
|
||||
|
||||
sound_map_list ::= . /* empty */
|
||||
sound_map_list ::= STRING(A). { AddSoundMap (A.string); }
|
||||
|
@ -116,6 +125,7 @@ sound_map_list ::= sound_map_list COMMA STRING(A). { AddSoundMap (A.string); }
|
|||
|
||||
|
||||
info_names_def ::= InfoNames LBRACE info_names_list RBRACE SEMICOLON.
|
||||
info_names_def ::= InfoNames LBRACE error RBRACE SEMICOLON.
|
||||
|
||||
info_names_list ::= . /* empty */
|
||||
info_names_list ::= SYM(A). { AddInfoName (A.string); }
|
||||
|
@ -123,6 +133,7 @@ info_names_list ::= info_names_list COMMA SYM(A). { AddInfoName (A.string); }
|
|||
|
||||
|
||||
thing_bits_def ::= ThingBits LBRACE thing_bits_list RBRACE SEMICOLON.
|
||||
thing_bits_def ::= ThingBits LBRACE error RBRACE SEMICOLON.
|
||||
|
||||
thing_bits_list ::= . /* empty */
|
||||
thing_bits_list ::= thing_bits_entry.
|
||||
|
@ -132,6 +143,7 @@ thing_bits_entry ::= exp(A) COMMA exp(B) COMMA SYM(C). { AddThingBits (C.string,
|
|||
|
||||
|
||||
render_styles_def ::= RenderStyles LBRACE render_styles_list RBRACE SEMICOLON.
|
||||
render_styles_def ::= RenderStyles LBRACE error RBRACE SEMICOLON.
|
||||
|
||||
render_styles_list ::= . /* empty */
|
||||
render_styles_list ::= render_styles_entry.
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -106,7 +106,7 @@ ESC = [\\] ([abfnrtv?'"\\] | "x" H+ | O+);
|
|||
"*" { RET(MULTIPLY); }
|
||||
"/" { RET(DIVIDE); }
|
||||
"(" { RET(LPAREN); }
|
||||
"}" { RET(RPAREN); }
|
||||
")" { RET(RPAREN); }
|
||||
"," { RET(COMMA); }
|
||||
"{" { RET(LBRACE); }
|
||||
"}" { RET(RBRACE); }
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef __WIN32__
|
||||
# if defined(_WIN32) || defined(WIN32)
|
||||
|
@ -22,6 +23,12 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __WIN32__
|
||||
extern int access();
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* #define PRIVATE static */
|
||||
#define PRIVATE
|
||||
|
||||
|
@ -31,19 +38,11 @@
|
|||
#define MAXRHS 1000
|
||||
#endif
|
||||
|
||||
void *msort(void *list, void *next, int (*cmp)());
|
||||
static void *msort(void *list, void *next, int (*cmp)());
|
||||
|
||||
/******** From the file "action.h" *************************************/
|
||||
struct action *Action_new();
|
||||
struct action *Action_sort();
|
||||
|
||||
/********* From the file "assert.h" ************************************/
|
||||
void myassert();
|
||||
#ifndef NDEBUG
|
||||
# define assert(X) if(!(X))myassert(__FILE__,__LINE__)
|
||||
#else
|
||||
# define assert(X)
|
||||
#endif
|
||||
static struct action *Action_new(void);
|
||||
static struct action *Action_sort(struct action *);
|
||||
|
||||
/********** From the file "build.h" ************************************/
|
||||
void FindRulePrecedences();
|
||||
|
@ -114,7 +113,7 @@ int SetUnion(/* char *A,char *B */); /* A <- A U B, thru element N */
|
|||
** Principal data structures for the LEMON parser generator.
|
||||
*/
|
||||
|
||||
typedef enum {B_FALSE=0, B_TRUE} Boolean;
|
||||
typedef enum {LEMON_FALSE=0, LEMON_TRUE} Boolean;
|
||||
|
||||
/* Symbols (terminals and nonterminals) of the grammar are stored
|
||||
** in the following: */
|
||||
|
@ -137,6 +136,7 @@ struct symbol {
|
|||
} assoc; /* Associativity if predecence is defined */
|
||||
char *firstset; /* First-set for all rules of this symbol */
|
||||
Boolean lambda; /* True if NT and can generate an empty string */
|
||||
int useCnt; /* Number of times used */
|
||||
char *destructor; /* Code which executes whenever this symbol is
|
||||
** popped from the stack during error processing */
|
||||
int destructorln; /* Line number of destructor code */
|
||||
|
@ -155,6 +155,7 @@ struct symbol {
|
|||
struct rule {
|
||||
struct symbol *lhs; /* Left-hand side of the rule */
|
||||
char *lhsalias; /* Alias for the LHS (NULL if none) */
|
||||
int lhsStart; /* True if left-hand side is the start symbol */
|
||||
int ruleline; /* Line number for the rule */
|
||||
int nrhs; /* Number of RHS symbols */
|
||||
struct symbol **rhs; /* The RHS symbols */
|
||||
|
@ -196,7 +197,9 @@ struct action {
|
|||
ACCEPT,
|
||||
REDUCE,
|
||||
ERROR,
|
||||
CONFLICT, /* Was a reduce, but part of a conflict */
|
||||
SSCONFLICT, /* A shift/shift conflict */
|
||||
SRCONFLICT, /* Was a reduce, but part of a conflict */
|
||||
RRCONFLICT, /* Was a reduce, but part of a conflict */
|
||||
SH_RESOLVED, /* Was a shift. Precedence resolved conflict */
|
||||
RD_RESOLVED, /* Was reduce. Precedence resolved conflict */
|
||||
NOT_USED /* Deleted by compression */
|
||||
|
@ -335,14 +338,14 @@ void Configtable_clear(/* int(*)(struct config *) */);
|
|||
*/
|
||||
|
||||
/* Allocate a new parser action */
|
||||
struct action *Action_new(){
|
||||
static struct action *Action_new(void){
|
||||
static struct action *freelist = 0;
|
||||
struct action *new;
|
||||
|
||||
if( freelist==0 ){
|
||||
int i;
|
||||
int amt = 100;
|
||||
freelist = (struct action *)malloc( sizeof(struct action)*amt );
|
||||
freelist = (struct action *)calloc(amt, sizeof(struct action));
|
||||
if( freelist==0 ){
|
||||
fprintf(stderr,"Unable to allocate memory for a new parser action.");
|
||||
exit(1);
|
||||
|
@ -355,23 +358,27 @@ struct action *Action_new(){
|
|||
return new;
|
||||
}
|
||||
|
||||
/* Compare two actions */
|
||||
/* Compare two actions for sorting purposes. Return negative, zero, or
|
||||
** positive if the first action is less than, equal to, or greater than
|
||||
** the first
|
||||
*/
|
||||
static int actioncmp(ap1,ap2)
|
||||
struct action *ap1;
|
||||
struct action *ap2;
|
||||
{
|
||||
int rc;
|
||||
rc = ap1->sp->index - ap2->sp->index;
|
||||
if( rc==0 ) rc = (int)ap1->type - (int)ap2->type;
|
||||
if( rc==0 ){
|
||||
rc = (int)ap1->type - (int)ap2->type;
|
||||
}
|
||||
if( rc==0 && ap1->type==REDUCE ){
|
||||
rc = ap1->x.rp->index - ap2->x.rp->index;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Sort parser actions */
|
||||
struct action *Action_sort(ap)
|
||||
struct action *ap;
|
||||
static struct action *Action_sort(struct action *ap)
|
||||
{
|
||||
ap = (struct action *)msort(ap,&ap->next,actioncmp);
|
||||
return ap;
|
||||
|
@ -438,7 +445,7 @@ void acttab_free(acttab *p){
|
|||
|
||||
/* Allocate a new acttab structure */
|
||||
acttab *acttab_alloc(void){
|
||||
acttab *p = malloc( sizeof(*p) );
|
||||
acttab *p = calloc( 1, sizeof(*p) );
|
||||
if( p==0 ){
|
||||
fprintf(stderr,"Unable to allocate memory for a new acttab.");
|
||||
exit(1);
|
||||
|
@ -559,17 +566,6 @@ int acttab_insert(acttab *p){
|
|||
return i - p->mnLookahead;
|
||||
}
|
||||
|
||||
/********************** From the file "assert.c" ****************************/
|
||||
/*
|
||||
** A more efficient way of handling assertions.
|
||||
*/
|
||||
void myassert(file,line)
|
||||
char *file;
|
||||
int line;
|
||||
{
|
||||
fprintf(stderr,"Assertion failed on line %d of file \"%s\"\n",line,file);
|
||||
exit(1);
|
||||
}
|
||||
/********************** From the file "build.c" *****************************/
|
||||
/*
|
||||
** Routines to construction the finite state machine for the LEMON
|
||||
|
@ -623,7 +619,7 @@ struct lemon *lemp;
|
|||
int progress;
|
||||
|
||||
for(i=0; i<lemp->nsymbol; i++){
|
||||
lemp->symbols[i]->lambda = B_FALSE;
|
||||
lemp->symbols[i]->lambda = LEMON_FALSE;
|
||||
}
|
||||
for(i=lemp->nterminal; i<lemp->nsymbol; i++){
|
||||
lemp->symbols[i]->firstset = SetNew();
|
||||
|
@ -636,10 +632,10 @@ struct lemon *lemp;
|
|||
if( rp->lhs->lambda ) continue;
|
||||
for(i=0; i<rp->nrhs; i++){
|
||||
struct symbol *sp = rp->rhs[i];
|
||||
if( sp->type!=TERMINAL || sp->lambda==B_FALSE ) break;
|
||||
if( sp->type!=TERMINAL || sp->lambda==LEMON_FALSE ) break;
|
||||
}
|
||||
if( i==rp->nrhs ){
|
||||
rp->lhs->lambda = B_TRUE;
|
||||
rp->lhs->lambda = LEMON_TRUE;
|
||||
progress = 1;
|
||||
}
|
||||
}
|
||||
|
@ -662,10 +658,10 @@ struct lemon *lemp;
|
|||
}
|
||||
break;
|
||||
}else if( s1==s2 ){
|
||||
if( s1->lambda==B_FALSE ) break;
|
||||
if( s1->lambda==LEMON_FALSE ) break;
|
||||
}else{
|
||||
progress += SetUnion(s1->firstset,s2->firstset);
|
||||
if( s2->lambda==B_FALSE ) break;
|
||||
if( s2->lambda==LEMON_FALSE ) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -722,6 +718,7 @@ does not work properly.",sp->name);
|
|||
** left-hand side */
|
||||
for(rp=sp->rule; rp; rp=rp->nextlhs){
|
||||
struct config *newcfp;
|
||||
rp->lhsStart = 1;
|
||||
newcfp = Configlist_addbasis(rp,0);
|
||||
SetAdd(newcfp->fws,0);
|
||||
}
|
||||
|
@ -973,7 +970,7 @@ struct lemon *lemp;
|
|||
struct action *ap, *nap;
|
||||
struct state *stp;
|
||||
stp = lemp->sorted[i];
|
||||
assert( stp->ap );
|
||||
/* assert( stp->ap ); */
|
||||
stp->ap = Action_sort(stp->ap);
|
||||
for(ap=stp->ap; ap && ap->next; ap=ap->next){
|
||||
for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){
|
||||
|
@ -985,11 +982,11 @@ struct lemon *lemp;
|
|||
}
|
||||
|
||||
/* Report an error for each rule that can never be reduced. */
|
||||
for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = B_FALSE;
|
||||
for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = LEMON_FALSE;
|
||||
for(i=0; i<lemp->nstate; i++){
|
||||
struct action *ap;
|
||||
for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
|
||||
if( ap->type==REDUCE ) ap->x.rp->canReduce = B_TRUE;
|
||||
if( ap->type==REDUCE ) ap->x.rp->canReduce = LEMON_TRUE;
|
||||
}
|
||||
}
|
||||
for(rp=lemp->rule; rp; rp=rp->next){
|
||||
|
@ -1021,7 +1018,7 @@ struct symbol *errsym; /* The error symbol (if defined. NULL otherwise) */
|
|||
int errcnt = 0;
|
||||
assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */
|
||||
if( apx->type==SHIFT && apy->type==SHIFT ){
|
||||
apy->type = CONFLICT;
|
||||
apy->type = SSCONFLICT;
|
||||
errcnt++;
|
||||
}
|
||||
if( apx->type==SHIFT && apy->type==REDUCE ){
|
||||
|
@ -1029,7 +1026,7 @@ struct symbol *errsym; /* The error symbol (if defined. NULL otherwise) */
|
|||
spy = apy->x.rp->precsym;
|
||||
if( spy==0 || spx->prec<0 || spy->prec<0 ){
|
||||
/* Not enough precedence information. */
|
||||
apy->type = CONFLICT;
|
||||
apy->type = SRCONFLICT;
|
||||
errcnt++;
|
||||
}else if( spx->prec>spy->prec ){ /* Lower precedence wins */
|
||||
apy->type = RD_RESOLVED;
|
||||
|
@ -1041,7 +1038,7 @@ struct symbol *errsym; /* The error symbol (if defined. NULL otherwise) */
|
|||
apx->type = SH_RESOLVED;
|
||||
}else{
|
||||
assert( spx->prec==spy->prec && spx->assoc==NONE );
|
||||
apy->type = CONFLICT;
|
||||
apy->type = SRCONFLICT;
|
||||
errcnt++;
|
||||
}
|
||||
}else if( apx->type==REDUCE && apy->type==REDUCE ){
|
||||
|
@ -1049,7 +1046,7 @@ struct symbol *errsym; /* The error symbol (if defined. NULL otherwise) */
|
|||
spy = apy->x.rp->precsym;
|
||||
if( spx==0 || spy==0 || spx->prec<0 ||
|
||||
spy->prec<0 || spx->prec==spy->prec ){
|
||||
apy->type = CONFLICT;
|
||||
apy->type = RRCONFLICT;
|
||||
errcnt++;
|
||||
}else if( spx->prec>spy->prec ){
|
||||
apy->type = RD_RESOLVED;
|
||||
|
@ -1060,10 +1057,14 @@ struct symbol *errsym; /* The error symbol (if defined. NULL otherwise) */
|
|||
assert(
|
||||
apx->type==SH_RESOLVED ||
|
||||
apx->type==RD_RESOLVED ||
|
||||
apx->type==CONFLICT ||
|
||||
apx->type==SSCONFLICT ||
|
||||
apx->type==SRCONFLICT ||
|
||||
apx->type==RRCONFLICT ||
|
||||
apy->type==SH_RESOLVED ||
|
||||
apy->type==RD_RESOLVED ||
|
||||
apy->type==CONFLICT
|
||||
apy->type==SSCONFLICT ||
|
||||
apy->type==SRCONFLICT ||
|
||||
apy->type==RRCONFLICT
|
||||
);
|
||||
/* The REDUCE/SHIFT case cannot happen because SHIFTs come before
|
||||
** REDUCEs on the list. If we reach this point it must be because
|
||||
|
@ -1089,7 +1090,7 @@ PRIVATE struct config *newconfig(){
|
|||
if( freelist==0 ){
|
||||
int i;
|
||||
int amt = 3;
|
||||
freelist = (struct config *)malloc( sizeof(struct config)*amt );
|
||||
freelist = (struct config *)calloc( amt, sizeof(struct config) );
|
||||
if( freelist==0 ){
|
||||
fprintf(stderr,"Unable to allocate memory for a new configuration.");
|
||||
exit(1);
|
||||
|
@ -1223,7 +1224,7 @@ struct lemon *lemp;
|
|||
break;
|
||||
}else{
|
||||
SetUnion(newcfp->fws,xsp->firstset);
|
||||
if( xsp->lambda==B_FALSE ) break;
|
||||
if( xsp->lambda==LEMON_FALSE ) break;
|
||||
}
|
||||
}
|
||||
if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
|
||||
|
@ -1452,6 +1453,7 @@ char **argv;
|
|||
lem.basisflag = basisflag;
|
||||
Symbol_new("$");
|
||||
lem.errsym = Symbol_new("error");
|
||||
lem.errsym->useCnt = 0;
|
||||
|
||||
/* Parse the input file */
|
||||
Parse(&lem);
|
||||
|
@ -1477,7 +1479,7 @@ char **argv;
|
|||
Reprint(&lem);
|
||||
}else{
|
||||
/* Initialize the size for all follow and first sets */
|
||||
SetSize(lem.nterminal);
|
||||
SetSize(lem.nterminal+1);
|
||||
|
||||
/* Find the precedence for every production rule (that has one) */
|
||||
FindRulePrecedences(&lem);
|
||||
|
@ -1623,7 +1625,7 @@ static void *merge(void *a,void *b,int (*cmp)(),size_t offset)
|
|||
** The "next" pointers for elements in list are changed.
|
||||
*/
|
||||
#define LISTSIZE 30
|
||||
void *msort(void *list,void *next,int (*cmp)())
|
||||
static void *msort(void *list,void *next,int (*cmp)())
|
||||
{
|
||||
size_t offset;
|
||||
char *ep;
|
||||
|
@ -2108,8 +2110,8 @@ to follow the previous rule.");
|
|||
case IN_RHS:
|
||||
if( x[0]=='.' ){
|
||||
struct rule *rp;
|
||||
rp = (struct rule *)malloc( sizeof(struct rule) +
|
||||
sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
|
||||
rp = (struct rule *)calloc( sizeof(struct rule) +
|
||||
sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1);
|
||||
if( rp==0 ){
|
||||
ErrorMsg(psp->filename,psp->tokenlineno,
|
||||
"Can't allocate enough memory for this rule.");
|
||||
|
@ -2145,7 +2147,7 @@ to follow the previous rule.");
|
|||
}else if( isalpha(x[0]) ){
|
||||
if( psp->nrhs>=MAXRHS ){
|
||||
ErrorMsg(psp->filename,psp->tokenlineno,
|
||||
"Too many symbols on RHS or rule beginning at \"%s\".",
|
||||
"Too many symbols on RHS of rule beginning at \"%s\".",
|
||||
x);
|
||||
psp->errorcnt++;
|
||||
psp->state = RESYNC_AFTER_RULE_ERROR;
|
||||
|
@ -2158,11 +2160,10 @@ to follow the previous rule.");
|
|||
struct symbol *msp = psp->rhs[psp->nrhs-1];
|
||||
if( msp->type!=MULTITERMINAL ){
|
||||
struct symbol *origsp = msp;
|
||||
msp = malloc(sizeof(*msp));
|
||||
memset(msp, 0, sizeof(*msp));
|
||||
msp = calloc(1,sizeof(*msp));
|
||||
msp->type = MULTITERMINAL;
|
||||
msp->nsubsym = 1;
|
||||
msp->subsym = malloc(sizeof(struct symbol*));
|
||||
msp->subsym = calloc(1,sizeof(struct symbol*));
|
||||
msp->subsym[0] = origsp;
|
||||
msp->name = origsp->name;
|
||||
psp->rhs[psp->nrhs-1] = msp;
|
||||
|
@ -2407,7 +2408,7 @@ to follow the previous rule.");
|
|||
static void preprocess_input(char *z){
|
||||
int i, j, k, n;
|
||||
int exclude = 0;
|
||||
int start = 1;
|
||||
int start = 0;
|
||||
int lineno = 1;
|
||||
int start_lineno = 1;
|
||||
for(i=0; z[i]; i++){
|
||||
|
@ -2484,7 +2485,7 @@ struct lemon *gp;
|
|||
char *cp, *nextcp;
|
||||
int startline = 0;
|
||||
|
||||
memset(&ps, 0, sizeof ps);
|
||||
memset(&ps, '\0', sizeof(ps));
|
||||
ps.gp = gp;
|
||||
ps.filename = gp->filename;
|
||||
ps.errorcnt = 0;
|
||||
|
@ -2633,7 +2634,7 @@ struct plink *Plink_new(){
|
|||
if( plink_freelist==0 ){
|
||||
int i;
|
||||
int amt = 100;
|
||||
plink_freelist = (struct plink *)malloc( sizeof(struct plink)*amt );
|
||||
plink_freelist = (struct plink *)calloc( amt, sizeof(struct plink) );
|
||||
if( plink_freelist==0 ){
|
||||
fprintf(stderr,
|
||||
"Unable to allocate memory for a new follow-set propagation link.\n");
|
||||
|
@ -2859,10 +2860,15 @@ int PrintAction(struct action *ap, FILE *fp, int indent){
|
|||
case ERROR:
|
||||
fprintf(fp,"%*s error",indent,ap->sp->name);
|
||||
break;
|
||||
case CONFLICT:
|
||||
case SRCONFLICT:
|
||||
case RRCONFLICT:
|
||||
fprintf(fp,"%*s reduce %-3d ** Parsing conflict **",
|
||||
indent,ap->sp->name,ap->x.rp->index);
|
||||
break;
|
||||
case SSCONFLICT:
|
||||
fprintf(fp,"%*s shift %d ** Parsing conflict **",
|
||||
indent,ap->sp->name,ap->x.stp->statenum);
|
||||
break;
|
||||
case SH_RESOLVED:
|
||||
case RD_RESOLVED:
|
||||
case NOT_USED:
|
||||
|
@ -2884,7 +2890,6 @@ struct lemon *lemp;
|
|||
|
||||
fp = file_open(lemp,".out","wb");
|
||||
if( fp==0 ) return;
|
||||
fprintf(fp," \b");
|
||||
for(i=0; i<lemp->nstate; i++){
|
||||
stp = lemp->sorted[i];
|
||||
fprintf(fp,"State %d:\n",stp->statenum);
|
||||
|
@ -2914,6 +2919,27 @@ struct lemon *lemp;
|
|||
}
|
||||
fprintf(fp,"\n");
|
||||
}
|
||||
fprintf(fp, "----------------------------------------------------\n");
|
||||
fprintf(fp, "Symbols:\n");
|
||||
for(i=0; i<lemp->nsymbol; i++){
|
||||
int j;
|
||||
struct symbol *sp;
|
||||
|
||||
sp = lemp->symbols[i];
|
||||
fprintf(fp, " %3d: %s", i, sp->name);
|
||||
if( sp->type==NONTERMINAL ){
|
||||
fprintf(fp, ":");
|
||||
if( sp->lambda ){
|
||||
fprintf(fp, " <lambda>");
|
||||
}
|
||||
for(j=0; j<lemp->nterminal; j++){
|
||||
if( sp->firstset && SetFind(sp->firstset, j) ){
|
||||
fprintf(fp, " %s", lemp->symbols[j]->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
@ -2928,7 +2954,6 @@ int modemask;
|
|||
char *pathlist;
|
||||
char *path,*cp;
|
||||
char c;
|
||||
extern int access();
|
||||
|
||||
#ifdef __WIN32__
|
||||
for (cp = argv0 + strlen(argv0); cp-- > argv0; )
|
||||
|
@ -3229,8 +3254,13 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
|
|||
for(i=0; i<rp->nrhs; i++) used[i] = 0;
|
||||
lhsused = 0;
|
||||
|
||||
if( rp->code==0 ){
|
||||
rp->code = "\n";
|
||||
rp->line = rp->ruleline;
|
||||
}
|
||||
|
||||
append_str(0,0,0,0,0);
|
||||
for(cp=(rp->code?rp->code:""); *cp; cp++){
|
||||
for(cp=rp->code; *cp; cp++){
|
||||
if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
|
||||
char saved;
|
||||
for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
|
||||
|
@ -3351,8 +3381,7 @@ int mhflag; /* True if generating makeheaders output */
|
|||
|
||||
/* Allocate and initialize types[] and allocate stddt[] */
|
||||
arraysize = lemp->nsymbol * 2;
|
||||
types = (char**)malloc( arraysize * sizeof(char*) );
|
||||
for(i=0; i<arraysize; i++) types[i] = 0;
|
||||
types = (char**)calloc( arraysize, sizeof(char*) );
|
||||
maxdtlength = 0;
|
||||
if( lemp->vartype ){
|
||||
maxdtlength = (int)strlen(lemp->vartype);
|
||||
|
@ -3432,7 +3461,9 @@ int mhflag; /* True if generating makeheaders output */
|
|||
fprintf(out," %s yy%d;\n",types[i],i+1); lineno++;
|
||||
free(types[i]);
|
||||
}
|
||||
fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
|
||||
if( lemp->errsym->useCnt ){
|
||||
fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
|
||||
}
|
||||
free(stddt);
|
||||
free(types);
|
||||
fprintf(out,"} YYMINORTYPE;\n"); lineno++;
|
||||
|
@ -3482,6 +3513,25 @@ static int axset_compare(const void *a, const void *b){
|
|||
return p2->nAction - p1->nAction;
|
||||
}
|
||||
|
||||
/*
|
||||
** Write text on "out" that describes the rule "rp".
|
||||
*/
|
||||
static void writeRuleText(FILE *out, struct rule *rp){
|
||||
int j;
|
||||
fprintf(out,"%s ::=", rp->lhs->name);
|
||||
for(j=0; j<rp->nrhs; j++){
|
||||
struct symbol *sp = rp->rhs[j];
|
||||
fprintf(out," %s", sp->name);
|
||||
if( sp->type==MULTITERMINAL ){
|
||||
int k;
|
||||
for(k=1; k<sp->nsubsym; k++){
|
||||
fprintf(out,"|%s",sp->subsym[k]->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Generate C source code for the parser */
|
||||
void ReportTable(lemp, mhflag)
|
||||
struct lemon *lemp;
|
||||
|
@ -3544,18 +3594,13 @@ int mhflag; /* Output in makeheaders format if true */
|
|||
lemp->wildcard->index); lineno++;
|
||||
}
|
||||
print_stack_union(out,lemp,&lineno,mhflag);
|
||||
fprintf(out, "#ifndef YYSTACKDEPTH\n"); lineno++;
|
||||
if( lemp->stacksize ){
|
||||
if( atoi(lemp->stacksize)<=0 ){
|
||||
ErrorMsg(lemp->filename,0,
|
||||
"Illegal stack size: [%s]. The stack size should be an integer constant.",
|
||||
lemp->stacksize);
|
||||
lemp->errorcnt++;
|
||||
lemp->stacksize = "100";
|
||||
}
|
||||
fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize); lineno++;
|
||||
}else{
|
||||
fprintf(out,"#define YYSTACKDEPTH 100\n"); lineno++;
|
||||
}
|
||||
fprintf(out, "#endif\n"); lineno++;
|
||||
if( mhflag ){
|
||||
fprintf(out,"#if INTERFACE\n"); lineno++;
|
||||
}
|
||||
|
@ -3582,8 +3627,10 @@ int mhflag; /* Output in makeheaders format if true */
|
|||
}
|
||||
fprintf(out,"#define YYNSTATE %d\n",lemp->nstate); lineno++;
|
||||
fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
|
||||
fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
|
||||
fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
|
||||
if( lemp->errsym->useCnt ){
|
||||
fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
|
||||
fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
|
||||
}
|
||||
if( lemp->has_fallback ){
|
||||
fprintf(out,"#define YYFALLBACK 1\n"); lineno++;
|
||||
}
|
||||
|
@ -3602,7 +3649,7 @@ int mhflag; /* Output in makeheaders format if true */
|
|||
*/
|
||||
|
||||
/* Compute the actions on all states and count them up */
|
||||
ax = malloc( sizeof(ax[0])*lemp->nstate*2 );
|
||||
ax = calloc(lemp->nstate*2 , sizeof(ax[0]));
|
||||
if( ax==0 ){
|
||||
fprintf(stderr,"malloc failed\n");
|
||||
exit(1);
|
||||
|
@ -3782,17 +3829,8 @@ int mhflag; /* Output in makeheaders format if true */
|
|||
*/
|
||||
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
|
||||
assert( rp->index==i );
|
||||
fprintf(out," /* %3d */ \"%s ::=", i, rp->lhs->name);
|
||||
for(j=0; j<rp->nrhs; j++){
|
||||
struct symbol *sp = rp->rhs[j];
|
||||
fprintf(out," %s", sp->name);
|
||||
if( sp->type==MULTITERMINAL ){
|
||||
int k;
|
||||
for(k=1; k<sp->nsubsym; k++){
|
||||
fprintf(out,"|%s",sp->subsym[k]->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(out," /* %3d */ \"", i);
|
||||
writeRuleText(out, rp);
|
||||
fprintf(out,"\",\n"); lineno++;
|
||||
}
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
@ -3805,7 +3843,8 @@ int mhflag; /* Output in makeheaders format if true */
|
|||
for(i=0; i<lemp->nsymbol; i++){
|
||||
struct symbol *sp = lemp->symbols[i];
|
||||
if( sp==0 || sp->type!=TERMINAL ) continue;
|
||||
fprintf(out," case %d:\n",sp->index); lineno++;
|
||||
fprintf(out," case %d: /* %s */\n",
|
||||
sp->index, sp->name); lineno++;
|
||||
}
|
||||
for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++);
|
||||
if( i<lemp->nsymbol ){
|
||||
|
@ -3819,7 +3858,8 @@ int mhflag; /* Output in makeheaders format if true */
|
|||
struct symbol *sp = lemp->symbols[i];
|
||||
if( sp==0 || sp->type==TERMINAL ||
|
||||
sp->index<=0 || sp->destructor!=0 ) continue;
|
||||
fprintf(out," case %d:\n",sp->index); lineno++;
|
||||
fprintf(out," case %d: /* %s */\n",
|
||||
sp->index, sp->name); lineno++;
|
||||
dflt_sp = sp;
|
||||
}
|
||||
if( dflt_sp!=0 ){
|
||||
|
@ -3830,7 +3870,8 @@ int mhflag; /* Output in makeheaders format if true */
|
|||
for(i=0; i<lemp->nsymbol; i++){
|
||||
struct symbol *sp = lemp->symbols[i];
|
||||
if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
|
||||
fprintf(out," case %d:\n",sp->index); lineno++;
|
||||
fprintf(out," case %d: /* %s */\n",
|
||||
sp->index, sp->name); lineno++;
|
||||
|
||||
/* Combine duplicate destructors into a single case */
|
||||
for(j=i+1; j<lemp->nsymbol; j++){
|
||||
|
@ -3838,7 +3879,8 @@ int mhflag; /* Output in makeheaders format if true */
|
|||
if( sp2 && sp2->type!=TERMINAL && sp2->destructor
|
||||
&& sp2->dtnum==sp->dtnum
|
||||
&& strcmp(sp->destructor,sp2->destructor)==0 ){
|
||||
fprintf(out," case %d:\n",sp2->index); lineno++;
|
||||
fprintf(out," case %d: /* %s */\n",
|
||||
sp2->index, sp2->name); lineno++;
|
||||
sp2->destructor = 0;
|
||||
}
|
||||
}
|
||||
|
@ -3869,10 +3911,14 @@ int mhflag; /* Output in makeheaders format if true */
|
|||
for(rp=lemp->rule; rp; rp=rp->next){
|
||||
struct rule *rp2;
|
||||
if( rp->code==0 ) continue;
|
||||
fprintf(out," case %d:\n",rp->index); lineno++;
|
||||
fprintf(out," case %d: /* ",rp->index);
|
||||
writeRuleText(out, rp);
|
||||
fprintf(out, " */\n"); lineno++;
|
||||
for(rp2=rp->next; rp2; rp2=rp2->next){
|
||||
if( rp2->code==rp->code ){
|
||||
fprintf(out," case %d:\n",rp2->index); lineno++;
|
||||
fprintf(out," case %d: /*",rp2->index);
|
||||
writeRuleText(out, rp2);
|
||||
fprintf(out," */\n"); lineno++;
|
||||
rp2->code = 0;
|
||||
}
|
||||
}
|
||||
|
@ -3964,6 +4010,7 @@ struct lemon *lemp;
|
|||
}
|
||||
if( ap->type!=REDUCE ) continue;
|
||||
rp = ap->x.rp;
|
||||
if( rp->lhsStart ) continue;
|
||||
if( rp==rbest ) continue;
|
||||
n = 1;
|
||||
for(ap2=ap->next; ap2; ap2=ap2->next){
|
||||
|
@ -4072,13 +4119,11 @@ int n;
|
|||
/* Allocate a new set */
|
||||
char *SetNew(){
|
||||
char *s;
|
||||
int i;
|
||||
s = (char*)malloc( size );
|
||||
s = (char*)calloc( size, 1);
|
||||
if( s==0 ){
|
||||
extern void memory_error();
|
||||
memory_error();
|
||||
}
|
||||
for(i=0; i<size; i++) s[i] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -4096,6 +4141,7 @@ char *s;
|
|||
int e;
|
||||
{
|
||||
int rv;
|
||||
assert( e>=0 && e<size );
|
||||
rv = s[e];
|
||||
s[e] = 1;
|
||||
return !rv;
|
||||
|
@ -4285,7 +4331,7 @@ char *x;
|
|||
|
||||
sp = Symbol_find(x);
|
||||
if( sp==0 ){
|
||||
sp = (struct symbol *)malloc( sizeof(struct symbol) );
|
||||
sp = (struct symbol *)calloc(1, sizeof(struct symbol) );
|
||||
MemoryCheck(sp);
|
||||
sp->name = Strsafe(x);
|
||||
sp->type = isupper(*x) ? TERMINAL : NONTERMINAL;
|
||||
|
@ -4294,11 +4340,13 @@ char *x;
|
|||
sp->prec = -1;
|
||||
sp->assoc = UNK;
|
||||
sp->firstset = 0;
|
||||
sp->lambda = B_FALSE;
|
||||
sp->lambda = LEMON_FALSE;
|
||||
sp->destructor = 0;
|
||||
sp->datatype = 0;
|
||||
sp->useCnt = 0;
|
||||
Symbol_insert(sp,sp->name);
|
||||
}
|
||||
sp->useCnt++;
|
||||
return sp;
|
||||
}
|
||||
|
||||
|
@ -4468,7 +4516,7 @@ struct symbol **Symbol_arrayof()
|
|||
int i,size;
|
||||
if( x2a==0 ) return 0;
|
||||
size = x2a->count;
|
||||
array = (struct symbol **)malloc( sizeof(struct symbol *)*size );
|
||||
array = (struct symbol **)calloc(size, sizeof(struct symbol *));
|
||||
if( array ){
|
||||
for(i=0; i<size; i++) array[i] = x2a->tbl[i].data;
|
||||
}
|
||||
|
@ -4519,7 +4567,7 @@ struct config *a;
|
|||
struct state *State_new()
|
||||
{
|
||||
struct state *new;
|
||||
new = (struct state *)malloc( sizeof(struct state) );
|
||||
new = (struct state *)calloc(1, sizeof(struct state) );
|
||||
MemoryCheck(new);
|
||||
return new;
|
||||
}
|
||||
|
|
1555
tools/lemon/lempar.c
1555
tools/lemon/lempar.c
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,57 @@
|
|||
Version 0.12.3 (2007-08-24)
|
||||
---------------------------
|
||||
- Fixed issue with some compilers.
|
||||
- Fixed #1776177 Build on AIX.
|
||||
- Fixed #1743180 fwrite with 0 length crashes on OS X.
|
||||
|
||||
Version 0.12.2 (2007-06-26)
|
||||
---------------------------
|
||||
- Fixed #1743180 fwrite with 0 length crashes on OS X.
|
||||
|
||||
Version 0.12.1 (2007-05-23)
|
||||
---------------------------
|
||||
- Fixed #1711240 problem with '"' and 7F on EBCDIC plattforms.
|
||||
|
||||
Version 0.12.0 (2007-05-01)
|
||||
---------------------------
|
||||
- Re-release of 0.11.3 as new stable branch.
|
||||
- Fixed issue with short form of switches and parameter if not first switch.
|
||||
- Fixed #1708378 segfault in actions.cc.
|
||||
|
||||
Version 0.11.3 (2007-04-01)
|
||||
---------------------------
|
||||
- Added support for underscores in named definitions.
|
||||
- Added new option --no-generation-date.
|
||||
- Fixed issue with long form of switches.
|
||||
|
||||
Version 0.11.2 (2007-03-01)
|
||||
---------------------------
|
||||
- Added inplace configuration 're2c:yyfill:parameter'.
|
||||
- Added inplace configuration 're2c:yych:conversion'.
|
||||
- Fixed -u switch code generation.
|
||||
- Added ability to avoid defines and overwrite variable and label names.
|
||||
|
||||
Version 0.11.1 (2007-02-20)
|
||||
---------------------------
|
||||
- Applied #1647875 add const to yybm vector.
|
||||
|
||||
Version 0.11.0 (2007-01-01)
|
||||
---------------------------
|
||||
- Added -u switch to support unicode.
|
||||
|
||||
Version 0.10.8 (2007-04-01)
|
||||
---------------------------
|
||||
- Fixed issue with long form of switches.
|
||||
|
||||
Version 0.10.7 (2007-02-20)
|
||||
---------------------------
|
||||
- Applied #1647875 add const to yybm vector.
|
||||
|
||||
Version 0.10.6 (2006-08-05)
|
||||
---------------------------
|
||||
- Fixed #1529351 Segv bug on unterminated code blocks.
|
||||
- Fixed #1528269 Invalid code generation.
|
||||
|
||||
Version 0.10.5 (2006-06-11)
|
||||
---------------------------
|
||||
- Fixed long form of -1 switch to --single-pass as noted in man page and help.
|
||||
|
@ -20,7 +74,7 @@ Version 0.10.2 (2006-05-01)
|
|||
- Fixed -i switch.
|
||||
- Added configuration 'yyfill:enable' to allow suppression of YYFILL() blocks.
|
||||
- Added tutorial like lessons to re2c.
|
||||
- Added /*!ignore!re2c */ to support documenting of re2c source.
|
||||
- Added /*!ignore:re2c */ to support documenting of re2c source.
|
||||
- Fixed issue with multiline re2c comments (/*!max:re2c ... */ and alike).
|
||||
- Fixed generation of YYDEBUG() when using -d switch.
|
||||
- Added /*!getstate:re2c */ which triggers generation of the YYGETSTATE() block.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
ifeq (Windows_NT,$(OS))
|
||||
WIN=1
|
||||
WINCMD=1
|
||||
endif
|
||||
ifeq (msys,$(OSTYPE))
|
||||
WIN=1
|
||||
WINCMD=0
|
||||
endif
|
||||
ifeq (Windows_NT,$(OS))
|
||||
WIN=1
|
||||
WINCMD=1
|
||||
endif
|
||||
ifeq (msys,$(OSTYPE))
|
||||
WIN=1
|
||||
WINCMD=0
|
||||
endif
|
||||
|
||||
ifeq (1,$(WIN))
|
||||
EXE = re2c.exe
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
re2c Version 0.10.5
|
||||
re2c Version 0.12.3
|
||||
------------------
|
||||
|
||||
Originally written by Peter Bumbulis (peter@csg.uwaterloo.ca)
|
||||
|
@ -17,7 +17,7 @@ platforms in 32 bit and 64 bit mode:
|
|||
- GCC 3.3 ... 4.1
|
||||
- Microsoft VC 7, 7.1, 8
|
||||
- Intel 9.0
|
||||
- Sun C++ 5.8 (CXXFLAGS='-compat5 -library=stlport4')
|
||||
- Sun C++ 5.8 (CXXFLAGS='-library=stlport4')
|
||||
- MIPSpro Compilers: Version 7.4.4m
|
||||
|
||||
GCC 2.x and Microsoft VC 6 are not capable of compiling re2c.
|
||||
|
@ -41,7 +41,7 @@ re2c) you need the following steps:
|
|||
Or you can create a rpm package and install it by the following commands:
|
||||
./configure
|
||||
make rpm
|
||||
rpm -Uhv <packagedir>/re2c-0.10.5-1.rpm
|
||||
rpm -Uhv <packagedir>/re2c-0.12.3-1.rpm
|
||||
|
||||
If you want to build from CVS then the first thing you should do is
|
||||
regenerating all build files using the following command:
|
||||
|
@ -51,7 +51,7 @@ need to generate RPM packages for cvs builds use these commands:
|
|||
./autogen.sh
|
||||
./configure
|
||||
./makerpm <release>
|
||||
rpm -Uhv <packagedir>/re2c-0.10.5-<release>.rpm
|
||||
rpm -Uhv <packagedir>/re2c-0.12.3-<release>.rpm
|
||||
|
||||
Here <realease> should be a number like 1. And <packagedir> must equal
|
||||
the directory where the makerpm step has written the generated rpm to.
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
|||
/* $Id: basics.h,v 1.6 2005/12/29 14:32:09 helly Exp $ */
|
||||
/* $Id: basics.h 520 2006-05-25 13:31:06Z helly $ */
|
||||
#ifndef _basics_h
|
||||
#define _basics_h
|
||||
|
||||
|
|
3298
tools/re2c/code.cc
3298
tools/re2c/code.cc
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
|||
/* $Id: code.h,v 1.7 2006/01/21 15:51:02 helly Exp $ */
|
||||
/* $Id: code.h 525 2006-05-25 13:32:49Z helly $ */
|
||||
#ifndef _code_h
|
||||
#define _code_h
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: dfa.h,v 1.23 2006/05/14 13:38:26 helly Exp $ */
|
||||
/* $Id: dfa.h 569 2006-06-05 22:14:00Z helly $ */
|
||||
#ifndef _dfa_h
|
||||
#define _dfa_h
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: globals.h,v 1.31 2006/05/14 13:38:26 helly Exp $ */
|
||||
/* $Id: globals.h 713 2007-04-29 15:33:47Z helly $ */
|
||||
#ifndef _globals_h
|
||||
#define _globals_h
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: ins.h,v 1.7 2006/01/03 11:40:38 helly Exp $ */
|
||||
/* $Id: ins.h 535 2006-05-25 13:36:14Z helly $ */
|
||||
#ifndef _ins_h
|
||||
#define _ins_h
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: main.cc,v 1.53 2006/05/14 13:38:26 helly Exp $ */
|
||||
/* $Id: main.cc 691 2007-04-22 15:07:39Z helly $ */
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#elif defined(_WIN32)
|
||||
|
@ -139,7 +139,7 @@ static void usage()
|
|||
" with -f and disables YYMAXFILL generation prior to last\n"
|
||||
" re2c block.\n"
|
||||
"\n"
|
||||
"--no-generation-date Suppress the date output in the generated output so that it\n"
|
||||
"--no-generation-date Suppress date output in the generated output so that it\n"
|
||||
" only shows the re2c version.\n"
|
||||
;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Author: Marcus Boerger <helly@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
/* $Id: mbo_getopt.cc,v 1.5 2006/04/17 19:28:47 helly Exp $ */
|
||||
/* $Id: mbo_getopt.cc 698 2007-04-23 21:06:56Z helly $ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Author: Marcus Boerger <helly@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
/* $Id: mbo_getopt.h,v 1.5 2006/04/17 19:28:47 helly Exp $ */
|
||||
/* $Id: mbo_getopt.h 539 2006-05-25 13:37:38Z helly $ */
|
||||
|
||||
/* Define structure for one recognized option (both single char and long name).
|
||||
* If short_open is '-' this is the last option.
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
#line 1 "./parser.y"
|
||||
|
||||
|
||||
/* $Id: parser.y,v 1.20 2006/04/16 15:15:46 helly Exp $ */
|
||||
/* $Id: parser.y 674 2007-04-16 21:39:11Z helly $ */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: parser.h,v 1.10 2006/01/21 15:51:02 helly Exp $ */
|
||||
/* $Id: parser.h 565 2006-06-05 22:07:13Z helly $ */
|
||||
#ifndef _parser_h
|
||||
#define _parser_h
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
%{
|
||||
|
||||
/* $Id: parser.y,v 1.20 2006/04/16 15:15:46 helly Exp $ */
|
||||
/* $Id: parser.y 674 2007-04-16 21:39:11Z helly $ */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
|
|
898
tools/re2c/re.h
898
tools/re2c/re.h
|
@ -1,16 +1,16 @@
|
|||
/* $Id: re.h,v 1.17 2006/04/09 00:06:33 helly Exp $ */
|
||||
#ifndef _re_h
|
||||
#define _re_h
|
||||
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include "token.h"
|
||||
#include "ins.h"
|
||||
#include "globals.h"
|
||||
|
||||
namespace re2c
|
||||
{
|
||||
|
||||
/* $Id: re.h 775 2007-07-10 19:33:17Z helly $ */
|
||||
#ifndef _re_h
|
||||
#define _re_h
|
||||
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include "token.h"
|
||||
#include "ins.h"
|
||||
#include "globals.h"
|
||||
|
||||
namespace re2c
|
||||
{
|
||||
|
||||
template<class _Ty>
|
||||
class free_list: protected std::set<_Ty>
|
||||
{
|
||||
|
@ -55,436 +55,442 @@ public:
|
|||
protected:
|
||||
bool in_clear;
|
||||
};
|
||||
|
||||
typedef struct extop
|
||||
{
|
||||
char op;
|
||||
int minsize;
|
||||
int maxsize;
|
||||
}
|
||||
|
||||
ExtOp;
|
||||
|
||||
struct CharPtn
|
||||
{
|
||||
uint card;
|
||||
CharPtn *fix;
|
||||
CharPtn *nxt;
|
||||
};
|
||||
|
||||
typedef CharPtn *CharPtr;
|
||||
|
||||
struct CharSet
|
||||
{
|
||||
CharSet();
|
||||
~CharSet();
|
||||
|
||||
CharPtn *fix;
|
||||
CharPtn *freeHead, **freeTail;
|
||||
CharPtr *rep;
|
||||
CharPtn *ptn;
|
||||
};
|
||||
|
||||
class Range
|
||||
{
|
||||
|
||||
public:
|
||||
Range *next;
|
||||
uint lb, ub; // [lb,ub)
|
||||
|
||||
static free_list<Range*> vFreeList;
|
||||
|
||||
public:
|
||||
Range(uint l, uint u) : next(NULL), lb(l), ub(u)
|
||||
{
|
||||
vFreeList.insert(this);
|
||||
}
|
||||
|
||||
Range(Range &r) : next(NULL), lb(r.lb), ub(r.ub)
|
||||
{
|
||||
vFreeList.insert(this);
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream&, const Range&);
|
||||
friend std::ostream& operator<<(std::ostream&, const Range*);
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &o, const Range *r)
|
||||
{
|
||||
return r ? o << *r : o;
|
||||
}
|
||||
|
||||
class RegExp
|
||||
{
|
||||
|
||||
public:
|
||||
uint size;
|
||||
|
||||
static free_list<RegExp*> vFreeList;
|
||||
|
||||
public:
|
||||
RegExp() : size(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~RegExp()
|
||||
{
|
||||
vFreeList.erase(this);
|
||||
}
|
||||
|
||||
virtual const char *typeOf() = 0;
|
||||
RegExp *isA(const char *t)
|
||||
{
|
||||
return typeOf() == t ? this : NULL;
|
||||
}
|
||||
|
||||
virtual void split(CharSet&) = 0;
|
||||
virtual void calcSize(Char*) = 0;
|
||||
virtual uint fixedLength();
|
||||
virtual void compile(Char*, Ins*) = 0;
|
||||
virtual void display(std::ostream&) const = 0;
|
||||
friend std::ostream& operator<<(std::ostream&, const RegExp&);
|
||||
friend std::ostream& operator<<(std::ostream&, const RegExp*);
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &o, const RegExp &re)
|
||||
{
|
||||
re.display(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &o, const RegExp *re)
|
||||
{
|
||||
return o << *re;
|
||||
}
|
||||
|
||||
class NullOp: public RegExp
|
||||
{
|
||||
|
||||
public:
|
||||
static const char *type;
|
||||
|
||||
public:
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
uint fixedLength();
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream &o) const
|
||||
{
|
||||
o << "_";
|
||||
}
|
||||
};
|
||||
|
||||
class MatchOp: public RegExp
|
||||
{
|
||||
|
||||
public:
|
||||
static const char *type;
|
||||
Range *match;
|
||||
|
||||
public:
|
||||
MatchOp(Range *m) : match(m)
|
||||
{
|
||||
}
|
||||
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
uint fixedLength();
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream&) const;
|
||||
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
MatchOp(const MatchOp& oth)
|
||||
: RegExp(oth)
|
||||
, match(oth.match)
|
||||
{
|
||||
}
|
||||
|
||||
MatchOp& operator = (const MatchOp& oth)
|
||||
{
|
||||
new(this) MatchOp(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class RuleOp: public RegExp
|
||||
{
|
||||
public:
|
||||
static const char *type;
|
||||
|
||||
private:
|
||||
RegExp *exp;
|
||||
|
||||
public:
|
||||
RegExp *ctx;
|
||||
Ins *ins;
|
||||
uint accept;
|
||||
Token *code;
|
||||
uint line;
|
||||
|
||||
public:
|
||||
RuleOp(RegExp*, RegExp*, Token*, uint);
|
||||
|
||||
~RuleOp()
|
||||
{
|
||||
delete code;
|
||||
}
|
||||
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream &o) const
|
||||
{
|
||||
o << exp << "/" << ctx << ";";
|
||||
}
|
||||
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
RuleOp(const RuleOp& oth)
|
||||
: RegExp(oth)
|
||||
, exp(oth.exp)
|
||||
, ctx(oth.ctx)
|
||||
, ins(oth.ins)
|
||||
, accept(oth.accept)
|
||||
, code(oth.code)
|
||||
, line(oth.line)
|
||||
{
|
||||
}
|
||||
RuleOp& operator = (const RuleOp& oth)
|
||||
{
|
||||
new(this) RuleOp(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class RuleLine: public line_number
|
||||
{
|
||||
public:
|
||||
|
||||
RuleLine(const RuleOp& _op)
|
||||
: op(_op)
|
||||
{
|
||||
}
|
||||
|
||||
uint get_line() const
|
||||
{
|
||||
return op.code->line;
|
||||
}
|
||||
|
||||
const RuleOp& op;
|
||||
};
|
||||
|
||||
RegExp *mkAlt(RegExp*, RegExp*);
|
||||
|
||||
class AltOp: public RegExp
|
||||
{
|
||||
|
||||
private:
|
||||
RegExp *exp1, *exp2;
|
||||
|
||||
public:
|
||||
static const char *type;
|
||||
|
||||
public:
|
||||
AltOp(RegExp *e1, RegExp *e2)
|
||||
: exp1(e1)
|
||||
, exp2(e2)
|
||||
{
|
||||
}
|
||||
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
uint fixedLength();
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream &o) const
|
||||
{
|
||||
o << exp1 << "|" << exp2;
|
||||
}
|
||||
|
||||
friend RegExp *mkAlt(RegExp*, RegExp*);
|
||||
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
AltOp(const AltOp& oth)
|
||||
: RegExp(oth)
|
||||
, exp1(oth.exp1)
|
||||
, exp2(oth.exp2)
|
||||
{
|
||||
}
|
||||
AltOp& operator = (const AltOp& oth)
|
||||
{
|
||||
new(this) AltOp(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class CatOp: public RegExp
|
||||
{
|
||||
|
||||
private:
|
||||
RegExp *exp1, *exp2;
|
||||
|
||||
public:
|
||||
static const char *type;
|
||||
|
||||
public:
|
||||
CatOp(RegExp *e1, RegExp *e2)
|
||||
: exp1(e1)
|
||||
, exp2(e2)
|
||||
{
|
||||
}
|
||||
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
uint fixedLength();
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream &o) const
|
||||
{
|
||||
o << exp1 << exp2;
|
||||
}
|
||||
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
CatOp(const CatOp& oth)
|
||||
: RegExp(oth)
|
||||
, exp1(oth.exp1)
|
||||
, exp2(oth.exp2)
|
||||
{
|
||||
}
|
||||
CatOp& operator = (const CatOp& oth)
|
||||
{
|
||||
new(this) CatOp(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class CloseOp: public RegExp
|
||||
{
|
||||
|
||||
private:
|
||||
RegExp *exp;
|
||||
|
||||
public:
|
||||
static const char *type;
|
||||
|
||||
public:
|
||||
CloseOp(RegExp *e)
|
||||
: exp(e)
|
||||
{
|
||||
}
|
||||
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream &o) const
|
||||
{
|
||||
o << exp << "+";
|
||||
}
|
||||
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
CloseOp(const CloseOp& oth)
|
||||
: RegExp(oth)
|
||||
, exp(oth.exp)
|
||||
{
|
||||
}
|
||||
CloseOp& operator = (const CloseOp& oth)
|
||||
{
|
||||
new(this) CloseOp(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class CloseVOp: public RegExp
|
||||
{
|
||||
|
||||
private:
|
||||
RegExp *exp;
|
||||
int min;
|
||||
int max;
|
||||
|
||||
public:
|
||||
static const char *type;
|
||||
|
||||
public:
|
||||
CloseVOp(RegExp *e, int lb, int ub)
|
||||
: exp(e)
|
||||
, min(lb)
|
||||
, max(ub)
|
||||
{
|
||||
}
|
||||
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream &o) const
|
||||
{
|
||||
o << exp << "+";
|
||||
}
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
CloseVOp(const CloseVOp& oth)
|
||||
: RegExp(oth)
|
||||
, exp(oth.exp)
|
||||
, min(oth.min)
|
||||
, max(oth.max)
|
||||
{
|
||||
}
|
||||
CloseVOp& operator = (const CloseVOp& oth)
|
||||
{
|
||||
new(this) CloseVOp(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
extern void genCode(std::ostream&, RegExp*);
|
||||
extern void genCode(std::ostream&, uint, RegExp*);
|
||||
extern void genGetState(std::ostream&, uint&, uint);
|
||||
extern RegExp *mkDiff(RegExp*, RegExp*);
|
||||
extern RegExp *mkAlt(RegExp*, RegExp*);
|
||||
|
||||
} // end namespace re2c
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct extop
|
||||
{
|
||||
char op;
|
||||
int minsize;
|
||||
int maxsize;
|
||||
}
|
||||
|
||||
ExtOp;
|
||||
|
||||
struct CharPtn
|
||||
{
|
||||
uint card;
|
||||
CharPtn *fix;
|
||||
CharPtn *nxt;
|
||||
};
|
||||
|
||||
typedef CharPtn *CharPtr;
|
||||
|
||||
struct CharSet
|
||||
{
|
||||
CharSet();
|
||||
~CharSet();
|
||||
|
||||
CharPtn *fix;
|
||||
CharPtn *freeHead, **freeTail;
|
||||
CharPtr *rep;
|
||||
CharPtn *ptn;
|
||||
};
|
||||
|
||||
class Range
|
||||
{
|
||||
|
||||
public:
|
||||
Range *next;
|
||||
uint lb, ub; // [lb,ub)
|
||||
|
||||
static free_list<Range*> vFreeList;
|
||||
|
||||
public:
|
||||
Range(uint l, uint u) : next(NULL), lb(l), ub(u)
|
||||
{
|
||||
vFreeList.insert(this);
|
||||
}
|
||||
|
||||
Range(Range &r) : next(NULL), lb(r.lb), ub(r.ub)
|
||||
{
|
||||
vFreeList.insert(this);
|
||||
}
|
||||
|
||||
~Range()
|
||||
{
|
||||
vFreeList.erase(this);
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream&, const Range&);
|
||||
friend std::ostream& operator<<(std::ostream&, const Range*);
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &o, const Range *r)
|
||||
{
|
||||
return r ? o << *r : o;
|
||||
}
|
||||
|
||||
class RegExp
|
||||
{
|
||||
|
||||
public:
|
||||
uint size;
|
||||
|
||||
static free_list<RegExp*> vFreeList;
|
||||
|
||||
public:
|
||||
RegExp() : size(0)
|
||||
{
|
||||
vFreeList.insert(this);
|
||||
}
|
||||
|
||||
virtual ~RegExp()
|
||||
{
|
||||
vFreeList.erase(this);
|
||||
}
|
||||
|
||||
virtual const char *typeOf() = 0;
|
||||
RegExp *isA(const char *t)
|
||||
{
|
||||
return typeOf() == t ? this : NULL;
|
||||
}
|
||||
|
||||
virtual void split(CharSet&) = 0;
|
||||
virtual void calcSize(Char*) = 0;
|
||||
virtual uint fixedLength();
|
||||
virtual void compile(Char*, Ins*) = 0;
|
||||
virtual void display(std::ostream&) const = 0;
|
||||
friend std::ostream& operator<<(std::ostream&, const RegExp&);
|
||||
friend std::ostream& operator<<(std::ostream&, const RegExp*);
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &o, const RegExp &re)
|
||||
{
|
||||
re.display(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &o, const RegExp *re)
|
||||
{
|
||||
return o << *re;
|
||||
}
|
||||
|
||||
class NullOp: public RegExp
|
||||
{
|
||||
|
||||
public:
|
||||
static const char *type;
|
||||
|
||||
public:
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
uint fixedLength();
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream &o) const
|
||||
{
|
||||
o << "_";
|
||||
}
|
||||
};
|
||||
|
||||
class MatchOp: public RegExp
|
||||
{
|
||||
|
||||
public:
|
||||
static const char *type;
|
||||
Range *match;
|
||||
|
||||
public:
|
||||
MatchOp(Range *m) : match(m)
|
||||
{
|
||||
}
|
||||
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
uint fixedLength();
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream&) const;
|
||||
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
MatchOp(const MatchOp& oth)
|
||||
: RegExp(oth)
|
||||
, match(oth.match)
|
||||
{
|
||||
}
|
||||
|
||||
MatchOp& operator = (const MatchOp& oth)
|
||||
{
|
||||
new(this) MatchOp(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class RuleOp: public RegExp
|
||||
{
|
||||
public:
|
||||
static const char *type;
|
||||
|
||||
private:
|
||||
RegExp *exp;
|
||||
|
||||
public:
|
||||
RegExp *ctx;
|
||||
Ins *ins;
|
||||
uint accept;
|
||||
Token *code;
|
||||
uint line;
|
||||
|
||||
public:
|
||||
RuleOp(RegExp*, RegExp*, Token*, uint);
|
||||
|
||||
~RuleOp()
|
||||
{
|
||||
delete code;
|
||||
}
|
||||
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream &o) const
|
||||
{
|
||||
o << exp << "/" << ctx << ";";
|
||||
}
|
||||
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
RuleOp(const RuleOp& oth)
|
||||
: RegExp(oth)
|
||||
, exp(oth.exp)
|
||||
, ctx(oth.ctx)
|
||||
, ins(oth.ins)
|
||||
, accept(oth.accept)
|
||||
, code(oth.code)
|
||||
, line(oth.line)
|
||||
{
|
||||
}
|
||||
RuleOp& operator = (const RuleOp& oth)
|
||||
{
|
||||
new(this) RuleOp(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class RuleLine: public line_number
|
||||
{
|
||||
public:
|
||||
|
||||
RuleLine(const RuleOp& _op)
|
||||
: op(_op)
|
||||
{
|
||||
}
|
||||
|
||||
uint get_line() const
|
||||
{
|
||||
return op.code->line;
|
||||
}
|
||||
|
||||
const RuleOp& op;
|
||||
};
|
||||
|
||||
RegExp *mkAlt(RegExp*, RegExp*);
|
||||
|
||||
class AltOp: public RegExp
|
||||
{
|
||||
|
||||
private:
|
||||
RegExp *exp1, *exp2;
|
||||
|
||||
public:
|
||||
static const char *type;
|
||||
|
||||
public:
|
||||
AltOp(RegExp *e1, RegExp *e2)
|
||||
: exp1(e1)
|
||||
, exp2(e2)
|
||||
{
|
||||
}
|
||||
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
uint fixedLength();
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream &o) const
|
||||
{
|
||||
o << exp1 << "|" << exp2;
|
||||
}
|
||||
|
||||
friend RegExp *mkAlt(RegExp*, RegExp*);
|
||||
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
AltOp(const AltOp& oth)
|
||||
: RegExp(oth)
|
||||
, exp1(oth.exp1)
|
||||
, exp2(oth.exp2)
|
||||
{
|
||||
}
|
||||
AltOp& operator = (const AltOp& oth)
|
||||
{
|
||||
new(this) AltOp(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class CatOp: public RegExp
|
||||
{
|
||||
|
||||
private:
|
||||
RegExp *exp1, *exp2;
|
||||
|
||||
public:
|
||||
static const char *type;
|
||||
|
||||
public:
|
||||
CatOp(RegExp *e1, RegExp *e2)
|
||||
: exp1(e1)
|
||||
, exp2(e2)
|
||||
{
|
||||
}
|
||||
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
uint fixedLength();
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream &o) const
|
||||
{
|
||||
o << exp1 << exp2;
|
||||
}
|
||||
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
CatOp(const CatOp& oth)
|
||||
: RegExp(oth)
|
||||
, exp1(oth.exp1)
|
||||
, exp2(oth.exp2)
|
||||
{
|
||||
}
|
||||
CatOp& operator = (const CatOp& oth)
|
||||
{
|
||||
new(this) CatOp(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class CloseOp: public RegExp
|
||||
{
|
||||
|
||||
private:
|
||||
RegExp *exp;
|
||||
|
||||
public:
|
||||
static const char *type;
|
||||
|
||||
public:
|
||||
CloseOp(RegExp *e)
|
||||
: exp(e)
|
||||
{
|
||||
}
|
||||
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream &o) const
|
||||
{
|
||||
o << exp << "+";
|
||||
}
|
||||
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
CloseOp(const CloseOp& oth)
|
||||
: RegExp(oth)
|
||||
, exp(oth.exp)
|
||||
{
|
||||
}
|
||||
CloseOp& operator = (const CloseOp& oth)
|
||||
{
|
||||
new(this) CloseOp(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class CloseVOp: public RegExp
|
||||
{
|
||||
|
||||
private:
|
||||
RegExp *exp;
|
||||
int min;
|
||||
int max;
|
||||
|
||||
public:
|
||||
static const char *type;
|
||||
|
||||
public:
|
||||
CloseVOp(RegExp *e, int lb, int ub)
|
||||
: exp(e)
|
||||
, min(lb)
|
||||
, max(ub)
|
||||
{
|
||||
}
|
||||
|
||||
const char *typeOf()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void split(CharSet&);
|
||||
void calcSize(Char*);
|
||||
void compile(Char*, Ins*);
|
||||
void display(std::ostream &o) const
|
||||
{
|
||||
o << exp << "+";
|
||||
}
|
||||
#ifdef PEDANTIC
|
||||
private:
|
||||
CloseVOp(const CloseVOp& oth)
|
||||
: RegExp(oth)
|
||||
, exp(oth.exp)
|
||||
, min(oth.min)
|
||||
, max(oth.max)
|
||||
{
|
||||
}
|
||||
CloseVOp& operator = (const CloseVOp& oth)
|
||||
{
|
||||
new(this) CloseVOp(oth);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
extern void genCode(std::ostream&, RegExp*);
|
||||
extern void genCode(std::ostream&, uint, RegExp*);
|
||||
extern void genGetState(std::ostream&, uint&, uint);
|
||||
extern RegExp *mkDiff(RegExp*, RegExp*);
|
||||
extern RegExp *mkAlt(RegExp*, RegExp*);
|
||||
|
||||
} // end namespace re2c
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
./"
|
||||
./" $Id: re2c.1.in 523 2006-05-25 13:32:09Z helly $
|
||||
./" $Id: re2c.1.in 663 2007-04-01 11:22:15Z helly $
|
||||
./"
|
||||
.TH RE2C 1 "22 April 2005" "Version 0.10.5"
|
||||
.TH RE2C 1 "22 April 2005" "Version 0.12.3"
|
||||
.ds re \fBre2c\fP
|
||||
.ds le \fBlex\fP
|
||||
.ds rx regular expression
|
||||
|
@ -10,7 +10,7 @@
|
|||
re2c \- convert regular expressions to C/C++
|
||||
|
||||
.SH SYNOPSIS
|
||||
\*(re [\fB-bdefghisvVw1\fP] [\fB-o output\fP] file\fP
|
||||
\*(re [\fB-bdefghisuvVw1\fP] [\fB-o output\fP] file\fP
|
||||
|
||||
.SH DESCRIPTION
|
||||
\*(re is a preprocessor that generates C-based recognizers from regular
|
||||
|
@ -26,61 +26,51 @@ For example, given the following code
|
|||
|
||||
.in +3
|
||||
.nf
|
||||
#define NULL ((char*) 0)
|
||||
char *scan(char *p)
|
||||
{
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT p
|
||||
#define YYFILL(n)
|
||||
/*!re2c
|
||||
[0-9]+ {return YYCURSOR;}
|
||||
[\\000-\\377] {return NULL;}
|
||||
re2c:define:YYCTYPE = "unsigned char";
|
||||
re2c:define:YYCURSOR = p;
|
||||
re2c:yyfill:enable = 0;
|
||||
re2c:yych:conversion = 1;
|
||||
re2c:indent:top = 1;
|
||||
[0-9]+ {return p;}
|
||||
[\000-\377] {return (char*)0;}
|
||||
*/
|
||||
}
|
||||
.fi
|
||||
.in -3
|
||||
|
||||
\*(re will generate
|
||||
\*(re -is will generate
|
||||
|
||||
.in +3
|
||||
.nf
|
||||
/* Generated by re2c on Sat Apr 16 11:40:58 1994 */
|
||||
#line 1 "simple.re"
|
||||
#define NULL ((char*) 0)
|
||||
char *scan(char *p)
|
||||
{
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR p
|
||||
#define YYLIMIT p
|
||||
#define YYFILL(n)
|
||||
{
|
||||
YYCTYPE yych;
|
||||
unsigned int yyaccept;
|
||||
goto yy0;
|
||||
yy1: ++YYCURSOR;
|
||||
yy0:
|
||||
if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
|
||||
yych = *YYCURSOR;
|
||||
if(yych <= '/') goto yy4;
|
||||
if(yych >= ':') goto yy4;
|
||||
yy2: yych = *++YYCURSOR;
|
||||
{
|
||||
unsigned char yych;
|
||||
|
||||
yych = (unsigned char)*p;
|
||||
if(yych <= '/') goto yy4;
|
||||
if(yych >= ':') goto yy4;
|
||||
++p;
|
||||
yych = (unsigned char)*p;
|
||||
goto yy7;
|
||||
yy3:
|
||||
#line 9
|
||||
{return YYCURSOR;}
|
||||
yy4: yych = *++YYCURSOR;
|
||||
yy5:
|
||||
#line 10
|
||||
{return NULL;}
|
||||
yy6: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy7: if(yych <= '/') goto yy3;
|
||||
if(yych <= '9') goto yy6;
|
||||
{return p;}
|
||||
yy4:
|
||||
++p;
|
||||
yych = (unsigned char)*p;
|
||||
{return char*)0;}
|
||||
yy6:
|
||||
++p;
|
||||
yych = (unsigned char)*p;
|
||||
yy7:
|
||||
if(yych <= '/') goto yy3;
|
||||
if(yych <= '9') goto yy6;
|
||||
goto yy3;
|
||||
}
|
||||
#line 11
|
||||
}
|
||||
|
||||
}
|
||||
.fi
|
||||
|
@ -123,7 +113,7 @@ Generate a scanner with support for storable state.
|
|||
For details see below at \fBSCANNER WITH STORABLE STATES\fP.
|
||||
.TP
|
||||
\fB-g\fP
|
||||
Generate a scanner that utilizes GCC's computed goto feature. That is re2c
|
||||
Generate a scanner that utilizes GCC's computed goto feature. That is \*(re
|
||||
generates jump tables whenever a decision is of a certain complexity (e.g. a
|
||||
lot of if conditions are otherwise necessary). This is only useable with GCC
|
||||
and produces output that cannot be compiled with any other compiler. Note that
|
||||
|
@ -132,8 +122,8 @@ inplace configuration "cgoto:threshold".
|
|||
.TP
|
||||
\fB-i\fP
|
||||
Do not output #line information. This is usefull when you want use a CMS tool
|
||||
with the re2c output which you might want if you do not require your users to
|
||||
have re2c themselves when building from your source.
|
||||
with the \*(re output which you might want if you do not require your users to
|
||||
have \*(re themselves when building from your source.
|
||||
\fB-o output\fP
|
||||
Specify the output file.
|
||||
.TP
|
||||
|
@ -141,6 +131,12 @@ Specify the output file.
|
|||
Generate nested \fCif\fPs for some \fCswitch\fPes. Many compilers need this
|
||||
assist to generate better code.
|
||||
.TP
|
||||
\fB-u\fP
|
||||
Generate a parser that supports Unicode chars (UTF-32). This means the
|
||||
generated code can deal with any valid Unicode character up to 0x10FFFF. When
|
||||
UTF-8 or UTF-16 needs to be supported you need to convert the incoming stream
|
||||
to UTF-32 upon input yourself.
|
||||
.TP
|
||||
\fB-v\fP
|
||||
Show version information.
|
||||
.TP
|
||||
|
@ -153,11 +149,16 @@ cannot be used together with \fB-e\fP switch.
|
|||
.TP
|
||||
\fB-1\fP
|
||||
Force single pass generation, this cannot be combined with -f and disables
|
||||
YYMAXFILL generation prior to last re2c block.
|
||||
YYMAXFILL generation prior to last \*(re block.
|
||||
.TP
|
||||
\fb--no-generation-date\fP
|
||||
Suppress date output in the generated output so that it only shows the re2c
|
||||
version.
|
||||
.SH "INTERFACE CODE"
|
||||
Unlike other scanner generators, \*(re does not generate complete scanners:
|
||||
the user must supply some interface code.
|
||||
In particular, the user must define the following macros:
|
||||
In particular, the user must define the following macros or use the
|
||||
corresponding inplace configurations:
|
||||
.TP
|
||||
\fCYYCTYPE\fP
|
||||
Type used to hold an input symbol.
|
||||
|
@ -187,26 +188,27 @@ The generated code saves trailing context backtracking information in \fCYYCTXMA
|
|||
The user only needs to define this macro if a scanner specification uses trailing
|
||||
context in one or more of its regular expressions.
|
||||
.TP
|
||||
\fCYYFILL(\fP\fIn\fP\fC)\fP
|
||||
\fCYYFILL\fP(\fIn\fP\fC\fP)
|
||||
The generated code "calls" \fCYYFILL\fP(n) when the buffer needs
|
||||
(re)filling: at least \fIn\fP additional characters should
|
||||
be provided. \fCYYFILL\fP(n) should adjust \fCYYCURSOR\fP, \fCYYLIMIT\fP,
|
||||
\fCYYMARKER\fP and \fCYYCTXMARKER\fP as needed. Note that for typical
|
||||
programming languages \fIn\fP will be the length of the longest keyword plus one.
|
||||
The user can place a comment of the form \fC/*!max:re2c */\fP once to insert
|
||||
a \fCYYMAXFILL\fP definition that is set to the maximum length value. If -1
|
||||
switch is used then YYMAXFILL can be triggered once after the last \fC/*!re2c */\fP
|
||||
a \fCYYMAXFILL\fP(n) definition that is set to the maximum length value. If -1
|
||||
switch is used then \fCYYMAXFILL\fP can be triggered only once after the
|
||||
last \fC/*!re2c */\fP
|
||||
block.
|
||||
.TP
|
||||
\fCYYGETSTATE()\fP
|
||||
\fCYYGETSTATE\fP()
|
||||
The user only needs to define this macro if the \fB-f\fP flag was specified.
|
||||
In that case, the generated code "calls" \fCYYGETSTATE\fP at the very beginning
|
||||
of the scanner in order to obtain the saved state. YYGETSTATE must return a signed
|
||||
In that case, the generated code "calls" \fCYYGETSTATE\fP() at the very beginning
|
||||
of the scanner in order to obtain the saved state. \fCYYGETSTATE\fP() must return a signed
|
||||
integer. The value must be either -1, indicating that the scanner is entered for the
|
||||
first time, or a value previously saved by \fCYYSETSTATE\fP. In the second case, the
|
||||
first time, or a value previously saved by \fCYYSETSTATE\fP(s). In the second case, the
|
||||
scanner will resume operations right after where the last \fCYYFILL\fP(n) was called.
|
||||
.TP
|
||||
\fCYYSETSTATE(\fP\fIn\fP\fC)\fP
|
||||
\fCYYSETSTATE(\fP\fIs\fP\fC)\fP
|
||||
The user only needs to define this macro if the \fB-f\fP flag was specified.
|
||||
In that case, the generated code "calls" \fCYYSETSTATE\fP just before calling
|
||||
\fCYYFILL\fP(n). The parameter to \fCYYSETSTATE\fP is a signed integer that uniquely
|
||||
|
@ -214,7 +216,9 @@ identifies the specific instance of \fCYYFILL\fP(n) that is about to be called.
|
|||
Should the user wish to save the state of the scanner and have \fCYYFILL\fP(n) return
|
||||
to the caller, all he has to do is store that unique identifer in a variable.
|
||||
Later, when the scannered is called again, it will call \fCYYGETSTATE()\fP and
|
||||
resume execution right where it left off.
|
||||
resume execution right where it left off. The generated code will contain
|
||||
both \fCYYSETSTATE\fP(s) and \fCYYGETSTATE\fP even if \fCYYFILL\fP(n) is being
|
||||
disabled.
|
||||
.TP
|
||||
\fCYYDEBUG(\fP\fIstate\fP,\fIcurrent\fC)\fP
|
||||
This is only needed if the \fB-d\fP flag was specified. It allows to easily debug
|
||||
|
@ -227,11 +231,11 @@ input at the current cursor.
|
|||
This will be automatically defined by \fC/*!max:re2c */\fP blocks as explained above.
|
||||
|
||||
.SH "SCANNER WITH STORABLE STATES"
|
||||
When the \fB-f\fP flag is specified, re2c generates a scanner that
|
||||
When the \fB-f\fP flag is specified, \*(re generates a scanner that
|
||||
can store its current state, return to the caller, and later resume
|
||||
operations exactly where it left off.
|
||||
|
||||
The default operation of re2c is a "pull" model, where the scanner asks
|
||||
The default operation of \*(re is a "pull" model, where the scanner asks
|
||||
for extra input whenever it needs it. However, this mode of operation
|
||||
assumes that the scanner is the "owner" the parsing loop, and that may
|
||||
not always be convenient.
|
||||
|
@ -246,9 +250,9 @@ chunk by chunk. When the scanner runs out of data to consume, it just stores
|
|||
its state, and return to the caller. When more input data is fed to the scanner,
|
||||
it resumes operations exactly where it left off.
|
||||
|
||||
When using the -f option re2c does not accept stdin because it has to do the
|
||||
When using the -f option \*(re does not accept stdin because it has to do the
|
||||
full generation process twice which means it has to read the input twice. That
|
||||
means re2c would fail in case it cannot open the input twice or reading the
|
||||
means \*(re would fail in case it cannot open the input twice or reading the
|
||||
input for the first time influences the second read attempt.
|
||||
|
||||
Changes needed compared to the "pull" model.
|
||||
|
@ -286,7 +290,7 @@ Please see examples/push.re for push-model scanner. The generated code can be
|
|||
tweaked using inplace configurations "\fBstate:abort\fP" and "\fBstate:nextlabel\fP".
|
||||
|
||||
.SH "SCANNER SPECIFICATIONS"
|
||||
Each scanner specification consists of a set of \fIrules\fP, \fIname
|
||||
Each scanner specification consists of a set of \fIrules\fP, \fInamed
|
||||
definitions\fP and \fIconfigurations\fP.
|
||||
.LP
|
||||
\fIRules\fP consist of a regular expression along with a block of C/C++ code that
|
||||
|
@ -302,12 +306,15 @@ Named definitions are of the form:
|
|||
\fIname\fP \fC=\fP \fIregular expression\fP\fC;\fP
|
||||
.RE
|
||||
.LP
|
||||
Configurations look like name definitions whose names start
|
||||
Configurations look like named definitions whose names start
|
||||
with "\fBre2c:\fP":
|
||||
.P
|
||||
.RS
|
||||
\fCre2c:\fP\fIname\fP \fC=\fP \fIvalue\fP\fC;\fP
|
||||
.RE
|
||||
.RS
|
||||
\fCre2c:\fP\fIname\fP \fC=\fP \fB"\fP\fIvalue\fP\fB"\fP\fC;\fP
|
||||
.RE
|
||||
|
||||
.SH "SUMMARY OF RE2C REGULAR EXPRESSIONS"
|
||||
.TP
|
||||
|
@ -345,7 +352,7 @@ one or more \fIr\fP's
|
|||
zero or one \fIr\fP's (that is, "an optional \fIr\fP")
|
||||
.TP
|
||||
name
|
||||
the expansion of the "name" definition (see above)
|
||||
the expansion of the "named definition" (see above)
|
||||
.TP
|
||||
\fC(\fP\fIr\fP\fC)\fP
|
||||
an \fIr\fP; parentheses are used to override precedence
|
||||
|
@ -385,12 +392,10 @@ and a hexadecimal character is defined by backslash, a lower cased '\fBx\fP'
|
|||
and its two hexadecimal digits or a backslash, an upper cased \fBX\fP and its
|
||||
four hexadecimal digits.
|
||||
.LP
|
||||
re2c
|
||||
further more supports the c/c++ unicode notation. That is a backslash followed
|
||||
\*(re further more supports the c/c++ unicode notation. That is a backslash followed
|
||||
by either a lowercased \fBu\fP and its four hexadecimal digits or an uppercased
|
||||
\fBU\fP and its eight hexadecimal digits. However using the U notation it is
|
||||
not possible to support characters greater \fB\\U0000FFFF\fP due to an internal
|
||||
limitation of re2c.
|
||||
\fBU\fP and its eight hexadecimal digits. However only in \fB-u\fP mode the
|
||||
generated code can deal with any valid Unicode character up to 0x10FFFF.
|
||||
.LP
|
||||
Since characters greater \fB\\X00FF\fP are not allowed in non unicode mode, the
|
||||
only portable "\fBany\fP" rules are \fB(.|"\\n")\fP and \fB[^]\fP.
|
||||
|
@ -401,7 +406,7 @@ Those grouped together have equal precedence.
|
|||
|
||||
.SH "INPLACE CONFIGURATION"
|
||||
.LP
|
||||
It is possible to configure code generation inside re2c blocks. The following
|
||||
It is possible to configure code generation inside \*(re blocks. The following
|
||||
lists the available configurations:
|
||||
.TP
|
||||
\fIre2c:indent:top\fP \fB=\fP 0 \fB;\fP
|
||||
|
@ -423,6 +428,12 @@ Set this to zero to suppress generation of YYFILL(n). When using this be sure
|
|||
to verify that the generated scanner does not read behind input. Allowing
|
||||
this behavior might introduce sever security issues to you programs.
|
||||
.TP
|
||||
\fIre2c:yyfill:parameter\fP \fB=\fP 1 \fB;\fP
|
||||
Allows to suppress parameter passing to \fBYYFILL\fP calls. If set to zero
|
||||
then no parameter is passed to \fBYYFILL\fP. If set to a non zero value then
|
||||
\fBYYFILL\fP usage will be followed by the number of requested characters in
|
||||
braces.
|
||||
.TP
|
||||
\fIre2c:startlabel\fP \fB=\fP 0 \fB;\fP
|
||||
If set to a non zero integer then the start label of the next scanner blocks
|
||||
will be generated even if not used by the scanner itself. Otherwise the normal
|
||||
|
@ -431,6 +442,10 @@ value then a label with that text will be generated regardless of whether the
|
|||
normal start label is being used or not. This setting is being reset to \fB0\fP
|
||||
after a start label has been generated.
|
||||
.TP
|
||||
\fIre2c:labelprefix\fP \fB=\fP yy \fB;\fP
|
||||
Allows to change the prefix of numbered labels. The default is \fByy\fP and
|
||||
can be set any string that is a valid label.
|
||||
.TP
|
||||
\fIre2c:state:abort\fP \fB=\fP 0 \fB;\fP
|
||||
When not zero and switch -f is active then the \fCYYGETSTATE\fP block will
|
||||
contain a default case that aborts and a -1 case is used for initialization.
|
||||
|
@ -448,11 +463,77 @@ When -g is active this value specifies the complexity threshold that triggers
|
|||
generation of jump tables rather than using nested if's and decision bitfields.
|
||||
The threshold is compared against a calculated estimation of if-s needed where
|
||||
every used bitmap divides the threshold by 2.
|
||||
.TP
|
||||
\fIre2c:yych:conversion\fP \fB=\fP 0 \fB;\fP
|
||||
When the input uses signed characters and \fB-s\fP or \fB-b\fP switches are
|
||||
in effect re2c allows to automatically convert to the unsigned character type
|
||||
that is then necessary for its internal single character. When this setting
|
||||
is zero or an empty string the conversion is disabled. Using a non zero number
|
||||
the conversion is taken from \fBYYCTYPE\fP. If that is given by an inplace
|
||||
configuration that value is being used. Otherwise it will be \fB(YYCTYPE)\fP
|
||||
and changes to that configuration are no longer possible. When this setting is
|
||||
a string the braces must be specified. Now assuming your input is a \fBchar*\fP
|
||||
buffer and you are using above mentioned switches you can set \fBYYCTYPE\fP to
|
||||
\fBunsigned char\fP and this setting to either \fB1\fP or \fB"(unsigned char)"\fP.
|
||||
.TP
|
||||
\fIre2c:define:YYCTXMARKER\fP \fB=\fP YYCTXMARKER \fB;\fP
|
||||
Allows to overwrite the define YYCTXMARKER and thus avoiding it by setting the
|
||||
value to the actual code needed.
|
||||
.TP
|
||||
\fIre2c:define:YYCTYPE\fP \fB=\fP YYCTYPE \fB;\fP
|
||||
Allows to overwrite the define YYCTYPE and thus avoiding it by setting the
|
||||
value to the actual code needed.
|
||||
.TP
|
||||
\fIre2c:define:YYCURSOR\fP \fB=\fP YYCURSOR \fB;\fP
|
||||
Allows to overwrite the define YYCURSOR and thus avoiding it by setting the
|
||||
value to the actual code needed.
|
||||
.TP
|
||||
\fIre2c:define:YYDEBUG\fP \fB=\fP YYDEBUG \fB;\fP
|
||||
Allows to overwrite the define YYDEBUG and thus avoiding it by setting the
|
||||
value to the actual code needed.
|
||||
.TP
|
||||
\fIre2c:define:YYFILL\fP \fB=\fP YYFILL \fB;\fP
|
||||
Allows to overwrite the define YYFILL and thus avoiding it by setting the
|
||||
value to the actual code needed.
|
||||
.TP
|
||||
\fIre2c:define:YYGETSTATE\fP \fB=\fP YYGETSTATE \fB;\fP
|
||||
Allows to overwrite the define YYGETSTATE and thus avoiding it by setting the
|
||||
value to the actual code needed.
|
||||
.TP
|
||||
\fIre2c:define:YYLIMIT\fP \fB=\fP YYLIMIT \fB;\fP
|
||||
Allows to overwrite the define YYLIMIT and thus avoiding it by setting the
|
||||
value to the actual code needed.
|
||||
.TP
|
||||
\fIre2c:define:YYMARKER\fP \fB=\fP YYMARKER \fB;\fP
|
||||
Allows to overwrite the define YYMARKER and thus avoiding it by setting the
|
||||
value to the actual code needed.
|
||||
.TP
|
||||
\fIre2c:define:YYSETSTATE\fP \fB=\fP YYSETSTATE \fB;\fP
|
||||
Allows to overwrite the define YYSETSTATE and thus avoiding it by setting the
|
||||
value to the actual code needed.
|
||||
.TP
|
||||
\fIre2c:label:yyFillLabel\fP \fB=\fP yyFillLabel \fB;\fP
|
||||
Allows to overwrite the name of the label yyFillLabel.
|
||||
.TP
|
||||
\fIre2c:label:yyNext\fP \fB=\fP yyNext \fB;\fP
|
||||
Allows to overwrite the name of the label yyNext.
|
||||
.TP
|
||||
\fIre2c:variable:yyaccept\fP \fB=\fP yyaccept \fB;\fP
|
||||
Allows to overwrite the name of the variable yyaccept.
|
||||
.TP
|
||||
\fIre2c:variable:yybm\fP \fB=\fP yybm \fB;\fP
|
||||
Allows to overwrite the name of the variable yybm.
|
||||
.TP
|
||||
\fIre2c:variable:yych\fP \fB=\fP yych \fB;\fP
|
||||
Allows to overwrite the name of the variable yych.
|
||||
.TP
|
||||
\fIre2c:variable:yytarget\fP \fB=\fP yytarget \fB;\fP
|
||||
Allows to overwrite the name of the variable yytarget.
|
||||
|
||||
.SH "UNDERSTANDING RE2C"
|
||||
.LP
|
||||
The subdirectory lessons of the re2c distribution contains a few step by step
|
||||
lessons to get you started with re2c. All examples in the lessons subdirectory
|
||||
The subdirectory lessons of the \*(re distribution contains a few step by step
|
||||
lessons to get you started with \*(re. All examples in the lessons subdirectory
|
||||
can be compiled and actually work.
|
||||
|
||||
.SH FEATURES
|
||||
|
@ -487,10 +568,10 @@ The \*(re internal algorithms need documentation.
|
|||
.LP
|
||||
flex(1), lex(1).
|
||||
.P
|
||||
More information on \fBre2c\fP can be found here:
|
||||
More information on \*(re can be found here:
|
||||
.PD 0
|
||||
.P
|
||||
.B http://sourceforge.net/projects/re2c/
|
||||
.B http://re2c.org/
|
||||
.PD 1
|
||||
|
||||
.SH AUTHORS
|
||||
|
@ -511,6 +592,6 @@ Emmanuel Mogenet <mgix@mgix.com> added storable state
|
|||
.PD 1
|
||||
|
||||
.SH VERSION INFORMATION
|
||||
This manpage describes \fBre2c\fP, version 0.10.5.
|
||||
This manpage describes \*(re, version 0.12.3.
|
||||
|
||||
.fi
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,373 +1,373 @@
|
|||
/* $Id:$ */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "scanner.h"
|
||||
#include "parser.h"
|
||||
#include "y.tab.h"
|
||||
#include "globals.h"
|
||||
#include "dfa.h"
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
#define BSIZE 8192
|
||||
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR cursor
|
||||
#define YYLIMIT lim
|
||||
#define YYMARKER ptr
|
||||
#define YYFILL(n) {cursor = fill(cursor);}
|
||||
|
||||
#define RETURN(i) {cur = cursor; return i;}
|
||||
|
||||
namespace re2c
|
||||
{
|
||||
|
||||
Scanner::Scanner(const char *fn, std::istream& i, std::ostream& o)
|
||||
: in(i)
|
||||
, out(o)
|
||||
, bot(NULL), tok(NULL), ptr(NULL), cur(NULL), pos(NULL), lim(NULL)
|
||||
, top(NULL), eof(NULL), tchar(0), tline(0), cline(1), iscfg(0), filename(fn)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
char *Scanner::fill(char *cursor)
|
||||
{
|
||||
if(!eof)
|
||||
{
|
||||
uint cnt = tok - bot;
|
||||
if(cnt)
|
||||
{
|
||||
memcpy(bot, tok, lim - tok);
|
||||
tok = bot;
|
||||
ptr -= cnt;
|
||||
cursor -= cnt;
|
||||
pos -= cnt;
|
||||
lim -= cnt;
|
||||
}
|
||||
if((top - lim) < BSIZE)
|
||||
{
|
||||
char *buf = new char[(lim - bot) + BSIZE];
|
||||
memcpy(buf, tok, lim - tok);
|
||||
tok = buf;
|
||||
ptr = &buf[ptr - bot];
|
||||
cursor = &buf[cursor - bot];
|
||||
pos = &buf[pos - bot];
|
||||
lim = &buf[lim - bot];
|
||||
top = &lim[BSIZE];
|
||||
delete [] bot;
|
||||
bot = buf;
|
||||
}
|
||||
in.read(lim, BSIZE);
|
||||
if ((cnt = in.gcount()) != BSIZE )
|
||||
{
|
||||
eof = &lim[cnt]; *eof++ = '\0';
|
||||
}
|
||||
lim += cnt;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/*!re2c
|
||||
zero = "\000";
|
||||
any = [\000-\377];
|
||||
dot = any \ [\n];
|
||||
esc = dot \ [\\];
|
||||
istring = "[" "^" ((esc \ [\]]) | "\\" dot)* "]" ;
|
||||
cstring = "[" ((esc \ [\]]) | "\\" dot)* "]" ;
|
||||
dstring = "\"" ((esc \ ["] ) | "\\" dot)* "\"";
|
||||
sstring = "'" ((esc \ ['] ) | "\\" dot)* "'" ;
|
||||
letter = [a-zA-Z];
|
||||
digit = [0-9];
|
||||
number = "0" | ("-"? [1-9] digit*);
|
||||
/* $Id: scanner.re 663 2007-04-01 11:22:15Z helly $ */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "scanner.h"
|
||||
#include "parser.h"
|
||||
#include "y.tab.h"
|
||||
#include "globals.h"
|
||||
#include "dfa.h"
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
#define BSIZE 8192
|
||||
|
||||
#define YYCTYPE unsigned char
|
||||
#define YYCURSOR cursor
|
||||
#define YYLIMIT lim
|
||||
#define YYMARKER ptr
|
||||
#define YYFILL(n) {cursor = fill(cursor);}
|
||||
|
||||
#define RETURN(i) {cur = cursor; return i;}
|
||||
|
||||
namespace re2c
|
||||
{
|
||||
|
||||
Scanner::Scanner(const char *fn, std::istream& i, std::ostream& o)
|
||||
: in(i)
|
||||
, out(o)
|
||||
, bot(NULL), tok(NULL), ptr(NULL), cur(NULL), pos(NULL), lim(NULL)
|
||||
, top(NULL), eof(NULL), tchar(0), tline(0), cline(1), iscfg(0), filename(fn)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
char *Scanner::fill(char *cursor)
|
||||
{
|
||||
if(!eof)
|
||||
{
|
||||
uint cnt = tok - bot;
|
||||
if(cnt)
|
||||
{
|
||||
memcpy(bot, tok, lim - tok);
|
||||
tok = bot;
|
||||
ptr -= cnt;
|
||||
cursor -= cnt;
|
||||
pos -= cnt;
|
||||
lim -= cnt;
|
||||
}
|
||||
if((top - lim) < BSIZE)
|
||||
{
|
||||
char *buf = new char[(lim - bot) + BSIZE];
|
||||
memcpy(buf, tok, lim - tok);
|
||||
tok = buf;
|
||||
ptr = &buf[ptr - bot];
|
||||
cursor = &buf[cursor - bot];
|
||||
pos = &buf[pos - bot];
|
||||
lim = &buf[lim - bot];
|
||||
top = &lim[BSIZE];
|
||||
delete [] bot;
|
||||
bot = buf;
|
||||
}
|
||||
in.read(lim, BSIZE);
|
||||
if ((cnt = in.gcount()) != BSIZE )
|
||||
{
|
||||
eof = &lim[cnt]; *eof++ = '\0';
|
||||
}
|
||||
lim += cnt;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/*!re2c
|
||||
zero = "\000";
|
||||
any = [\000-\377];
|
||||
dot = any \ [\n];
|
||||
esc = dot \ [\\];
|
||||
istring = "[" "^" ((esc \ [\]]) | "\\" dot)* "]" ;
|
||||
cstring = "[" ((esc \ [\]]) | "\\" dot)* "]" ;
|
||||
dstring = "\"" ((esc \ ["] ) | "\\" dot)* "\"";
|
||||
sstring = "'" ((esc \ ['] ) | "\\" dot)* "'" ;
|
||||
letter = [a-zA-Z];
|
||||
digit = [0-9];
|
||||
number = "0" | ("-"? [1-9] digit*);
|
||||
name = (letter|"_") (letter|digit|"_")*;
|
||||
cname = ":" name;
|
||||
space = [ \t];
|
||||
eol = ("\r\n" | "\n");
|
||||
config = "re2c" cname+;
|
||||
value = [^\r\n; \t]* | dstring | sstring;
|
||||
*/
|
||||
|
||||
int Scanner::echo()
|
||||
{
|
||||
char *cursor = cur;
|
||||
bool ignore_eoc = false;
|
||||
int ignore_cnt = 0;
|
||||
|
||||
if (eof && cursor == eof) // Catch EOF
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
tok = cursor;
|
||||
echo:
|
||||
/*!re2c
|
||||
"/*!re2c" {
|
||||
if (bUsedYYMaxFill && bSinglePass) {
|
||||
fatal("found scanner block after YYMAXFILL declaration");
|
||||
}
|
||||
out.write((const char*)(tok), (const char*)(&cursor[-7]) - (const char*)(tok));
|
||||
tok = cursor;
|
||||
RETURN(1);
|
||||
}
|
||||
"/*!max:re2c" {
|
||||
if (bUsedYYMaxFill) {
|
||||
fatal("cannot generate YYMAXFILL twice");
|
||||
}
|
||||
out << "#define YYMAXFILL " << maxFill << std::endl;
|
||||
tok = pos = cursor;
|
||||
ignore_eoc = true;
|
||||
bUsedYYMaxFill = true;
|
||||
goto echo;
|
||||
}
|
||||
"/*!getstate:re2c" {
|
||||
tok = pos = cursor;
|
||||
genGetState(out, topIndent, 0);
|
||||
ignore_eoc = true;
|
||||
goto echo;
|
||||
}
|
||||
"/*!ignore:re2c" {
|
||||
tok = pos = cursor;
|
||||
ignore_eoc = true;
|
||||
goto echo;
|
||||
}
|
||||
"*" "/" "\r"? "\n" {
|
||||
cline++;
|
||||
if (ignore_eoc) {
|
||||
if (ignore_cnt) {
|
||||
out << sourceFileInfo;
|
||||
}
|
||||
ignore_eoc = false;
|
||||
ignore_cnt = 0;
|
||||
} else {
|
||||
out.write((const char*)(tok), (const char*)(cursor) - (const char*)(tok));
|
||||
}
|
||||
tok = pos = cursor;
|
||||
goto echo;
|
||||
}
|
||||
"*" "/" {
|
||||
if (ignore_eoc) {
|
||||
if (ignore_cnt) {
|
||||
out << "\n" << sourceFileInfo;
|
||||
}
|
||||
ignore_eoc = false;
|
||||
ignore_cnt = 0;
|
||||
} else {
|
||||
out.write((const char*)(tok), (const char*)(cursor) - (const char*)(tok));
|
||||
}
|
||||
tok = pos = cursor;
|
||||
goto echo;
|
||||
}
|
||||
"\n" {
|
||||
if (ignore_eoc) {
|
||||
ignore_cnt++;
|
||||
} else {
|
||||
out.write((const char*)(tok), (const char*)(cursor) - (const char*)(tok));
|
||||
}
|
||||
tok = pos = cursor; cline++;
|
||||
goto echo;
|
||||
}
|
||||
zero {
|
||||
if (!ignore_eoc) {
|
||||
out.write((const char*)(tok), (const char*)(cursor) - (const char*)(tok) - 1); // -1 so we don't write out the \0
|
||||
}
|
||||
if(cursor == eof) {
|
||||
RETURN(0);
|
||||
}
|
||||
}
|
||||
any {
|
||||
goto echo;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
int Scanner::scan()
|
||||
{
|
||||
char *cursor = cur;
|
||||
uint depth;
|
||||
|
||||
scan:
|
||||
tchar = cursor - pos;
|
||||
tline = cline;
|
||||
tok = cursor;
|
||||
if (iscfg == 1)
|
||||
{
|
||||
goto config;
|
||||
}
|
||||
else if (iscfg == 2)
|
||||
{
|
||||
goto value;
|
||||
}
|
||||
/*!re2c
|
||||
"{" { depth = 1;
|
||||
goto code;
|
||||
}
|
||||
"/*" { depth = 1;
|
||||
goto comment; }
|
||||
|
||||
"*/" { tok = cursor;
|
||||
RETURN(0); }
|
||||
|
||||
dstring { cur = cursor;
|
||||
yylval.regexp = strToRE(token());
|
||||
return STRING; }
|
||||
|
||||
sstring { cur = cursor;
|
||||
yylval.regexp = strToCaseInsensitiveRE(token());
|
||||
return STRING; }
|
||||
|
||||
"\"" { fatal("unterminated string constant (missing \")"); }
|
||||
"'" { fatal("unterminated string constant (missing ')"); }
|
||||
|
||||
istring { cur = cursor;
|
||||
yylval.regexp = invToRE(token());
|
||||
return RANGE; }
|
||||
|
||||
cstring { cur = cursor;
|
||||
yylval.regexp = ranToRE(token());
|
||||
return RANGE; }
|
||||
|
||||
"[" { fatal("unterminated range (missing ])"); }
|
||||
|
||||
[()|=;/\\] { RETURN(*tok); }
|
||||
|
||||
[*+?] { yylval.op = *tok;
|
||||
RETURN(CLOSE); }
|
||||
|
||||
"{0,}" { yylval.op = '*';
|
||||
RETURN(CLOSE); }
|
||||
|
||||
"{" [0-9]+ "}" { yylval.extop.minsize = atoi((char *)tok+1);
|
||||
yylval.extop.maxsize = atoi((char *)tok+1);
|
||||
RETURN(CLOSESIZE); }
|
||||
|
||||
"{" [0-9]+ "," [0-9]+ "}" { yylval.extop.minsize = atoi((char *)tok+1);
|
||||
yylval.extop.maxsize = MAX(yylval.extop.minsize,atoi(strchr((char *)tok, ',')+1));
|
||||
RETURN(CLOSESIZE); }
|
||||
|
||||
"{" [0-9]+ ",}" { yylval.extop.minsize = atoi((char *)tok+1);
|
||||
yylval.extop.maxsize = -1;
|
||||
RETURN(CLOSESIZE); }
|
||||
|
||||
"{" [0-9]* "," { fatal("illegal closure form, use '{n}', '{n,}', '{n,m}' where n and m are numbers"); }
|
||||
|
||||
config { cur = cursor;
|
||||
tok+= 5; /* skip "re2c:" */
|
||||
iscfg = 1;
|
||||
yylval.str = new Str(token());
|
||||
return CONFIG;
|
||||
}
|
||||
|
||||
name { cur = cursor;
|
||||
yylval.symbol = Symbol::find(token());
|
||||
return ID; }
|
||||
|
||||
"." { cur = cursor;
|
||||
yylval.regexp = mkDot();
|
||||
return RANGE;
|
||||
}
|
||||
|
||||
space+ { goto scan; }
|
||||
|
||||
eol { if(cursor == eof) RETURN(0);
|
||||
pos = cursor; cline++;
|
||||
goto scan;
|
||||
}
|
||||
|
||||
any { std::ostringstream msg;
|
||||
msg << "unexpected character: ";
|
||||
prtChOrHex(msg, *tok);
|
||||
fatal(msg.str().c_str());
|
||||
goto scan;
|
||||
}
|
||||
*/
|
||||
|
||||
code:
|
||||
/*!re2c
|
||||
"}" { if(--depth == 0){
|
||||
cur = cursor;
|
||||
yylval.token = new Token(token(), tline);
|
||||
return CODE;
|
||||
}
|
||||
goto code; }
|
||||
"{" { ++depth;
|
||||
goto code; }
|
||||
"\n" { if(cursor == eof) fatal("missing '}'");
|
||||
pos = cursor; cline++;
|
||||
goto code;
|
||||
}
|
||||
zero { if(cursor == eof) {
|
||||
if (depth) fatal("missing '}'");
|
||||
RETURN(0);
|
||||
}
|
||||
goto code;
|
||||
}
|
||||
dstring | sstring | any { goto code; }
|
||||
*/
|
||||
|
||||
comment:
|
||||
/*!re2c
|
||||
"*/" { if(--depth == 0)
|
||||
goto scan;
|
||||
else
|
||||
goto comment; }
|
||||
"/*" { ++depth;
|
||||
fatal("ambiguous /* found");
|
||||
goto comment; }
|
||||
"\n" { if(cursor == eof) RETURN(0);
|
||||
tok = pos = cursor; cline++;
|
||||
goto comment;
|
||||
}
|
||||
any { if(cursor == eof) RETURN(0);
|
||||
goto comment; }
|
||||
*/
|
||||
|
||||
config:
|
||||
/*!re2c
|
||||
space+ { goto config; }
|
||||
"=" space* { iscfg = 2;
|
||||
cur = cursor;
|
||||
RETURN('=');
|
||||
}
|
||||
any { fatal("missing '='"); }
|
||||
*/
|
||||
|
||||
value:
|
||||
/*!re2c
|
||||
number { cur = cursor;
|
||||
yylval.number = atoi(token().to_string().c_str());
|
||||
iscfg = 0;
|
||||
return NUMBER;
|
||||
}
|
||||
value { cur = cursor;
|
||||
yylval.str = new Str(token());
|
||||
iscfg = 0;
|
||||
return VALUE;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Scanner::fatal(uint ofs, const char *msg) const
|
||||
{
|
||||
out.flush();
|
||||
#ifdef _MSC_VER
|
||||
std::cerr << filename << "(" << tline << "): error : "
|
||||
<< "column " << (tchar + ofs + 1) << ": "
|
||||
<< msg << std::endl;
|
||||
#else
|
||||
std::cerr << "re2c: error: "
|
||||
<< "line " << tline << ", column " << (tchar + ofs + 1) << ": "
|
||||
<< msg << std::endl;
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
space = [ \t];
|
||||
eol = ("\r\n" | "\n");
|
||||
config = "re2c" cname+;
|
||||
value = [^\r\n; \t]* | dstring | sstring;
|
||||
*/
|
||||
|
||||
int Scanner::echo()
|
||||
{
|
||||
char *cursor = cur;
|
||||
bool ignore_eoc = false;
|
||||
int ignore_cnt = 0;
|
||||
|
||||
if (eof && cursor == eof) // Catch EOF
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
tok = cursor;
|
||||
echo:
|
||||
/*!re2c
|
||||
"/*!re2c" {
|
||||
if (bUsedYYMaxFill && bSinglePass) {
|
||||
fatal("found scanner block after YYMAXFILL declaration");
|
||||
}
|
||||
out.write((const char*)(tok), (const char*)(&cursor[-7]) - (const char*)(tok));
|
||||
tok = cursor;
|
||||
RETURN(1);
|
||||
}
|
||||
"/*!max:re2c" {
|
||||
if (bUsedYYMaxFill) {
|
||||
fatal("cannot generate YYMAXFILL twice");
|
||||
}
|
||||
out << "#define YYMAXFILL " << maxFill << std::endl;
|
||||
tok = pos = cursor;
|
||||
ignore_eoc = true;
|
||||
bUsedYYMaxFill = true;
|
||||
goto echo;
|
||||
}
|
||||
"/*!getstate:re2c" {
|
||||
tok = pos = cursor;
|
||||
genGetState(out, topIndent, 0);
|
||||
ignore_eoc = true;
|
||||
goto echo;
|
||||
}
|
||||
"/*!ignore:re2c" {
|
||||
tok = pos = cursor;
|
||||
ignore_eoc = true;
|
||||
goto echo;
|
||||
}
|
||||
"*" "/" "\r"? "\n" {
|
||||
cline++;
|
||||
if (ignore_eoc) {
|
||||
if (ignore_cnt) {
|
||||
out << sourceFileInfo;
|
||||
}
|
||||
ignore_eoc = false;
|
||||
ignore_cnt = 0;
|
||||
} else {
|
||||
out.write((const char*)(tok), (const char*)(cursor) - (const char*)(tok));
|
||||
}
|
||||
tok = pos = cursor;
|
||||
goto echo;
|
||||
}
|
||||
"*" "/" {
|
||||
if (ignore_eoc) {
|
||||
if (ignore_cnt) {
|
||||
out << "\n" << sourceFileInfo;
|
||||
}
|
||||
ignore_eoc = false;
|
||||
ignore_cnt = 0;
|
||||
} else {
|
||||
out.write((const char*)(tok), (const char*)(cursor) - (const char*)(tok));
|
||||
}
|
||||
tok = pos = cursor;
|
||||
goto echo;
|
||||
}
|
||||
"\n" {
|
||||
if (ignore_eoc) {
|
||||
ignore_cnt++;
|
||||
} else {
|
||||
out.write((const char*)(tok), (const char*)(cursor) - (const char*)(tok));
|
||||
}
|
||||
tok = pos = cursor; cline++;
|
||||
goto echo;
|
||||
}
|
||||
zero {
|
||||
if (!ignore_eoc) {
|
||||
out.write((const char*)(tok), (const char*)(cursor) - (const char*)(tok) - 1); // -1 so we don't write out the \0
|
||||
}
|
||||
if(cursor == eof) {
|
||||
RETURN(0);
|
||||
}
|
||||
}
|
||||
any {
|
||||
goto echo;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
int Scanner::scan()
|
||||
{
|
||||
char *cursor = cur;
|
||||
uint depth;
|
||||
|
||||
scan:
|
||||
tchar = cursor - pos;
|
||||
tline = cline;
|
||||
tok = cursor;
|
||||
if (iscfg == 1)
|
||||
{
|
||||
goto config;
|
||||
}
|
||||
else if (iscfg == 2)
|
||||
{
|
||||
goto value;
|
||||
}
|
||||
/*!re2c
|
||||
"{" { depth = 1;
|
||||
goto code;
|
||||
}
|
||||
"/*" { depth = 1;
|
||||
goto comment; }
|
||||
|
||||
"*/" { tok = cursor;
|
||||
RETURN(0); }
|
||||
|
||||
dstring { cur = cursor;
|
||||
yylval.regexp = strToRE(token());
|
||||
return STRING; }
|
||||
|
||||
sstring { cur = cursor;
|
||||
yylval.regexp = strToCaseInsensitiveRE(token());
|
||||
return STRING; }
|
||||
|
||||
"\"" { fatal("unterminated string constant (missing \")"); }
|
||||
"'" { fatal("unterminated string constant (missing ')"); }
|
||||
|
||||
istring { cur = cursor;
|
||||
yylval.regexp = invToRE(token());
|
||||
return RANGE; }
|
||||
|
||||
cstring { cur = cursor;
|
||||
yylval.regexp = ranToRE(token());
|
||||
return RANGE; }
|
||||
|
||||
"[" { fatal("unterminated range (missing ])"); }
|
||||
|
||||
[()|=;/\\] { RETURN(*tok); }
|
||||
|
||||
[*+?] { yylval.op = *tok;
|
||||
RETURN(CLOSE); }
|
||||
|
||||
"{0,}" { yylval.op = '*';
|
||||
RETURN(CLOSE); }
|
||||
|
||||
"{" [0-9]+ "}" { yylval.extop.minsize = atoi((char *)tok+1);
|
||||
yylval.extop.maxsize = atoi((char *)tok+1);
|
||||
RETURN(CLOSESIZE); }
|
||||
|
||||
"{" [0-9]+ "," [0-9]+ "}" { yylval.extop.minsize = atoi((char *)tok+1);
|
||||
yylval.extop.maxsize = MAX(yylval.extop.minsize,atoi(strchr((char *)tok, ',')+1));
|
||||
RETURN(CLOSESIZE); }
|
||||
|
||||
"{" [0-9]+ ",}" { yylval.extop.minsize = atoi((char *)tok+1);
|
||||
yylval.extop.maxsize = -1;
|
||||
RETURN(CLOSESIZE); }
|
||||
|
||||
"{" [0-9]* "," { fatal("illegal closure form, use '{n}', '{n,}', '{n,m}' where n and m are numbers"); }
|
||||
|
||||
config { cur = cursor;
|
||||
tok+= 5; /* skip "re2c:" */
|
||||
iscfg = 1;
|
||||
yylval.str = new Str(token());
|
||||
return CONFIG;
|
||||
}
|
||||
|
||||
name { cur = cursor;
|
||||
yylval.symbol = Symbol::find(token());
|
||||
return ID; }
|
||||
|
||||
"." { cur = cursor;
|
||||
yylval.regexp = mkDot();
|
||||
return RANGE;
|
||||
}
|
||||
|
||||
space+ { goto scan; }
|
||||
|
||||
eol { if(cursor == eof) RETURN(0);
|
||||
pos = cursor; cline++;
|
||||
goto scan;
|
||||
}
|
||||
|
||||
any { std::ostringstream msg;
|
||||
msg << "unexpected character: ";
|
||||
prtChOrHex(msg, *tok);
|
||||
fatal(msg.str().c_str());
|
||||
goto scan;
|
||||
}
|
||||
*/
|
||||
|
||||
code:
|
||||
/*!re2c
|
||||
"}" { if(--depth == 0){
|
||||
cur = cursor;
|
||||
yylval.token = new Token(token(), tline);
|
||||
return CODE;
|
||||
}
|
||||
goto code; }
|
||||
"{" { ++depth;
|
||||
goto code; }
|
||||
"\n" { if(cursor == eof) fatal("missing '}'");
|
||||
pos = cursor; cline++;
|
||||
goto code;
|
||||
}
|
||||
zero { if(cursor == eof) {
|
||||
if (depth) fatal("missing '}'");
|
||||
RETURN(0);
|
||||
}
|
||||
goto code;
|
||||
}
|
||||
dstring | sstring | any { goto code; }
|
||||
*/
|
||||
|
||||
comment:
|
||||
/*!re2c
|
||||
"*/" { if(--depth == 0)
|
||||
goto scan;
|
||||
else
|
||||
goto comment; }
|
||||
"/*" { ++depth;
|
||||
fatal("ambiguous /* found");
|
||||
goto comment; }
|
||||
"\n" { if(cursor == eof) RETURN(0);
|
||||
tok = pos = cursor; cline++;
|
||||
goto comment;
|
||||
}
|
||||
any { if(cursor == eof) RETURN(0);
|
||||
goto comment; }
|
||||
*/
|
||||
|
||||
config:
|
||||
/*!re2c
|
||||
space+ { goto config; }
|
||||
"=" space* { iscfg = 2;
|
||||
cur = cursor;
|
||||
RETURN('=');
|
||||
}
|
||||
any { fatal("missing '='"); }
|
||||
*/
|
||||
|
||||
value:
|
||||
/*!re2c
|
||||
number { cur = cursor;
|
||||
yylval.number = atoi(token().to_string().c_str());
|
||||
iscfg = 0;
|
||||
return NUMBER;
|
||||
}
|
||||
value { cur = cursor;
|
||||
yylval.str = new Str(token());
|
||||
iscfg = 0;
|
||||
return VALUE;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Scanner::fatal(uint ofs, const char *msg) const
|
||||
{
|
||||
out.flush();
|
||||
#ifdef _MSC_VER
|
||||
std::cerr << filename << "(" << tline << "): error : "
|
||||
<< "column " << (tchar + ofs + 1) << ": "
|
||||
<< msg << std::endl;
|
||||
#else
|
||||
std::cerr << "re2c: error: "
|
||||
<< "line " << tline << ", column " << (tchar + ofs + 1) << ": "
|
||||
<< msg << std::endl;
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Scanner::~Scanner()
|
||||
{
|
||||
|
@ -376,6 +376,6 @@ Scanner::~Scanner()
|
|||
delete [] bot;
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace re2c
|
||||
|
||||
|
||||
} // end namespace re2c
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Author: Marcus Boerger <helly@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
/* $Id: stream_lc.h,v 1.10 2006/02/26 20:36:09 helly Exp $ */
|
||||
/* $Id: stream_lc.h 767 2007-06-26 15:21:10Z helly $ */
|
||||
|
||||
#ifndef _stream_lc_h
|
||||
#define _stream_lc_h
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: substr.cc,v 1.11 2006/02/26 20:30:54 helly Exp $ */
|
||||
/* $Id: substr.cc 546 2006-05-25 13:40:14Z helly $ */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "substr.h"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: substr.h,v 1.10 2006/01/01 13:42:10 helly Exp $ */
|
||||
/* $Id: substr.h 530 2006-05-25 13:34:33Z helly $ */
|
||||
#ifndef _substr_h
|
||||
#define _substr_h
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: token.h,v 1.4 2004/11/01 04:35:57 nuffer Exp $ */
|
||||
/* $Id: token.h 547 2006-05-25 13:40:35Z helly $ */
|
||||
#ifndef _token_h
|
||||
#define _token_h
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: translate.cc,v 1.5 2005/12/28 18:33:37 helly Exp $ */
|
||||
/* $Id: translate.cc 713 2007-04-29 15:33:47Z helly $ */
|
||||
#include "globals.h"
|
||||
|
||||
namespace re2c
|
||||
|
|
|
@ -250,7 +250,7 @@ int main (int argc, char **argv)
|
|||
printf ("Usage: %s <source file> <output file>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
#if !defined(NDEBUG) && 1
|
||||
#if !defined(NDEBUG) && 0
|
||||
ParseTrace(fopen("trace.txt", "w"), ":");
|
||||
#endif
|
||||
IncludeFile (argv[1]);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -10,27 +10,28 @@
|
|||
#define SYMNUM 10
|
||||
#define LPAREN 11
|
||||
#define RPAREN 12
|
||||
#define PRINT 13
|
||||
#define COMMA 14
|
||||
#define STRING 15
|
||||
#define ENDL 16
|
||||
#define DEFINE 17
|
||||
#define SYM 18
|
||||
#define INCLUDE 19
|
||||
#define RBRACE 20
|
||||
#define ENUM 21
|
||||
#define LBRACE 22
|
||||
#define EQUALS 23
|
||||
#define SPECIAL 24
|
||||
#define SEMICOLON 25
|
||||
#define COLON 26
|
||||
#define LBRACKET 27
|
||||
#define RBRACKET 28
|
||||
#define FLAGS 29
|
||||
#define ARG2 30
|
||||
#define ARG3 31
|
||||
#define ARG4 32
|
||||
#define ARG5 33
|
||||
#define OR_EQUAL 34
|
||||
#define TAG 35
|
||||
#define LINEID 36
|
||||
#define NOP 13
|
||||
#define PRINT 14
|
||||
#define COMMA 15
|
||||
#define STRING 16
|
||||
#define ENDL 17
|
||||
#define DEFINE 18
|
||||
#define SYM 19
|
||||
#define INCLUDE 20
|
||||
#define RBRACE 21
|
||||
#define ENUM 22
|
||||
#define LBRACE 23
|
||||
#define EQUALS 24
|
||||
#define SPECIAL 25
|
||||
#define SEMICOLON 26
|
||||
#define COLON 27
|
||||
#define LBRACKET 28
|
||||
#define RBRACKET 29
|
||||
#define FLAGS 30
|
||||
#define ARG2 31
|
||||
#define ARG3 32
|
||||
#define ARG4 33
|
||||
#define ARG5 34
|
||||
#define OR_EQUAL 35
|
||||
#define TAG 36
|
||||
#define LINEID 37
|
||||
|
|
|
@ -243,10 +243,33 @@ void yyparse (void)
|
|||
void *pParser = ParseAlloc (malloc);
|
||||
YYSTYPE token;
|
||||
int tokentype;
|
||||
int include_state = 0;
|
||||
|
||||
while ((tokentype = yylex(&token)) != 0)
|
||||
{
|
||||
/* Whenever the sequence INCLUDE STRING is encountered in the token
|
||||
* stream, feed a dummy NOP token to the parser so that it will
|
||||
* reduce the include_statement before grabbing any more tokens
|
||||
* from the current file.
|
||||
*/
|
||||
if (tokentype == INCLUDE && include_state == 0)
|
||||
{
|
||||
include_state = 1;
|
||||
}
|
||||
else if (tokentype == STRING && include_state == 1)
|
||||
{
|
||||
include_state = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
include_state = 0;
|
||||
}
|
||||
Parse (pParser, tokentype, token);
|
||||
if (include_state == 2)
|
||||
{
|
||||
include_state = 0;
|
||||
Parse (pParser, NOP, token);
|
||||
}
|
||||
}
|
||||
memset (&token, 0, sizeof(token));
|
||||
Parse (pParser, 0, token);
|
||||
|
@ -354,7 +377,7 @@ exp(A) ::= MINUS exp(B). [NEG] { A = -B; }
|
|||
exp(A) ::= LPAREN exp(B) RPAREN. { A = B; }
|
||||
|
||||
translation_unit ::= . /* empty */
|
||||
translation_unit ::= external_declaration.
|
||||
translation_unit ::= translation_unit external_declaration.
|
||||
|
||||
external_declaration ::= define_statement.
|
||||
external_declaration ::= include_statement.
|
||||
|
@ -363,6 +386,7 @@ external_declaration ::= enum_statement.
|
|||
external_declaration ::= linetype_declaration.
|
||||
external_declaration ::= boom_declaration.
|
||||
external_declaration ::= special_declaration.
|
||||
external_declaration ::= NOP.
|
||||
|
||||
print_statement ::= PRINT LPAREN print_list RPAREN.
|
||||
{
|
||||
|
|
Binary file not shown.
BIN
wadsrc/doomx.lmp
BIN
wadsrc/doomx.lmp
Binary file not shown.
BIN
wadsrc/foo
BIN
wadsrc/foo
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -3696,7 +3696,7 @@
|
|||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="Creating $(InputName).h from src/$(InputFileName)"
|
||||
CommandLine="tools\re2c\re2c -s -o "src/$(InputName).h" "src/$(InputFileName)"
"
|
||||
CommandLine="tools\re2c\re2c --no-generation-date -s -o "src/$(InputName).h" "src/$(InputFileName)"
"
|
||||
Outputs=""src/$(InputName).h""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
|
@ -3716,7 +3716,7 @@
|
|||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="Creating $(InputName).h from src/$(InputFileName)"
|
||||
CommandLine="tools\re2c\re2c -s -o "src/$(InputName).h" "src/$(InputFileName)"
"
|
||||
CommandLine="tools\re2c\re2c --no-generation-date -s -o "src/$(InputName).h" "src/$(InputFileName)"
"
|
||||
Outputs=""src/$(InputName).h""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
|
|
Loading…
Reference in a new issue