Click here to Skip to main content
15,892,537 members
Articles / Desktop Programming / Win32

True Natural Language Understanding through a Conceptual Language Understanding Engine

Rate me:
Please Sign up or sign in to vote.
4.97/5 (55 votes)
11 Jan 201029 min read 68K   3.1K   118  
An article introducing an Artificial Intelligence technique that understands and manipulates concepts from text.
/*
The usage of this source code file, including but not limited to the reading, the compilation and 
redistribution, is subject to the license agreement detailed in the license.txt and license.pdf files
which accompany this source code. By proceeding to use this file you are acknowledging that you have
read either license.txt or license.pdf, and that you agree to be bound by the terms and conditions of
the license. If license.txt and license.pdf are not available, you are not licensed this file and you 
must delete it permanently; or contact the author at proy@conceptualspeech.com to obtain a copy of 
the license before proceeding to use this file.

Copyright Philippe Roy 2010 - proy@conceptualspeech.com.
*/

#pragma warning( disable : 4251 )
#include "v8.h"
#include <stack>

using namespace v8;
using std::stack;

#include "JSObjectSupport.h"
#include "Predicate.h"
#include "POSNode.h"
#include "DigitalConceptBuilder.h"
#include "StringUtils.h"

#include <Windows.h>

#include "DebugDefinitions.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

class POSNode;

Handle<ObjectTemplate> global;
JSTrace JSTrace::globTrace;
int g_alreadyReporting = 0;
stack<POSNode*> g_nodeContext;
stack<string> g_sourceContext;

#pragma warning( disable : 4290 )

Handle<ObjectTemplate> JSGetGlobal()
{
	InitJavascriptGlobal();
	return global;
}

Handle<Value> JSPrint(const Arguments& args)
{ 
	String::AsciiValue ascii0(args[0]);
	Handle<Value> result;
	string dResultStr;
	string dContent = *ascii0;
	printf(dContent.c_str());
	return result;
}

Handle<Value> JSAlert(const Arguments& args)
{ 
	Handle<Value> result;
    String::AsciiValue ascii0(args[0]);
	String::AsciiValue ascii1((args.Length() > 1)?args[1]:args[0]);
	string dCurSequence = DigitalConceptBuilder::GetCurSequence();
	if ((args.Length() == 1) || (*ascii1 == dCurSequence))
	{
		MessageBox(NULL, *ascii0, "Javascript message", MB_OK);
	}
	return result;
}

Handle<Value> JSNewPredicate(const Arguments& args)
{
	shared_auto_ptr<CPredicate> dReturn(new CPredicate());
	dReturn->MemoryProtect();
	return dReturn->CreateJavascriptInstance();
}

Handle<Value> JSSetResultPredicate(const Arguments& args)
{
	Local<External> wrap = Local<External>::Cast(args[0]->ToObject()->GetInternalField(0));
	shared_auto_ptr<CPredicate> usePredicate = static_cast<CPredicate*>(wrap->Value());
	DigitalConceptBuilder::GetCurCalculationContext()->SetResultPredicate(usePredicate);
	return NullValue();
}

Handle<Value> JSGetResultPredicate(const Arguments& args)
{
	if (DigitalConceptBuilder::GetCurCalculationContext()->GetResultPredicate().get() != NULL)
	{
		return DigitalConceptBuilder::GetCurCalculationContext()->GetResultPredicate()->CreateJavascriptInstance();
	}
	else
	{
		return NullValue();
	}
}

string ProcessValueToDisplay(Handle<Value> dValue, bool multiLine)
{
	String::AsciiValue dReturnStr(dValue);
	if ((string)*dReturnStr == "[object Predicate]")
	{
		Local<External> wrap1 = Local<External>::Cast(dValue->ToObject()->GetInternalField(0));
		void* ptr1 = wrap1->Value();
		CPredicate *dPredicate = (CPredicate*)ptr1;
		string dPred = dPredicate->ToString(multiLine);
		return dPred;
	}
	else if ((string)*dReturnStr == "[object POSNode]")
	{
		Local<External> wrap1 = Local<External>::Cast(dValue->ToObject()->GetInternalField(0));
		void* ptr1 = wrap1->Value();
		POSNode *dPOSNode = (POSNode*)ptr1;
		if (dPOSNode != NULL)
		{
			string dPred = dPOSNode->GetNodeDesc() + ", " + dPOSNode->GetConstructionLine();
			return dPred;
		}
		else
		{
			return "NULL";
		}
	}
	else
	{
		string dContent = *dReturnStr;
		return dContent;
	}
}

Handle<Value> ExecuteJavascriptString(Persistent<Context> context, string dSourceStr, string nameStr, bool skiptrace, Handle<Script> *dScript) throw(CMathematicalError)
{
	Context::Scope context_scope(context);

	Handle<Value> result;
	Handle<String> source = String::New(dSourceStr.c_str());
	Handle<Script> script;
	if (dScript == NULL)
	{
		Handle<Value> name = String::New(nameStr.c_str());
		{
			TryCatch try_catch;
			script = Script::Compile(source, name);
			if (script.IsEmpty()) 
			{
				String::AsciiValue error(try_catch.Exception());
				string tmpString = *error;
				CMathematicalError dError(tmpString);
				throw(dError);
			} 
		}
	}
	else
	{
		script = *dScript;
	}
	string indent = "";
	if ((!skiptrace) && (DigitalConceptBuilder::GetCurCalculationContext()->GetJavascriptTrace()))
	{
		for (int i = 0; i < g_alreadyReporting; i++)
		{
			indent += "\t";
		}
		Handle<Value> dCurPredicate = ExecuteJavascriptString(context, "var curPredicate; curPredicate", "trace", true);
		string dCurPredicateStr = ProcessValueToDisplay(dCurPredicate, false);
		Handle<Value> dCurNode = ExecuteJavascriptString(context, "var curNode; curNode", "trace", true);
		string dCurNodeStr = ProcessValueToDisplay(dCurNode, false);
		printf("%s %s %s %s\n%s[\n", g_nodeContext.empty()?"":(indent + "NODE:" + g_nodeContext.top()->GetNodeDesc() + ((g_nodeContext.top()->GetConstructionLine() != "")?(", " + g_nodeContext.top()->GetConstructionLine()):"")).c_str(), g_sourceContext.empty()?"":(g_nodeContext.empty()?"":"\n" + indent + "REF:\"" + g_sourceContext.top() + "\"").c_str(), ("\n" + indent + "curPredicate: " + dCurPredicateStr).c_str(), ("\n" + indent + "curNode: " + dCurNodeStr).c_str(), indent.c_str());
		SearchAndReplace(dSourceStr, "\n", "\1");
		SearchAndReplace(dSourceStr, "\1", "\n\t" + indent);
		SearchAndReplace(dSourceStr, "\r\n", "\1");
		SearchAndReplace(dSourceStr, "\1", "\n");
		printf("%s\t%s", indent.c_str(), dSourceStr.c_str());
		printf("\n");
	}
	g_alreadyReporting++;
	result = script->Run();
	g_alreadyReporting--;
	if ((!skiptrace) && (DigitalConceptBuilder::GetCurCalculationContext()->GetJavascriptTrace()))
	{
		string dDisplay = ProcessValueToDisplay(result, true);
		SearchAndReplace(dDisplay, "\n", "\1");
		SearchAndReplace(dDisplay, "\1", "\n" + indent);
		Handle<Value> dCurPredicate = ExecuteJavascriptString(context, "var curPredicate; curPredicate", "trace", true);
		string dCurPredicateStr = ProcessValueToDisplay(dCurPredicate, false);
		printf("%s] -> %s, curPredicate -> %s\n\n", indent.c_str(), dDisplay.c_str(), dCurPredicateStr.c_str());
	}
	return result;
}

JSTrace::JSTrace(): m_enabled(false) {}
JSTrace::~JSTrace() {}

void JSTrace::SetEnable(bool value)
{
	if ((!value) && (m_enabled) && (m_content.length() > 0))
	{
		printf(m_content.c_str());
		m_content = "";
	}
	else if ((value) && (!m_enabled))
	{
		if (m_syntacticContext.length() > 0)
		{
			m_content += "Syntactic context: " + m_syntacticContext + "\n";
		}
	}
	m_enabled = value;
}

void JSTrace::SetSyntacticContext(string dContext)
{
	m_syntacticContext = dContext;
}

void JSTrace::AppendContext(string label, shared_auto_ptr<CPredicate> wp, shared_auto_ptr<POSNode> curNode)
{
	if (m_enabled)
	{
		m_content += (label.length() > 0)?"Context: " + label + "\n":"";
		if (wp.get() != NULL)
		{
			m_content += wp->Inspect(1);
		}
		if (curNode.get() != NULL)
		{
			m_content += curNode->Inspect(1);
		}
	}
}

Handle<Value> NullValue()
{
	return Integer::New(0);
}

void InitJavascriptGlobal()
{
	if (global.IsEmpty())
	{
		global = v8::ObjectTemplate::New();
		global->Set(String::New("alert"), FunctionTemplate::New(JSAlert));
		global->Set(String::New("print"), FunctionTemplate::New(JSPrint));
		global->Set(String::New("new_predicate"), FunctionTemplate::New(JSNewPredicate));
		global->Set(String::New("setResultPredicate"), FunctionTemplate::New(JSSetResultPredicate));
		global->Set(String::New("getResultPredicate"), FunctionTemplate::New(JSGetResultPredicate));
	}
}

#pragma warning( default : 4290 )

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
Canada Canada
Philippe Roy was a key contributor throughout his 20+ years career with many high-profile companies such as Nuance Communications, IBM (ViaVoice and ProductManager), VoiceBox Technologies, just to name a few. He is creative and proficient in OO coding and design, knowledgeable about the intellectual-property world (he owns many patents), tri-lingual, and passionate about being part of a team that creates great solutions.

Oh yes, I almost forgot to mention, he has a special thing for speech recognition and natural language processing... The magic of first seeing a computer transform something as chaotic as sound and natural language into intelligible and useful output has never left him.

Comments and Discussions