//  #0
//  Program     : _cllct_parseNMS
//  Author      : Joseph D. Wolfe
//  Description : create sreturns with new and orginal col/row/eq names
//  Requirements: >=Stata 10 (currently untested on previous versions)

* version 0.0.1 :: 06/07/11 12:05 PM
* version 0.0.2 :: 07/26/11 12:05 PM
* version 0.0.3 :: 10/25/11 09:50 AM
*!version 0.0.4 :: 05/24/12 06:17 PM

//  #1
//  Program define

capture clear programs
program define _cllct_parseNMS, sclass

syntax ,                     ///
	[                        ///
	innames(string asis)     ///
	rownames(numlist)        ///
	coleq(string asis)       ///
	roweq(string asis)       ///
	trace                    ///
	debug					 ///
	]                        ///

set trace off
if "`trace'"    != "" set trace on
if "`rownames'" == "" local rownames = 0

//  #2
//  add defaults

*check if equation names are already specified
local parseNMS = regexm(`"`innames'"', ":")

*see if equations are specified in incoming names
local anyceq = regexm(`"`newoutcol'"', ":")
local anyreq = regexm(`"`newoutrow'"', ":")

//  #3
//  add errors

if `parseNMS' & `"`roweq'"'!="" & `rownames' {
	di as error ///
	"You cannot use roweq() when equations are specified in row names"
	exit 198
}

if `parseNMS' & `"`coleq'"'!=""  & !`rownames' {
	di as error ///
	"You cannot use coleq() when equations are specified in column names"
	exit 198
}

//  #4
//  Prepare for parsing

*add spaces around = and : to assist in parsing
local crnames : subinstr local innames "=" " = ", all
local crnames : subinstr local crnames ":" " : ", all
// local crnames = itrim(`"`crnames'"')
local crnum   : list sizeof local crnames
tokenize `"`crnames'"'

*n1wd-n3wd stands for next # word
*p1wd-p3wd stands for prev # word
local n1wd =  1
local n2wd =  2
local n3wd =  3
local p1wd = -1
local p2wd = -2
local p3wd = -3

//  #5
//  loop through each word of tokenized crnames and label as in or out names

forvalues wd = 1(1)`crnum' {
	local ++n1wd
	local ++n2wd
	local ++n3wd
	local ++p1wd
	local ++p2wd
	local ++p3wd
	local innm  = 0  // if 1 then send to INcolNMS
	local outnm = 0  // if 1 then send to OUTcolNMS
	local stop  = 0

	*the next word can be "=", ":", or neither
	*figure out which and then determine where name should be
	if `"``n1wd''"' == "=" {
		if  `"``wd''"'   == "="  | `"``wd''"' == ":"   local stop = 1
		if  `"``n2wd''"' == "="  | `"``n2wd''"'==":"   local stop = 1
		if (`"``p1wd''"' == "=")                       |               ///
           (`"``p1wd''"' == ":" & `"``p3wd''"' == "=") |               ///
           (`"``p1wd''"' == ":" & `"``p3wd''"' == "=") local stop = 1

		if !`stop' local outnm = 1
	}

	if (`"``n1wd''"' == ":") {
		if  `"``wd''"'   == "="  | `"``wd''"'  ==":"    local stop  =1
		if  `"``n2wd''"' == "="  | `"``n2wd''"'==":"    local stop  =1
		if (`"``p1wd''"' == "=") &                                      ///
           (`"``p2wd''"' == "="  | `"``p2wd''"' == ":") local stop  =1
		if  `"``p1wd''"' == "="                         local innm  =1
		if  `"``n2wd''"' == "="                         local outnm =1
		if  `"``n1wd''"' == ":" & `"``n2wd''"' != "=" &                 ///
            `"``n2wd''"' != ":" & `"``n3wd''"' == "="   local outnm =1
		if  `"``p1wd''"' != "=" & `"``n3wd''"'!="=" {
			local innm  = 1
			local outnm = 1
		}
	}

	if (`"``n1wd''"' != "=" & `"``n1wd''"' !=":")	{
		if `"``p1wd''"'  == "=" & `"``p2wd''"' == "="  local stop  =1
		if `"``p1wd''"'  == ":" & `"``p2wd''"' == ":"  local stop  =1
		if `"``p1wd''"'  == "="                        local innm  =1
		if `"``p1wd''"'  == ":" & `"``p3wd''"'== "="   local innm  =1
		if  `"``p1wd''"' == ":" & `"``p2wd''"'!= "="                    ///
                                & `"``p2wd''"'!= ":"   local innm  =1
		if `"``wd''"'    ==":"  & `"``n2wd''"'== "="   local outnm =1
		if `"``wd''"'    ==":"  & `"``p2wd''"'== "="   local innm  =1
		if `"``p1wd''"'  ==":"  & `"``n2wd''"'!= "="                    ///
         & `"``p3wd''"'  =="=" 		                 	local innm =1
		if `"``p1wd''"'  ==":"  & `"``n2wd''"'!= "=" & `"``p3wd''"'!="=" {
			local innm  = 1
			local outnm = 1
		}
		if `"``wd''"'==":" & `"``p2wd''"'!="=" & `"``n2wd''"'!="=" {
			local innm  = 1
			local outnm = 1
		}
    	if `"``p1wd''"'!=":" & `"``p1wd''"'!="=" & `"``wd''"'!=":" &    ///
           `"``n2wd''"'!="=" {
			local innm  = 1
			local outnm = 1
		}
    	if `"``p1wd''"'!=":" & `"``p1wd''"'!="=" & `"``wd''"'!=":" &   ////
           `"``n1wd''"'!=":" & `"``n1wd''"'!="=" {
			local innm  = 1
			local outnm = 1
		}
	}

	*never include equal signs in locals
	if `"``wd''"' == "=" {
		local innm  = 0
		local outnm = 0
	}

if "`debug'"!="" {
	di "`wd'*******************************"
	di `"Names = `innames'"'
	di `"IN `innm' / OUT `outnm'"'
	di `"wd - ``wd''"'
	di `"n1wd - ``n1wd''"'
	di `"n2wd - ``n2wd''"'
	di `"n3wd - ``n3wd''"'
	di `"p1wd - ``p1wd''"'
	di `"p2wd - ``p2wd''"'
	di `"p3wd - ``p3wd''"'
	di `"Error - `stop'"'
}

	*put 2+ word column/equation names into quotes
	local quotes : list sizeof local `wd'
	if `quotes'>1 local wd `""``wd''""'
	else local wd `"``wd''"'

	if `innm' {
		*make sure all in names have equation name
		local inwd `"`wd'"'
		local inwd = itrim(`"`inwd'"')
		local inwd =  trim(`"`inwd'"')

		if (!regexm(`"`wd'"',":")     &  !regexm(`"``p1wd''"',":") &       ///
           !regexm(`"``n1wd''"',":")) | (!regexm(`"`wd'"',":")     &       ///
            regexm(`"``p1wd''"',"innames\(") & !regexm(`"``n1wd''"',":"))  {
            	local inwd `"_:`inwd'"'
				local IN_NMS `"`IN_NMS' `inwd'"'
         }

		else if `"`inwd'"'==":" |  `"``p1wd''"'==":" { //v004 fix
			local IN_NMS `"`IN_NMS'`inwd'"'
		}

		else if `"`inwd'"'!=":" & `"``p1wd''"'!=":" {
			local IN_NMS `"`IN_NMS' `inwd'"'
		}
	}
	if `outnm' {
		*make sure all out names have equation name
		local outwd `"`wd'"'
		local outwd = itrim(`"`outwd'"')
		local outwd =  trim(`"`outwd'"')

		if (!regexm(`"`wd'"',":")      & !regexm(`"``p1wd''"',":") &       ///
			!regexm(`"``n1wd''"',":")) | (!regexm(`"`wd'"',":")    &       ///
         	 regexm(`"``p1wd''"',"innames\(") & !regexm(`"``n1wd''"',":")) {
			 	local outwd `"_:`outwd'"'
				local OUT_NMS `"`OUT_NMS' `outwd'"'
		}

		else if `"`outwd'"'==":" | `"``p1wd''"'==":" {
			local OUT_NMS `"`OUT_NMS'`outwd'"'
		}

		else if `"`outwd'"'!=":" & `"``p1wd''"'!=":" {
			local OUT_NMS `"`OUT_NMS' `outwd'"'
		}
	}

	*Syntax error
	if "`stop'" == "" local stop = 0
	if "`stop'" == "1" {
		di as error "Column or Row specification contains invalid syntax"
		exit 198
	}
}

/* v004: no longer necessary
//  #6
//  Remove Unnecessary Spaces

local IN_NMS = itrim(`"`IN_NMS'"')
local IN_NMS : subinstr local IN_NMS " = " "=", all
local IN_NMS : subinstr local IN_NMS  " =" "=", all
local IN_NMS : subinstr local IN_NMS  "= " "=", all

local IN_NMS : subinstr local IN_NMS " : " ":", all
local IN_NMS : subinstr local IN_NMS  " :" ":", all
local IN_NMS : subinstr local IN_NMS  ": " ":", all

local OUT_NMS = itrim(`"`OUT_NMS'"')
local OUT_NMS : subinstr local OUT_NMS " = " "=", all
local OUT_NMS : subinstr local OUT_NMS  " =" "=", all
local OUT_NMS : subinstr local OUT_NMS  "= " "=", all

local OUT_NMS : subinstr local OUT_NMS " : " ":", all
local OUT_NMS : subinstr local OUT_NMS  " :" ":", all
local OUT_NMS : subinstr local OUT_NMS  ": " ":", all
*/

//  #7
//  Set s-returns

sreturn local parseNMS = `parseNMS'  // to use in parseEQNMS
sreturn local IN_NMS  `"`IN_NMS'"'
sreturn local OUT_NMS `"`OUT_NMS'"'

if "`debug'"!="" {
	di `"Names = `innames'"'
	di `"IN_NMS = `IN_NMS'"'
	di `"OUT_NMS = `OUT_NMS'"'
}

//  #8
//  end _cllct_parseNMS program

end
exit