/*
 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Yokogawa Electric Corporation,
 * YDC Corporation, IPA (Information-technology Promotion Agency, Japan).
 * All rights reserved.
 * 
 * Redistribution and use of this software in source and binary forms, with 
 * or without modification, are permitted provided that the following 
 * conditions and disclaimer are agreed and accepted by the user:
 * 
 * 1. Redistributions of source code must retain the above copyright 
 * notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the following disclaimer in the 
 * documentation and/or other materials provided with the distribution.
 * 
 * 3. Neither the names of the copyrighters, the name of the project which 
 * is related to this software (hereinafter referred to as "project") nor 
 * the names of the contributors may be used to endorse or promote products 
 * derived from this software without specific prior written permission.
 * 
 * 4. No merchantable use may be permitted without prior written 
 * notification to the copyrighters. However, using this software for the 
 * purpose of testing or evaluating any products including merchantable 
 * products may be permitted without any notification to the copyrighters.
 * 
 * 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHTERS, THE PROJECT AND 
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING 
 * BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 * FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.  IN NO EVENT SHALL THE 
 * COPYRIGHTERS, THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT,STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
 * THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $TAHI: v6eval/lib/Cm/CmMatch.cc,v 1.5 2001/10/12 04:56:13 tanaka Exp $
 */
#include "CmMatch.h"
#include "CmToken.h"
#include <stdio.h>
#include <stdlib.h>
CmMatch::CmMatch(const CmToken* t,CSTR s):CmQueue(),
	token_(t),string_(s),org_() {}
CmMatch::~CmMatch() {}

CmMatch* CmMatch::setToken(const CmToken& t) {
	if(token()!=0) {
		ooutf("duplicate CmMatch(%s)\n",t.string());
		abort();}
	token(&t);
	return this;}

//----------------------------------------------------------------------
// SPLIT TOKEN STRING by LENGTH
// this will be the child of newly created CmMatch
CmMatch* CmMatch::split(int32_t l) {
	CSTR ms=string();
	CmCString upper(ms,l);
	CmCString lower(ms+l);
	CmMatch* ulm=new CmMatch(0,upper.string());
	CmQueue* p=prev();
	deque();
	p->insert(ulm);
	ulm->org().insert(this);
	setString(lower.string());
	return ulm;}

//----------------------------------------------------------------------
// MATCHING INITIAL LETTER
CmQueue* CmMatch::greaterEqualInitial(const CmQueue& org,char c,char& mi) {
	const CmQueue* o=&org;
	CmQueue* p=org.next();
	mi=0;
	for(;p!=o;p=p->next()) {
		CmMatch* m=(CmMatch*)p;
		mi=m->initial();
		if(c<=mi) {return p;}}
	return p;}

const CmMatch* CmMatch::equalInitial(const CmQueue& org,char c) {
	const CmQueue* o=&org;
	CmQueue* p=org.next();
	for(;p!=o;p=p->next()) {
		CmMatch* m=(CmMatch*)p;
		char mi=m->initial();
		if(c==mi) {return m;}}
	return 0;}

//----------------------------------------------------------------------
// SCAN STRING
CmMatch* CmMatch::matchTokenString(const CmToken& t,CSTR ts) {
	CSTR ms=string();
	CSTR mp=0;
	char mc,tc;
	for(mp=ms;(tc=*ts,mc=*mp);mp++,ts++) { 
		if(tc!=mc) {break;}}
	if(mc==0&&tc==0) {
		return setToken(t);}
	CmMatch* lm=mc==0?this:split(mp-ms);
	lm=(tc==0)?lm->setToken(t):lm->newTokenString(t,ts);
	return lm;}

const CmMatch* CmMatch::findMatchString(CSTR ts) const {
	CSTR ms=string();
	CSTR mp=0;
	char mc,tc=0;
	for(mp=ms;(tc=*ts,mc=*mp);mp++,ts++) {
		if(tc!=mc) {break;}}
	if(mc!=0) {return 0;}
	const CmMatch* child=findString(org_,ts);
	const CmMatch* lm=child!=0?child->findMatchString(ts):0;
	return lm!=0?lm:this;}

//----------------------------------------------------------------------
// FIND INITIAL MATCH
CmMatch* CmMatch::addTokenString(CmQueue& org,const CmToken& t,CSTR ts) {
	char ti=*ts;
	char mi=0;
	CmQueue* q=greaterEqualInitial(org,ti,mi);
	CmMatch* lm=0;
	if(ti!=mi) {
		lm=new CmMatch(&t,ts);
		q->insert(lm);}
	else {
		lm=(CmMatch*)q;
		lm=lm->matchTokenString(t,ts);}
	return lm;}

const CmMatch* CmMatch::findString(const CmQueue& org,CSTR ts) {
	const CmMatch* lm=equalInitial(org,*ts);
	return lm!=0?lm->findMatchString(ts):0;}

//----------------------------------------------------------------------
// PUBLIC INTERFACE
const CmToken* CmMatch::findToken(CSTR s,const CmQueue* o) {
	const CmQueue& org=o!=0?*o:top();
	const CmMatch* lm=findString(org,s);
	return lm!=0?lm->token():0;}

const CmToken* CmMatch::lex(CSTR& s) {
	const CmToken* lt=findToken(s);
	if(lt!=0) {s+=lt->length();}
	return lt;}

CmMatch* CmMatch::addToken(const CmToken& t,CmQueue* o) {
	CmQueue& org=o!=0?*o:top();
	return addTokenString(org,t,t.string());}

CmQueue CmMatch::top_;


syntax highlighted by Code2HTML, v. 0.9.1