Example #1
0
static int DaoParser_FindPair( DaoParser *self,  const char *lw, const char *rw, int start, int to )
{
	DaoToken **tokens = self->tokens->items.pToken;
	int i, k = 0;
	int found = 0;

	if( start < 0 ) goto ErrorUnPaired;
	if( to < 0 ) to = self->tokens->size - 1;
	for(i=start; i<=to; ++i){
		if( strcmp( lw, tokens[i]->string.mbs ) == 0 ){
			k++;
		}else if( strcmp( rw, tokens[i]->string.mbs ) == 0 ){
			k--;
			found = 1;
		}
		if( k == 0 && found ) return i;
	}
ErrorUnPaired:
	if( self->vmSpace ){
		DString_SetMBS( self->mbs, lw );
		if( k ==0 ){
			DaoParser_Error( self, DAO_TOKEN_NOT_FOUND, self->mbs );
		}else{
			DString_AppendChar( self->mbs, ' ' );
			DString_AppendMBS( self->mbs, rw );
			DaoParser_Error( self, DAO_TOKENS_NOT_PAIRED, self->mbs );
		}
	}
	return -100;
}
Example #2
0
static int DaoParser_MacroApply( DaoParser *self, DArray *tokens,
		DMacroGroup *group, DMap *tokMap, DMap *used,
		int level, DString *tag, int pos0, int adjust )
{
	DMacroUnit **units = (DMacroUnit**) group->units->items.pVoid;
	DMacroUnit  *unit;
	DMacroGroup *grp;
	DMacroNode *node, *node2;
	DArray *toks = DArray_New(D_TOKEN);
	DaoToken *tk = DaoToken_New();
	DaoToken *tt = NULL;
	DNode  *kwnode = NULL;
	DMap *check = NULL;
	DMap one = { NULL, 0, 0, 0 };
	int M, N = group->units->size;
	int i, j, gid = -1;
	int repeated = 0;
	int start_mbs = -1;
	int start_wcs = -1;
	int squote, dquote;

	if( group->repeat != DMACRO_AUTO ) level ++;

	for( i=0; i<N; i++ ){
		unit = units[i];
		if( tokens->size >0 ) pos0 = tokens->items.pToken[ tokens->size -1 ]->line;
		self->curLine = pos0;
		/*
		   printf( "apply unit %i: %i\n", i, unit->type );
		 */
		switch( unit->type ){
		case DMACRO_TOK :
			squote = unit->marker->type == DTOK_ESC_SQUO;
			dquote = unit->marker->type == DTOK_ESC_DQUO;
			if( (squote && start_mbs >=0) || (dquote && start_wcs >=0) ){
				int qstart = squote ? start_mbs : start_wcs;
				tt = tokens->items.pToken[ qstart ];
				for(j=qstart+1,M=tokens->size; j<M; j++){
					DaoToken *jtok = tokens->items.pToken[j];
					int t = j ? tokens->items.pToken[j-1]->type : 0;
					if( t == DTOK_IDENTIFIER && jtok->type == t )
						DString_AppendChar( & tt->string, ' ' );
					DString_Append( & tt->string, & jtok->string );
				}
				if( squote ){
					DString_AppendChar( & tt->string, '\'' );
					DArray_Erase( tokens, start_mbs+1, tokens->size );
				}else{
					DString_AppendChar( & tt->string, '\"' );
					DArray_Erase( tokens, start_wcs+1, tokens->size );
				}
				start_mbs = -1;
				break;
			}else if( squote ){
				start_mbs = tokens->size;
				DArray_Append( tokens, unit->marker );
				tt = tokens->items.pToken[ start_mbs ];
				tt->type = tt->name = DTOK_MBS;
				DString_SetMBS( & tt->string, "\'" );
				break;
			}else if( dquote ){
				start_wcs = tokens->size;
				DArray_Append( tokens, unit->marker );
				tt = tokens->items.pToken[ start_wcs ];
				tt->type = tt->name = DTOK_WCS;
				DString_SetMBS( & tt->string, "\"" );
				break;
			}
			DArray_Append( tokens, unit->marker );
			tokens->items.pToken[ tokens->size-1 ]->cpos += adjust;
			break;
		case DMACRO_VAR :
			DaoToken_Assign( tk, unit->marker );
			DString_Append( & tk->string, tag );
			DArray_Append( tokens, tk );
			break;
		case DMACRO_EXP :
		case DMACRO_ID :
		case DMACRO_OP :
		case DMACRO_BL :
		case DMACRO_IBL :

			kwnode = MAP_Find( tokMap, & unit->marker->string );
			if( kwnode ==NULL ){
				DaoParser_Error( self, DAO_CTW_UNDEF_MAC_MARKER, & unit->marker->string );
				goto Failed;
			}
			node = (DMacroNode*) kwnode->value.pVoid;
			kwnode = MAP_Find( used, unit );
			if( kwnode == NULL ){
				DMap_Insert( used, unit, & one );
				kwnode = MAP_Find( used, unit );
			}
			check = (DMap*) kwnode->value.pVoid;
			repeated = 1;

			/*
			   printf( ">>>\n%s level %i: \n", unit->marker->string.mbs, level );
			   DMacroNode_Print( node );
			   printf( "\n" );
			 */
			/* search a leaf */
			node2 = DMacroNode_FindLeaf( node, check, level );
			if( node2 ){
				/*
				   printf( "appending tokens\n" );
				   DMacroNode_Print( node2 );
				   printf( "\n" );
				 */
				DArray_InsertArray( tokens, tokens->size, node2->leaves, 0, -1 );
				DMap_Insert( check, node2, NULL );
				/* DArray_Clear( node2->leaves ); */
			}else{
				DMacroNode_RemoveEmptyLeftBranch( node, level );
				goto Failed;
			}
			break;
		case DMACRO_GRP :
		case DMACRO_ALT :
			grp = (DMacroGroup*) unit;
			DArray_Clear( toks );
			j = DaoParser_MacroApply( self, toks, grp, tokMap, used, level, tag, pos0, adjust );
			switch( grp->repeat ){
			case DMACRO_AUTO :
			case DMACRO_ONE :
				if( j <0 && group->type != DMACRO_ALT ) goto Failed;
				repeated = (j>0);
				if( j >=0 ){
					gid = i;
					DArray_InsertArray( tokens, tokens->size, toks, 0, -1 );
				}
				break;
			case DMACRO_ZERO_OR_ONE :
				gid = i;
				repeated = (j>0);
				if( j >=0 ){
					DArray_InsertArray( tokens, tokens->size, toks, 0, -1 );
				}
				break;
			case DMACRO_ZERO_OR_MORE :
				gid = i;
				repeated = (j>0);
				if( j >=0 ){
					DArray_InsertArray( tokens, tokens->size, toks, 0, -1 );
				}
				while( j >0 ){
					DArray_Clear( toks );
					j = DaoParser_MacroApply( self, toks, grp, tokMap, used, level, tag, pos0, adjust );
					if( j >0 ){
						DArray_InsertArray( tokens, tokens->size, toks, 0, -1 );
					}
				}
				break;
			case DMACRO_ONE_OR_MORE :
				if( j <0 && group->type != DMACRO_ALT ) goto Failed;
				repeated = (j>0);
				if( j >=0 ){
					DArray_InsertArray( tokens, tokens->size, toks, 0, -1 );
				}

				while( j >0 ){
					gid = i;
					DArray_Clear( toks );
					j = DaoParser_MacroApply( self, toks, grp, tokMap, used, level, tag, pos0, adjust );
					if( j >0 ){
						DArray_InsertArray( tokens, tokens->size, toks, 0, -1 );
					}
				}
				break;
			}
			break;
		default : goto Failed;
		}
		if( group->type == DMACRO_ALT && gid >=0 ) break;
	}
	if( group->repeat != DMACRO_AUTO ) level --;
	if( group->type == DMACRO_ALT && gid <0 ) goto Failed;
	DaoToken_Delete( tk );
	DArray_Delete( toks );
	return repeated;
Failed :
	DaoToken_Delete( tk );
	DArray_Delete( toks );
	return -1;
}
Example #3
0
int DaoParser_ParseMacro( DaoParser *self, int start )
{
	int rb1, rb2, i = start, N = self->tokens->size;
	DaoToken **toks = self->tokens->items.pToken;
	DaoMacro *macro;
	DString *lang = NULL;
	DArray  *stops;
	DMap  *markers;

	if( start + 5 >= N ) return -1;
	if( toks[start+1]->type != DTOK_LCB ){
		lang = & toks[start+1]->string;
		if( toks[start+1]->type != DTOK_IDENTIFIER ){
			DaoParser_Error( self, DAO_TOKEN_NEED_NAME, lang );
			return -1;
		}
		if( lang->size == 3 && strcmp( lang->mbs, "dao" ) == 0 ){
			DaoParser_Error( self, DAO_TOKEN_NEED_NAME, lang );
			return -1;
		}
		start += 1;
	}
	if( toks[start+1]->name != DTOK_LCB ) return -1;

	self->curLine = toks[start]->line;
	rb1 = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, start, -1 );
	if( rb1 <0 || rb1 +3 >= N ) return -1;
	if( toks[rb1+1]->name != DKEY_AS || toks[rb1+2]->name != DTOK_LCB ){
		DaoParser_Error( self, DAO_CTW_INV_MAC_DEFINE, NULL );
		return -1;
	}
	rb2 = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, rb1 + 1, -1 );
	if( rb2 <0 ) return -1;

	/*
	   for( i=start; i<rb2; i++ ) printf( "%s  ", toks[i]->string.mbs ); printf("\n");
	 */

	macro = DaoMacro_New();

	if( DaoParser_MakeMacroGroup( self, macro->macroMatch, macro->macroMatch, start+2, rb1 ) ==0 ){
		DaoMacro_Delete( macro );
		return -1;
	}
	if( macro->macroMatch->units->size >0 ){
		DMacroUnit *unit = (DMacroUnit*) macro->macroMatch->units->items.pVoid[0];
		if( unit->type != DMACRO_TOK )
			DaoParser_Error( self, DAO_CTW_INV_MAC_FIRSTOK, & toks[i]->string );
	}
	if( toks[rb1+3]->line != toks[rb1+2]->line ) macro->macroApply->cpos = toks[rb1+3]->cpos;
	if( DaoParser_MakeMacroGroup( self, macro->macroApply, macro->macroApply, rb1+3, rb2 ) ==0 ){
		DaoMacro_Delete( macro );
		return -1;
	}
	markers = DMap_New(D_STRING,0);

	for(i=start+2; i<rb1; i++){
		if( toks[i]->string.mbs[0] == '$' ){
			if( MAP_Find( markers, & toks[i]->string ) != NULL ){
				self->curLine = toks[i]->line;
				DaoParser_Error( self, DAO_CTW_REDEF_MAC_MARKER, & toks[i]->string );
				return 0;
			}
			MAP_Insert( markers, & toks[i]->string, 0 );
		}
	}
	DMap_Clear( markers );
	i = rb1+3;
	if( DString_EQ( & toks[start+2]->string, & toks[rb1+3]->string ) ) i ++;
	while( i < rb2 ){
		char ch = toks[i]->string.mbs[0];
		if( ch != '$' && ch != '\\' && ch != '\'' ){
			if( MAP_Find( markers, & toks[i]->string ) == NULL ){
				DArray_Append( macro->keyListApply, & toks[i]->string );
				MAP_Insert( markers, & toks[i]->string, 0 );
			}
		}
		i ++;
	}

	stops = DArray_New(D_TOKEN);
	DMacroGroup_SetStop( macro->macroMatch, stops );
	DMacroGroup_FindVariables( macro->macroMatch );
	DArray_Clear( stops );
	DMacroGroup_SetStop( macro->macroApply, stops );
	DaoNamespace_AddMacro( self->nameSpace, lang, & toks[start+2]->string, macro );
	DArray_Delete( stops );
	DMap_Delete( markers );
	return rb2;
}
Example #4
0
static int DaoParser_MakeMacroGroup( DaoParser *self,
		DMacroGroup *group, DMacroGroup *parent, int from, int to )
{
	DaoToken **toks = self->tokens->items.pToken;
	unsigned char tk;
	int i, sep, rb, prev;
	DMacroUnit *unit;
	DMacroGroup *grp, *group2; /* mingw don't like grp2 ?! */

	/*
	   for( i=from; i<to; i++ ) printf( "%s  ", toks[i]->mbs ); printf("\n");
	 */

	i = from;
	while( i < to ){
		char *chs = toks[i]->string.mbs;
		self->curLine = toks[i]->line;
		tk = toks[i]->name;
#if 0
		//printf( "%i %s\n", i, chs );
#endif
		if( tk == DTOK_ESC_LB || tk == DTOK_ESC_LSB || tk == DTOK_ESC_LCB ){
			grp = DMacroGroup_New();
			grp->cpos = toks[i]->cpos;
			grp->parent = parent;
			DArray_Append( group->units, (void*)grp );
			switch( tk ){
			case DTOK_ESC_LB :
				rb = DaoParser_FindPairToken( self, DTOK_ESC_LB, DTOK_ESC_RB, i, to );
				break;
			case DTOK_ESC_LSB :
				rb = DaoParser_FindPairToken( self, DTOK_ESC_LSB, DTOK_ESC_RSB, i, to );
				grp->repeat = DMACRO_ZERO_OR_ONE;
				break;
			case DTOK_ESC_LCB :
				rb = DaoParser_FindPairToken( self, DTOK_ESC_LCB, DTOK_ESC_RCB, i, to );
				grp->repeat = DMACRO_ZERO_OR_MORE;
				break;
			default :
				{
					rb = -1;
					DaoParser_Error( self, DAO_CTW_INV_MAC_OPEN, & toks[i]->string );
					break;
				}
			}
			if( rb <0 ) return 0;

			prev = i+1;
			sep = DaoParser_FindOpenToken( self, DTOK_ESC_PIPE, i+1, rb, 0 );
			if( sep >=0 ){
				while( sep >=0 ){
					group2 = DMacroGroup_New();
					group2->parent = grp;
					if( DaoParser_MakeMacroGroup( self, group2, group2, prev, sep ) == 0 )
						return 0;
					DArray_Append( grp->units, (void*)group2 );
					prev = sep +1;
					sep = DaoParser_FindOpenToken( self, DTOK_ESC_PIPE, prev, rb, 0 );
					if( prev < rb && sep <0 ) sep = rb;
				}
				grp->type = DMACRO_ALT;
			}else if( DaoParser_MakeMacroGroup( self, grp, grp, i+1, rb ) == 0 ){
				return 0;
			}
			i = rb +1;
			self->curLine = toks[i]->line;
			if( toks[i]->string.mbs[0] == '\\' ){
				switch( toks[i]->name ){
				case DTOK_ESC_EXCLA : grp->repeat = DMACRO_ZERO; i++; break;
				case DTOK_ESC_QUES  : grp->repeat = DMACRO_ZERO_OR_ONE; i++; break;
				case DTOK_ESC_STAR  : grp->repeat = DMACRO_ZERO_OR_MORE; i++; break;
				case DTOK_ESC_PLUS  : grp->repeat = DMACRO_ONE_OR_MORE; i++; break;
				case DTOK_ESC_SQUO : case DTOK_ESC_DQUO :
				case DTOK_ESC_LB :  case DTOK_ESC_RB :
				case DTOK_ESC_LCB : case DTOK_ESC_RCB :
				case DTOK_ESC_LSB : case DTOK_ESC_RSB : break;
				default : DaoParser_Error( self, DAO_CTW_INV_MAC_REPEAT, & toks[i]->string );
						  return 0;
				}
			}
			continue;
		}

		self->curLine = toks[i]->line;
		unit  = DMacroUnit_New();
		DaoToken_Assign( unit->marker, toks[i] );
		DArray_Append( group->units, (void*)unit );
		switch( chs[0] ){
		case '$' :
			if( DString_FindMBS( & toks[i]->string, "EXP", 0 ) == 1 ){
				unit->type = DMACRO_EXP;
			}else if( DString_FindMBS( & toks[i]->string, "VAR", 0 ) == 1 ){
				unit->type = DMACRO_VAR;
			}else if( DString_FindMBS( & toks[i]->string, "ID", 0 ) == 1 ){
				unit->type = DMACRO_ID;
			}else if( DString_FindMBS( & toks[i]->string, "OP", 0 ) == 1 ){
				unit->type = DMACRO_OP;
			}else if( DString_FindMBS( & toks[i]->string, "BL", 0 ) == 1 ){
				unit->type = DMACRO_BL;
			}else if( DString_FindMBS( & toks[i]->string, "IBL", 0 ) == 1 ){
				unit->type = DMACRO_IBL;
			}
			break;
		case '(' :
		case '[' :
		case '{' :
			switch( chs[0] ){
			case '(' :
				rb = DaoParser_FindPairToken( self, DTOK_LB, DTOK_RB, i, to );
				break;
			case '[' :
				rb = DaoParser_FindPairToken( self, DTOK_LSB, DTOK_RSB, i, to );
				break;
			case '{' :
				rb = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, i, to );
				break;
			default : rb = -1;
			}
			if( rb <0 ) return 0;

			grp = DMacroGroup_New();
			grp->parent = group;
			grp->repeat = DMACRO_AUTO;
			DArray_Append( group->units, (void*)grp );
			if( DaoParser_MakeMacroGroup( self, grp, parent, i+1, rb ) == 0 ) return 0;
			i = rb;
			continue;
		case '\'' :
			if( chs[2] == '\'' ){
				unit->marker->type = 0;
				switch( chs[1] ){
				case '(' : unit->marker->type = unit->marker->name = DTOK_LB; break;
				case ')' : unit->marker->type = unit->marker->name = DTOK_RB; break;
				case '[' : unit->marker->type = unit->marker->name = DTOK_LSB; break;
				case ']' : unit->marker->type = unit->marker->name = DTOK_RSB; break;
				case '{' : unit->marker->type = unit->marker->name = DTOK_LCB; break;
				case '}' : unit->marker->type = unit->marker->name = DTOK_RCB; break;
				case '\'' : unit->marker->type= unit->marker->name = DTOK_ESC_SQUO;break;
							case '\"' : unit->marker->type= unit->marker->name = DTOK_ESC_DQUO;break;
				default : break;
				}
				if( unit->marker->type == 0 ){
					DaoParser_Error( self, DAO_CTW_INV_MAC_SPECTOK, & toks[i]->string );
					return 0;
				}
				unit->type = DMACRO_BR;
				DString_SetMBS( & unit->marker->string, chs+1 );
				DString_Erase( & unit->marker->string, unit->marker->string.size-1, 1 );
			}
		default : break;
		}
		if( i+1 < to && toks[i+1]->string.mbs[0] == '@' ){
			char ch = toks[i+1]->string.mbs[1];
			if( ch != '@' ){
				if( toks[i+1]->string.size != 2 || ch < '1' || ch >'9' ){
					DaoParser_Error( self, DAO_CTW_INV_MAC_INDENT, & toks[i+1]->string );
					return 0;
				}
				unit->indent = ch - '0';
				i ++;
			}
		}
		i ++;
	}
	return 1;
}
Example #5
0
int DaoParser_ParseMacro( DaoParser *self, int start )
{
	int rb1, rb2, i = start, N = self->tokens->size;
	DaoToken **toks = self->tokens->items.pToken;
	DMacroUnit *first;
	DaoMacro *macro;
	DString *lang = NULL;
	DArray  *stops;
	DMap  *markers;
	DNode *it;

	if( start + 5 >= N ) return -1;
	if( toks[start+1]->type != DTOK_LCB ){
		lang = & toks[start+1]->string;
		if( toks[start+1]->type != DTOK_IDENTIFIER ){
			DaoParser_Error( self, DAO_TOKEN_NEED_NAME, lang );
			return -1;
		}
		if( lang->size == 3 && strcmp( lang->mbs, "dao" ) == 0 ){
			DaoParser_Error( self, DAO_TOKEN_NEED_NAME, lang );
			return -1;
		}
		start += 1;
	}
	if( toks[start+1]->name != DTOK_LCB ) return -1;

	self->curLine = toks[start]->line;
	rb1 = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, start, -1 );
	if( rb1 <0 || rb1 +3 >= N ) return -1;
	if( toks[rb1+1]->name != DKEY_AS || toks[rb1+2]->name != DTOK_LCB ){
		DaoParser_Error( self, DAO_CTW_INV_MAC_DEFINE, NULL );
		return -1;
	}
	rb2 = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, rb1 + 1, -1 );
	if( rb2 <0 ) return -1;

	/*
	   for( i=start; i<rb2; i++ ) printf( "%s  ", toks[i]->string.mbs ); printf("\n");
	 */

	macro = DaoMacro_New();
	markers = DMap_New(D_STRING,0);

	if( DaoParser_MakeMacroGroup( self, macro->macroMatch, macro->macroMatch, start+2, rb1, markers, NULL ) ==0 ){
		goto Error;
	}
	if( macro->macroMatch->units->size == 0 ) goto Error;
	first = (DMacroUnit*) macro->macroMatch->units->items.pVoid[0];
	if( first->type != DMACRO_TOK ){
		DaoParser_Error( self, DAO_CTW_INV_MAC_FIRSTOK, & toks[i]->string );
		goto Error;
	}
	for(it=DMap_First(markers); it; it=DMap_Next(markers,it)){
		if( it->value.pInt > 1 ){
			DaoParser_Error( self, DAO_CTW_REDEF_MAC_MARKER, it->key.pString );
			goto Error;
		}
	}

	DMap_Clear( markers );
	if( toks[rb1+3]->line != toks[rb1+2]->line ) macro->macroApply->cpos = toks[rb1+3]->cpos;
	if( DaoParser_MakeMacroGroup( self, macro->macroApply, macro->macroApply, rb1+3, rb2, NULL, markers ) ==0 ){
		goto Error;
	}
	for(it=DMap_First(markers); it; it=DMap_Next(markers,it)){
		DArray_Append( macro->keyListApply, it->key.pString );
	}

	stops = DArray_New(D_TOKEN);
	DMacroGroup_SetStop( macro->macroMatch, stops );
	DMacroGroup_FindVariables( macro->macroMatch );
	DArray_Clear( stops );
	DMacroGroup_SetStop( macro->macroApply, stops );
	DaoNamespace_AddMacro( self->nameSpace, lang, & first->marker->string, macro );
	DArray_Delete( stops );
	DMap_Delete( markers );
	return rb2;
Error:
	DaoMacro_Delete( macro );
	DMap_Delete( markers );
	return -1;
}
Example #6
0
static int DaoParser_MakeMacroGroup( DaoParser *self, DMacroGroup *group, DMacroGroup *parent, int from, int to, DMap *vars, DMap *markers )
{
	unsigned char tk;
	int i, sep, rb, prev;
	DaoToken **toks = self->tokens->items.pToken;
	DMacroGroup *grp, *group2; /* mingw don't like grp2 ?! */
	DMacroUnit *unit;
	DNode *it;

	/*
	   for( i=from; i<to; i++ ) printf( "%s  ", toks[i]->mbs ); printf("\n");
	 */

	i = from;
	while( i < to ){
		DaoToken *tok = toks[i];
		char *chs = tok->string.mbs;
		int tk = tok->name;

#if 0
		printf( "%i %s\n", i, chs );
#endif
		self->curLine = tok->line;
		if( tk == DTOK_LB || tk == DTOK_LSB || tk == DTOK_LCB ){
			grp = DMacroGroup_New();
			grp->cpos = tok->cpos;
			grp->parent = parent;
			DArray_Append( group->units, (void*)grp );
			switch( tk ){
			case DTOK_LB :
				rb = DaoParser_FindPairToken( self, DTOK_LB, DTOK_RB, i, to );
				break;
			case DTOK_LSB :
				rb = DaoParser_FindPairToken( self, DTOK_LSB, DTOK_RSB, i, to );
				grp->repeat = DMACRO_ZERO_OR_ONE;
				break;
			case DTOK_LCB :
				rb = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, i, to );
				grp->repeat = DMACRO_ZERO_OR_MORE;
				break;
			default :
				rb = -1;
				DaoParser_Error( self, DAO_CTW_INV_MAC_OPEN, & tok->string );
				break;
			}
			if( rb <0 ) return 0;

			prev = i+1;
			sep = DaoParser_FindOpenToken( self, DTOK_PIPE, i+1, rb, 0 );
			if( sep >=0 ){
				while( sep >=0 ){
					group2 = DMacroGroup_New();
					group2->parent = grp;
					if( DaoParser_MakeMacroGroup( self, group2, group2, prev, sep, vars, markers ) == 0 )
						return 0;
					DArray_Append( grp->units, (void*)group2 );
					prev = sep +1;
					sep = DaoParser_FindOpenToken( self, DTOK_PIPE, prev, rb, 0 );
					if( prev < rb && sep <0 ) sep = rb;
				}
				grp->type = DMACRO_ALT;
			}else if( DaoParser_MakeMacroGroup( self, grp, grp, i+1, rb, vars, markers ) == 0 ){
				return 0;
			}
			i = rb +1;
			tok = toks[i];
			self->curLine = tok->line;
			switch( tok->name ){
			case DTOK_NOT   : grp->repeat = DMACRO_ZERO; i++; break;
			case DTOK_QUERY : grp->repeat = DMACRO_ZERO_OR_ONE; i++; break;
			case DTOK_MUL   : grp->repeat = DMACRO_ZERO_OR_MORE; i++; break;
			case DTOK_ADD   : grp->repeat = DMACRO_ONE_OR_MORE; i++; break;
			default : break;
			}
			continue;
		}

		self->curLine = tok->line;
		unit = DMacroUnit_New();
		DaoToken_Assign( unit->marker, tok );
		DArray_Append( group->units, (void*)unit );
		if( chs[0] == '$' ){
			if( DString_FindMBS( & tok->string, "EXP", 0 ) == 1 ){
				unit->type = DMACRO_EXP;
			}else if( DString_FindMBS( & tok->string, "VAR", 0 ) == 1 ){
				unit->type = DMACRO_VAR;
			}else if( DString_FindMBS( & tok->string, "ID", 0 ) == 1 ){
				unit->type = DMACRO_ID;
			}else if( DString_FindMBS( & tok->string, "OP", 0 ) == 1 ){
				unit->type = DMACRO_OP;
			}else if( DString_FindMBS( & tok->string, "BL", 0 ) == 1 ){
				unit->type = DMACRO_BL;
			}else{
				DaoParser_Error( self, DAO_CTW_INV_MAC_SPECTOK, & tok->string );
				return 0;
			}
			if( vars != NULL ){
				it = DMap_Find( vars, & unit->marker->string );
				if( it == NULL ) it = DMap_Insert( vars, & unit->marker->string, 0 );
				it->value.pInt += 1;
			}
		}else if( tk == DTOK_MBS ){
			DaoLexer_Reset( self->wlexer );
			DaoLexer_Tokenize( self->wlexer, chs + 1, 0 );
			if( self->wlexer->tokens->size == 2 ){
				DaoToken_Assign( unit->marker, self->wlexer->tokens->items.pToken[0] );
				if( markers != NULL ){
					it = DMap_Find( markers, & unit->marker->string );
					if( it == NULL ) it = DMap_Insert( markers, & unit->marker->string, 0 );
					it->value.pInt += 1;
				}
			}
			DaoLexer_Reset( self->wlexer );

			rb = -1;
			if( tok->string.size == 3 ){
				switch( chs[1] ){
				case '(': rb = DaoParser_FindPair( self, "'('", "')'", i, to ); break;
				case '[': rb = DaoParser_FindPair( self, "'['", "']'", i, to ); break;
				case '{': rb = DaoParser_FindPair( self, "'{'", "'}'", i, to ); break;
				default : break;
				}
			}
			if( rb >= 0 ){
				grp = DMacroGroup_New();
				grp->parent = group;
				grp->repeat = DMACRO_AUTO;
				DArray_Append( group->units, (void*)grp );
				if( DaoParser_MakeMacroGroup( self, grp, parent, i+1, rb, vars, markers ) == 0 ) return 0;
				i = rb;
				continue;
			}
		}
		i ++;
	}
	return 1;
}