link-grammar-5.8.0/link-grammar/dict-file/read-dict.c
/**
 * Build (and return the root of) the tree for the expression beginning
 * with the current token.  At the end, the token is the first one not
 * part of this expression.
 */
Build (and return the root of) the tree for the expression beginning
with the current token.  At the end, the token is the first one not
part of this expression.
Build ( and return the root of ) the tree for the expression beginning with the current token . At the end the token is the first one not part of this expression .
static Exp *make_expression(Dictionary dict)
{
	Exp *nl = NULL;
	Exp *e_head = NULL;
	Exp *e_tail = NULL; 
	bool is_sym_and = false;
	while (true)
	{
		if (is_equal(dict, '('))
		{
			if (!link_advance(dict)) {
				return NULL;
			}
			nl = make_expression(dict);
			if (nl == NULL) {
				return NULL;
			}
			if (!is_equal(dict, ')')) {
				dict_error(dict, "Expecting a \")\".");
				return NULL;
			}
			if (!link_advance(dict)) {
				return NULL;
			}
		}
		else if (is_equal(dict, '{'))
		{
			if (!link_advance(dict)) {
				return NULL;
			}
			nl = make_expression(dict);
			if (nl == NULL) {
				return NULL;
			}
			if (!is_equal(dict, '}')) {
				dict_error(dict, "Expecting a \"}\".");
				return NULL;
			}
			if (!link_advance(dict)) {
				return NULL;
			}
			nl = make_optional_node(dict->Exp_pool, nl);
		}
		else if (is_equal(dict, '['))
		{
			if (!link_advance(dict)) {
				return NULL;
			}
			nl = make_expression(dict);
			if (nl == NULL) {
				return NULL;
			}
			if (!is_equal(dict, ']')) {
				dict_error(dict, "Expecting a \"]\".");
				return NULL;
			}
			if (!link_advance(dict)) {
				return NULL;
			}
			if (is_number(dict->token))
			{
				float cost;
				if (strtodC(dict->token, &cost))
				{
					nl->cost += cost;
				}
				else
				{
					warning(dict, "Invalid cost (using 1.0)\n");
					nl->cost += 1.0;
				}
				if (!link_advance(dict)) {
					return NULL;
				}
			}
			else if ((strcmp(dict->token, "or") != 0) &&
			         (strcmp(dict->token, "and") != 0) &&
			         isalpha(dict->token[0]))
			{
				const char *bad = valid_dialect_name(dict->token);
				if (bad != NULL)
				{
					char badchar[] = { *bad, '\0' };
					dict_error2(dict, "Invalid character in dialect tag name:",
					           badchar);
					return NULL;
				}
				if (nl->tag_type != Exptag_none)
				{
					nl = make_unary_node(dict->Exp_pool, nl);
				}
				nl->tag_id = exptag_dialect_add(dict, dict->token);
				nl->tag_type = Exptag_dialect;
				if (!link_advance(dict)) {
					return NULL;
				}
			}
			else
			{
				nl->cost += 1.0;
			}
		}
		else if (!dict->is_special)
		{
			nl = make_connector(dict);
			if (nl == NULL) {
				return NULL;
			}
		}
		else if (is_equal(dict, ')') || is_equal(dict, ']'))
		{
			nl = make_zeroary_node(dict->Exp_pool);
		}
		else
		{
			dict_error(dict, "Connector, \"(\", \"[\", or \"{\" expected.");
			return NULL;
		}
		if (is_sym_and)
		{
			Exp *na = make_and_node(dict->Exp_pool,
			                   Exp_create_dup(dict->Exp_pool, e_tail),
			                   Exp_create_dup(dict->Exp_pool, nl));
			Exp *nb = make_and_node(dict->Exp_pool,
			                   Exp_create_dup(dict->Exp_pool, nl),
			                   Exp_create_dup(dict->Exp_pool, e_tail));
			Exp *or = make_or_node(dict->Exp_pool, na, nb);
			*e_tail = *or; 
			is_sym_and = false;
		}
		else if (e_tail != NULL)
		{
			e_tail->operand_next = nl;
			e_tail = nl;
		}
		Exp_type op;
		if (is_equal(dict, '&') || (strcmp(dict->token, "and") == 0))
		{
			op = AND_type;
		}
		else if (is_equal(dict, '|') || (strcmp(dict->token, "or") == 0))
		{
			op =  OR_type;
		}
		else if (is_equal(dict, SYM_AND) || (strcmp(dict->token, "sym") == 0))
		{
			op = AND_type; 
			is_sym_and = true; 
		}
		else
		{
			if (e_head != NULL) return e_head;
			return nl;
		}
		if (e_head == NULL)
		{
			e_head = make_op_Exp(dict->Exp_pool, op);
			e_head->operand_first = nl;
		}
		else
		{
			if (e_head->type != op)
			{
				dict_error(dict, "\"and\" and \"or\" at the same level in an expression");
				return NULL;
			}
		}
		if (!link_advance(dict)) {
			return NULL;
		}
		if (e_tail == NULL)
			e_tail = e_head->operand_first;
	}
}
static Exp * make_expression ( Dictionary dict ) { Exp * nl = NULL ; Exp * e_head = NULL ; Exp * e_tail = NULL ; bool is_sym_and = false ; while ( true ) { if ( is_equal ( dict , ' ' ) ) { if ( ! link_advance ( dict ) ) { return NULL ; } nl = make_expression ( dict ) ; if ( nl == NULL ) { return NULL ; } if ( ! is_equal ( dict , ' ' ) ) { dict_error ( dict , " \" \" " ) ; return NULL ; } if ( ! link_advance ( dict ) ) { return NULL ; } } else if ( is_equal ( dict , ' ' ) ) { if ( ! link_advance ( dict ) ) { return NULL ; } nl = make_expression ( dict ) ; if ( nl == NULL ) { return NULL ; } if ( ! is_equal ( dict , ' ' ) ) { dict_error ( dict , " \" \" " ) ; return NULL ; } if ( ! link_advance ( dict ) ) { return NULL ; } nl = make_optional_node ( dict -> Exp_pool , nl ) ; } else if ( is_equal ( dict , ' ' ) ) { if ( ! link_advance ( dict ) ) { return NULL ; } nl = make_expression ( dict ) ; if ( nl == NULL ) { return NULL ; } if ( ! is_equal ( dict , ' ' ) ) { dict_error ( dict , " \" \" " ) ; return NULL ; } if ( ! link_advance ( dict ) ) { return NULL ; } if ( is_number ( dict -> token ) ) { float cost ; if ( strtodC ( dict -> token , & cost ) ) { nl -> cost += cost ; } else { warning ( dict , " \n " ) ; nl -> cost += 1.0 ; } if ( ! link_advance ( dict ) ) { return NULL ; } } else if ( ( strcmp ( dict -> token , " " ) != 0 ) && ( strcmp ( dict -> token , " " ) != 0 ) && isalpha ( dict -> token [ 0 ] ) ) { const char * bad = valid_dialect_name ( dict -> token ) ; if ( bad != NULL ) { char badchar [ ] = { * bad , ' \0 ' } ; dict_error2 ( dict , " " , badchar ) ; return NULL ; } if ( nl -> tag_type != Exptag_none ) { nl = make_unary_node ( dict -> Exp_pool , nl ) ; } nl -> tag_id = exptag_dialect_add ( dict , dict -> token ) ; nl -> tag_type = Exptag_dialect ; if ( ! link_advance ( dict ) ) { return NULL ; } } else { nl -> cost += 1.0 ; } } else if ( ! dict -> is_special ) { nl = make_connector ( dict ) ; if ( nl == NULL ) { return NULL ; } } else if ( is_equal ( dict , ' ' ) || is_equal ( dict , ' ' ) ) { nl = make_zeroary_node ( dict -> Exp_pool ) ; } else { dict_error ( dict , " \" \" \" \" \" \" " ) ; return NULL ; } if ( is_sym_and ) { Exp * na = make_and_node ( dict -> Exp_pool , Exp_create_dup ( dict -> Exp_pool , e_tail ) , Exp_create_dup ( dict -> Exp_pool , nl ) ) ; Exp * nb = make_and_node ( dict -> Exp_pool , Exp_create_dup ( dict -> Exp_pool , nl ) , Exp_create_dup ( dict -> Exp_pool , e_tail ) ) ; Exp * or = make_or_node ( dict -> Exp_pool , na , nb ) ; * e_tail = * or ; is_sym_and = false ; } else if ( e_tail != NULL ) { e_tail -> operand_next = nl ; e_tail = nl ; } Exp_type op ; if ( is_equal ( dict , ' ' ) || ( strcmp ( dict -> token , " " ) == 0 ) ) { op = AND_type ; } else if ( is_equal ( dict , ' ' ) || ( strcmp ( dict -> token , " " ) == 0 ) ) { op = OR_type ; } else if ( is_equal ( dict , SYM_AND ) || ( strcmp ( dict -> token , " " ) == 0 ) ) { op = AND_type ; is_sym_and = true ; } else { if ( e_head != NULL ) return e_head ; return nl ; } if ( e_head == NULL ) { e_head = make_op_Exp ( dict -> Exp_pool , op ) ; e_head -> operand_first = nl ; } else { if ( e_head -> type != op ) { dict_error ( dict , " \" \" \" \" " ) ; return NULL ; } } if ( ! link_advance ( dict ) ) { return NULL ; } if ( e_tail == NULL ) e_tail = e_head -> operand_first ; } }
Build (and return the root of) the tree for the expression beginning
 with the current token.
Build ( and return the root of ) the tree for the expression beginning with the current token .
/* last part of the expression */ /* A square bracket can have a number or a name after it.
			 * If a number is present, then that it is interpreted
			 * as the cost of the bracket. If a name is present, it
			 * is used as an expression tag. Else, the cost of a
			 * square bracket is 1.0.
			 */ /* allows "()" or "[]" */ /* Part 2/2 of SYM_AND processing. */ /* Expand A ^ B into the expr ((A & B) or (B & A)). */ /* SYM_AND result */ /* This is Non-commuting AND or Commuting OR.
			 * Append the just read expression (nl) to its operand chain. */ /* Extract the operator. */ /* Non-commuting AND */ /* Commuting OR */ /* Commuting AND */ /* Part 1/2 of SYM_AND processing */ /* allow mixing with ordinary ands at the same level */ /* processing to be completed after next argument */ /* If this is the first operand, use nl for it.  Else just validate
		 * that the current operator is consistent with that of the current
		 * expression level. */ /* unreachable */