Beispiel #1
0
//音声認識ルールを登録する部分の詳細な実行です。正規表現のネストがあるので再起してます。
xreturn::r<bool> JuliusPlus::AddRegexpImpl(const CallbackDataStruct & callback,const std::string & str, JuliusPlusRule*  stateHandle)
{
	//	_USE_WINDOWS_ENCODING;
	std::string matchString;

	//正規表現をパースしながら回す.
	const char * p = str.c_str();
	const char * splitPos = p;
	JuliusPlusRule*  currentRule = stateHandle;
	for(  ; *p ; ++p )
	{
#ifdef _WINDOWS_
		if ( issjiskanji(*p) )
		{
			p ++;
			continue;
		}
#endif
		if (*p == '(')
		{
			//閉じ括弧まで飛ばす. )
			int nest = 1;
			const char* n = p + 1;
			for( ; *n  ; ++n )
			{
#ifdef _WINDOWS_
				if ( issjiskanji(*n) )
				{
					n ++;
					continue;
				}
#endif
				if (*n == '(')
				{
					++nest ;
				}
				else if (*n == ')')
				{
					--nest ;
					if (nest <= 0)
					{
						break;
					}
				}
			}

			//ネストする前の部分
			matchString = std::string(splitPos, 0 ,p - splitPos);


			//ネストしている部分を格納するルールを作る.
			JuliusPlusRule*  nestRule;

			//お目当ての()ネストを格納する部分を作る
			//キャプチャー?
			if (*(p+1) == '?' && *(p+2) == ':')
			{
				nestRule = new JuliusPlusRule(callback);
			}
			else
			{
				nestRule = new JuliusPlusRule( this->LocalCaptureRuleNodeCount++ , callback);
			}

			if (matchString.empty())
			{//先行文字列が空
				currentRule->AddNestRule(nestRule);
			}
			else
			{//文字列だけを入れると OR扱いになってしまうので、ネストを格納するネストを作らないとダメ。
				JuliusPlusRule* firstNestRule = new JuliusPlusRule(callback);
				firstNestRule->AddWord(matchString);

				firstNestRule->AddNestRule(nestRule);
				currentRule->AddNestRule(firstNestRule);
			}

			//かっこの後にも構文が連続する場合、そのツリーを作成する.
			if (*n == '\0'  || *(n+1) == '\0' || *(n+1) == '|')
			{//閉じかっこで構文がとまる場合はそこで終端
				//nop
			}
			else
			{//さらに構文が続いている場合
				JuliusPlusRule * afterRule = new JuliusPlusRule(callback);
				nestRule->SetCombineRule(afterRule);

				currentRule = afterRule;
			}

			//ネストしているルールを再帰して実行.
			matchString = std::string(p+1 , 0 , (int) (n - p - 1) );
			auto r = this->AddRegexpImpl(callback,matchString, nestRule);
			if(!r)
			{
				return xreturn::errnoError(r);
			}

			p = n ;
			splitPos = n + 1;  //+1は最後の ) を飛ばす. iは forの ++i で i == splitPos となる。(わかりにくい)
		}
		else if (*p == '|') 
		{
			matchString = std::string(splitPos,0 , (int) (p - splitPos));
			if (matchString.length() >= 1)
			{
				currentRule->AddWord(matchString);
			}
			//空分岐 (A|) のような場合、空ノードを入れる.
			if (matchString.length() <= 0 || *(p+1) == '\0' )
			{
				assert(0); //not implement! 未実装!
				currentRule->AddWord("");
			}

			splitPos = p + 1;
			currentRule = stateHandle;
		}
		else if (*p == '.' && *(p+1) == '+') 
		{
			assert(0); //not implement! 未実装!
			//			currentRule->AddWord("*");

			p += 1;
			splitPos = p + 1;
		}
	}

	//最後の残り
	matchString = std::string(splitPos , 0 , (int) (p - splitPos) );
	if ( matchString.length() >= 1 &&str.length() >= 1 && *(p-1) != ')')
	{
		currentRule->AddWord(matchString );
	}
	return true;
}
Beispiel #2
0
int GetToken(char *buf,int len,TOKEN *token,
        char *token_separate,char *token_separate_point)
{
int    token_start,token_len;
int    i,j;
char   point[10];

    token->token=NULL;
    token->size=0;
    token->no=0;

    token_start=0;
    for(i=0;i<len;i++){
        /* SJIS漢字1バイト目、エスケープ */
        if(issjiskanji(buf[i])||buf[i]=='\\'){
            i++;
        }
        else if(buf[i]=='"'){    /* "文字列 */
            for(j=i+1;j<len;j++){
                /* SJIS漢字1バイト目、エスケープ */
                if(issjiskanji(buf[j])||buf[j]=='\\'){
                    j++;
                    continue;
                }
                if(buf[j]=='"'){
                    break;
                }
            }
            i=j;
        }
        else if(buf[i]=='\''){    /* '文字列 */
            for(j=i+1;j<len;j++){
                /* SJIS漢字1バイト目、エスケープ */
                if(issjiskanji(buf[j])||buf[j]=='\\'){
                    j++;
                    continue;
                }
                if(buf[j]=='\''){
                    break;
                }
            }
            i=j;
        }
        else if(strchr(token_separate,buf[i])!=NULL){    /* 分離文字 */
            token_len=i-token_start;
            if(token_len>0){
                AddToken(token,&buf[token_start],token_len);
            }
            token_start=i+1;
        }
        else if(strchr(token_separate_point,buf[i])!=NULL){    /* 区切り分離文字 */
            token_len=i-token_start;
            if(token_len>0){
                AddToken(token,&buf[token_start],token_len);
            }
            sprintf(point,"%c",buf[i]);
            AddToken(token,point,1);
            token_start=i+1;
        }
    }
    token_len=i-token_start;
    if(token_len>0){
        AddToken(token,&buf[token_start],token_len);
    }

    return(0);
}
Beispiel #3
0
//音声認識ルールを構築します。 正規表現にも対応しています。
xreturn::r<bool> JuliusPlus::AddRegexp(const CallbackDataStruct & callback,const std::string & str ,JuliusPlusRule* stateHandle ) 
{
	//unixへの移植を考えて wchar_tはやめることにした。
	//unix で UTF8 を使っている限りはマルチバイトに悩むことはないでしょう。 EUCとかレガシーなシステムは知らん。
	//	_USE_WINDOWS_ENCODING;

	//一番最初だけ正規表現の構文変換をかける.
	//難しすぎる表現を簡単なゆとり仕様に直して、パースしやすくする。
	// .+ --> (:?.*)
	// (まる|さんかく)? --> (まる|さんかく|)   正しい正規表現としてはエラーだが、このエンジンの場合容認する.
	// なのは? --> なの(は|)
	std::string optstr;
	optstr.reserve(str.size());

	for( const char * p = str.c_str()  ; *p ; ++p )
	{
#ifdef _WINDOWS_
		if ( issjiskanji(*p) )
		{
			optstr += *p;
			optstr += *(p+1);
			p ++;
			continue;
		}
#endif
		if ( *p == '.' && *(p+1) == '+')
		{ // .+ --> (:?.*)
			optstr += "(?:.+)";
			++p;
		}
		else if (*p == '(' && *(p+1) == '?' && *(p+2) == ':' )
		{
			optstr += "(?:";
			p+=2;
		}
		else if (*(p+1) == '?')
		{
			if (*p == ')')
			{// (まる|さんかく)? --> (まる|さんかく|)
				optstr += "|)";
			}
			else 
			{// なのは? --> なの(は|)
				optstr += std::string("(?:") + *p + "|)";
			}
			++p;
		}
		else if (*p == '*' || *p == '+' || *p == '.' || *p == '[' || *p == ']')
		{
			//            throw exception(std::string("") + "現在は、メタ文字 " + p + " は利用できません。利用可能なメタ文字 () | .+ ?");
			return xreturn::error(std::string("") + "現在は、メタ文字 " + p + " は利用できません。利用可能なメタ文字 () | .+ ?");
		}
		else
		{
			optstr += *p;
		}
	}

	//正規表現 captureの番号。
	this->LocalCaptureRuleNodeCount = 1;
	//このルールを収めるメールを作る。(この処理は厳格に見ると非効率だが、とりあえずこれで)
	JuliusPlusRule* firstNestRule = new JuliusPlusRule(callback);
	stateHandle->AddNestRule(firstNestRule);
	//正規表現パースを本気でやる
	return AddRegexpImpl(callback,optstr, firstNestRule);
}