<?php

include_once("config.php");

function parseLexEntry($toParse){

	$toParse = trim($toParse);
	
	if (strlen($toParse) == 0)
		return "empty string";
	
	$i = 0;
	$res = array("tokens" => array());
	//var_dump($toParse);
	$i = consumeWhiteChars($toParse, $i);

	while ($i < strlen($toParse) && $toParse[$i] == '('){
		$tokRes = parseToken($toParse, $i);
		//print_r($tokRes);
		if (is_array($tokRes))
			$res["tokens"][] = $tokRes;
		else
			return $tokRes;	// error
			
		$i = consumeWhiteChars($toParse, $i);
	}

	if ($i < strlen($toParse))
		return "fatal parse error";

	return $res;
}

function parseToken($toParse, &$i){
	$i = $i + 1;	// going over the first "("

	$res = array("tokens" => array());
	
	$i = consumeWhiteChars($toParse, $i);

	// parsing internal tokens
	$internalTokensCounter = 0;
	while ($toParse[$i] == '('){
		$internalTokensCounter = $internalTokensCounter + 1;
		$tokRes = parseToken($toParse, $i);
		if (is_array($tokRes))
			$res["tokens"][] = $tokRes;
		else
			return $tokRes;	// error occured
		$i = consumeWhiteChars($toParse, $i);
	}

	// parsing operator
	if ($internalTokensCounter == 1){
		$opRes = parseOperator($toParse, $i);
		if (is_array($opRes)){
			$res["op"] = $opRes;
			$i = consumeWhiteChars($toParse, $i);
			while ($toParse[$i] == '('){
				$internalTokensCounter = $internalTokensCounter + 1;
				$tokRes = parseToken($toParse, $i);
				if (is_array($tokRes))
					$res["tokens"][] = $tokRes;
				else
					return $tokRes;
				$i = consumeWhiteChars($toParse, $i);
			}
		}
		else
			return $opRes;
	}

	$i = consumeWhiteChars($toParse, $i);
	if (isset($res["op"])){
		if ($toParse[$i] == ')'){
			$i = $i + 1;
			return $res;
		}
		else
			return "parse error";
	}

	// parsing token word
	$token = "";
	while ($internalTokensCounter == 0 && $i < strlen($toParse) && 
			$toParse[$i] != ' ' && $toParse[$i] != ')'){
		$token .= $toParse[$i];
		$i = $i + 1;
	}
	

	if ($internalTokensCounter == 0) {
		if ($toParse[$i] == ' ' || $toParse[$i] == ')'){
			$res["form"] = $token;
		}
		else
			return "token without a word";
	}

	$i = consumeWhiteChars($toParse, $i);

	// parsing attributes
	$err = parseAttributes($toParse, $i, $res);
	if (strlen($err) > 0){
		return $err;
	}
	
	if ($toParse[$i] == ')'){
		$i = $i + 1;
		return $res;
	}
	else
		return "could not find closing mark";
}

function parseOperator($toParse, &$i){
	$res = NULL;
	if ($toParse[$i] == '^'){
		$res = array("type" => "xor");
		$i = $i + 1;
	}
	else if ($toParse[$i] == '|'){
		$res = array("type" => "or");
		$i = $i + 1;
	}
	else if ($toParse[$i] == '<-->'){
		$res = array("type" => "inter");
		$i = $i + 4;
	}
	else if ($toParse[$i] == '<'){
		$i = $i + 1;
		$left = array();
		$right = array();
		while ($toParse[$i] == 'C' || $toParse[$i] == 'D' || $toParse[$i] == 'P'){
			if ($toParse[$i] == 'C')
				$left["conj"] = true;
			else if ($toParse[$i] == 'D')
				$left["det"] = true;
			else if ($toParse[$i] == 'P')
				$left["prep"] = true;
			$i = $i + 1;
		}
		if ($toParse[$i] == '|')
			$i = $i + 1;
		else
			return "unsupported feature in or-interchange operator";
		
		while ($toParse[$i] == 'C' || $toParse[$i] == 'D' || $toParse[$i] == 'P'){
			if ($toParse[$i] == 'C')
				$right["conj"] = true;
			else if ($toParse[$i] == 'D')
				$right["det"] = true;
			else if ($toParse[$i] == 'P')
				$right["prep"] = true;
			$i = $i + 1;
		}
		if ($toParse[$i] == '>')
			$i = $i + 1;
		else
			return "unsupported feature in or-interchange operator";
		
		$res = array("type" => "or-interchange", "left" => $left, "right" => $right);
	}
	return $res;
}

function parseAttributes($toParse, &$i, &$res){
	$value = "";

	while ($toParse[$i] != ')'){
		$colonPos = strpos($toParse, ":", $i);
		if ($colonPos === false){
			return "error in parsing attribute. missing ':'";
		}
		
		$name = substr($toParse, $i, $colonPos - $i); 
		if ($toParse[$colonPos + 1] == '('){
		
				// composite attribute
			$i = $colonPos + 1;
			$attrRes = tryGetAttributeList($toParse, $i);
			if (!is_null($attrRes)){
				$res[$name] = $attrRes;
				$i = $i + 1;
			}
			else{
				$i = $colonPos + 2;
				$attrRes = array();
				$err = parseAttributes($toParse, $i, $attrRes);
				if (strlen($err) > 0)
					return $err;
				else{
					$res[$name] = $attrRes;
					$i = $i + 1;
				}
			}
			$i = consumeWhiteChars($toParse, $i);
		}
		else{
			// simple attribute
			
			$spacePos = strpos($toParse, " ", $colonPos);
			$endPos = strpos($toParse, ")", $colonPos);
			if ($spacePos === false && $endPos == false)
				return "error in parsing attribute. missing end of attribute";
					
			$lPos = ($spacePos === false) ? $endPos : (($endPos === false) ? $spacePos : (min($endPos, $spacePos)));
			$attrValue = getSystemAttrValue(substr($toParse, $colonPos + 1, $lPos - ($colonPos + 1)));
			if (!is_null($attrValue)){
				$res[$name] = $attrValue;
				$i = $lPos;
			}
			else
				return "error in parsing attribute. invalid attribute value " + substr($toParse, $colonPos + 1, $lPos);
			$i = consumeWhiteChars($toParse, $i);
		}

	}
}

function tryGetAttributeList($toParse, &$i){
	$origI = $i;
	$res = array();
	while ($toParse[$i] != ')'){
		$i = $i + 1;
		$i = consumeWhiteChars($toParse, $i);
		$comPos = strpos($toParse, ",", $i);
		$endPos = strpos($toParse, ")", $i);
		
		if ($comPos === false && $endPos === false){
			$i = $origI;
			return NULL;
		}

		$lPos = ($comPos === false)? $endPos : (($endPos === false)? $compPos : min($endPos, $comPos));
		$value = getSystemAttrValue(substr($toParse, $i, $lpos - $i));
		if (strlen($value) > 0){
			$res[] = $value;
			$i = $lPos;
		}
		else{
			$i = $origI;
			return NULL;
		}
		$i = consumeWhiteChars($toParse, $i);
	}
	return $res;
}

function getSystemAttrValue($name){
	if ($name == "y" || $name == "Y")
		return true;
	else if ($name == "n" || $name == "N")
		return false;
	else if (strlen($name) > 0)
		return $name;
	return NULL;
}

function consumeWhiteChars($str, $i){
	while (preg_match("[\\s]", $str[$i]) === 1) 
		$i = $i + 1;
	return $i;
}


?>