Soar Kernel  9.3.2 08-06-12
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Functions | Variables
parser.cpp File Reference
#include <portability.h>
#include <stdlib.h>
#include "parser.h"
#include "symtab.h"
#include "kernel.h"
#include "gdatastructs.h"
#include "production.h"
#include "mem.h"
#include "rhsfun.h"
#include "agent.h"
#include "init_soar.h"
#include "print.h"
#include "rete.h"
#include "xml.h"
#include "reinforcement_learning.h"
#include "semantic_memory.h"
#include <ctype.h>

Go to the source code of this file.

Functions

actiondestructively_reverse_action_list (action *a)
void fill_in_attr_tests (agent *thisAgent, condition *conds, test t)
void fill_in_id_tests (agent *thisAgent, condition *conds, test t)
Bool is_preference_lexeme (enum lexer_token_type test_lexeme)
test make_placeholder_test (agent *thisAgent, char first_letter)
Symbolmake_placeholder_var (agent *thisAgent, char first_letter)
Symbolmake_symbol_for_current_lexeme (agent *thisAgent, bool allow_lti)
conditionnegate_condition_list (agent *thisAgent, condition *conds)
actionparse_attr_value_make (agent *thisAgent, Symbol *id)
conditionparse_attr_value_tests (agent *thisAgent)
conditionparse_cond (agent *thisAgent)
conditionparse_cond_plus (agent *thisAgent)
conditionparse_conds_for_one_id (agent *thisAgent, char first_letter_if_no_id_given, test *dest_id_test)
test parse_disjunction_test (agent *thisAgent)
rhs_value parse_function_call_after_lparen (agent *thisAgent, Bool is_stand_alone_action)
test parse_head_of_conds_for_one_id (agent *thisAgent, char first_letter_if_no_id_given)
conditionparse_lhs (agent *thisAgent)
bool parse_lti (agent *thisAgent)
byte parse_preference_specifier_without_referent (agent *thisAgent)
actionparse_preferences (agent *thisAgent, Symbol *id, rhs_value attr, rhs_value value)
actionparse_preferences_soar8_non_operator (agent *thisAgent, Symbol *id, rhs_value attr, rhs_value value)
productionparse_production (agent *thisAgent, unsigned char *rete_addition_result)
test parse_relational_test (agent *thisAgent)
Bool parse_rhs (agent *thisAgent, action **dest_rhs)
actionparse_rhs_action (agent *thisAgent)
rhs_value parse_rhs_value (agent *thisAgent)
test parse_simple_test (agent *thisAgent)
conditionparse_tail_of_conds_for_one_id (agent *thisAgent)
test parse_test (agent *thisAgent)
conditionparse_value_test_star (agent *thisAgent, char first_letter)
void reset_placeholder_variable_generator (agent *thisAgent)
void substitute_for_placeholders_in_action_list (agent *thisAgent, action *a)
void substitute_for_placeholders_in_condition_list (agent *thisAgent, condition *cond)
void substitute_for_placeholders_in_symbol (agent *thisAgent, Symbol **sym)
void substitute_for_placeholders_in_test (agent *thisAgent, test *t)

Variables

const char * help_on_lhs_grammar []
const char * help_on_rhs_grammar []

Function Documentation

action* destructively_reverse_action_list ( action a)

Definition at line 1852 of file parser.cpp.

References action_struct::next, and NIL.

Referenced by parse_production().

{
action *prev, *current, *next;
prev = NIL;
current = a;
while (current) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
return prev;
}
void fill_in_attr_tests ( agent thisAgent,
condition conds,
test  t 
)

Definition at line 546 of file parser.cpp.

References three_field_tests_struct::attr_test, CONJUNCTIVE_NEGATION_CONDITION, copy_of_equality_test_found_in_test(), copy_test(), condition_struct::data, deallocate_test(), condition_struct::condition_main_data_union::ncc, condition_struct::next, NIL, POSITIVE_CONDITION, condition_struct::condition_main_data_union::tests, ncc_info_struct::top, and condition_struct::type.

Referenced by parse_attr_value_tests().

{
condition *positive_c, *c;
test equality_test_from_t;
/* --- see if there's at least one positive condition --- */
for (positive_c=conds; positive_c!=NIL; positive_c=positive_c->next)
if ((positive_c->type==POSITIVE_CONDITION) &&
(positive_c->data.tests.attr_test==NIL)) break;
if (positive_c) { /* --- there is at least one positive condition --- */
/* --- add just the equality test to most of the conditions --- */
equality_test_from_t = copy_of_equality_test_found_in_test (thisAgent, t);
for (c=conds; c!=NIL; c=c->next) {
fill_in_attr_tests (thisAgent, c->data.ncc.top, equality_test_from_t);
else if (c->data.tests.attr_test==NIL)
c->data.tests.attr_test = copy_test (thisAgent, equality_test_from_t);
}
deallocate_test (thisAgent, equality_test_from_t);
/* --- add the whole test to one positive condition --- */
deallocate_test (thisAgent, positive_c->data.tests.attr_test);
positive_c->data.tests.attr_test = copy_test (thisAgent, t);
return;
}
/* --- all conditions are negative --- */
for (c=conds; c!=NIL; c=c->next) {
fill_in_attr_tests (thisAgent, c->data.ncc.top, t);
} else {
c->data.tests.attr_test = copy_test (thisAgent, t);
}
}
}
void fill_in_id_tests ( agent thisAgent,
condition conds,
test  t 
)

Definition at line 510 of file parser.cpp.

References CONJUNCTIVE_NEGATION_CONDITION, copy_of_equality_test_found_in_test(), copy_test(), condition_struct::data, deallocate_test(), three_field_tests_struct::id_test, condition_struct::condition_main_data_union::ncc, condition_struct::next, NIL, POSITIVE_CONDITION, condition_struct::condition_main_data_union::tests, ncc_info_struct::top, and condition_struct::type.

Referenced by parse_attr_value_tests(), and parse_conds_for_one_id().

{
condition *positive_c, *c;
test equality_test_from_t;
/* --- see if there's at least one positive condition --- */
for (positive_c=conds; positive_c!=NIL; positive_c=positive_c->next)
if ((positive_c->type==POSITIVE_CONDITION) &&
(positive_c->data.tests.id_test==NIL)) break;
if (positive_c) { /* --- there is at least one positive condition --- */
/* --- add just the equality test to most of the conditions --- */
equality_test_from_t = copy_of_equality_test_found_in_test (thisAgent, t);
for (c=conds; c!=NIL; c=c->next) {
fill_in_id_tests (thisAgent, c->data.ncc.top, equality_test_from_t);
else if (c->data.tests.id_test==NIL)
c->data.tests.id_test = copy_test (thisAgent, equality_test_from_t);
}
deallocate_test (thisAgent, equality_test_from_t);
/* --- add the whole test to one positive condition --- */
deallocate_test (thisAgent, positive_c->data.tests.id_test);
positive_c->data.tests.id_test = copy_test (thisAgent, t);
return;
}
/* --- all conditions are negative --- */
for (c=conds; c!=NIL; c=c->next) {
fill_in_id_tests (thisAgent, c->data.ncc.top, t);
} else {
if (c->data.tests.id_test==NIL)
c->data.tests.id_test = copy_test (thisAgent, t);
}
}
}
Bool is_preference_lexeme ( enum lexer_token_type  test_lexeme)

Definition at line 1260 of file parser.cpp.

References AMPERSAND_LEXEME, EQUAL_LEXEME, EXCLAMATION_POINT_LEXEME, FALSE, GREATER_LEXEME, LESS_LEXEME, MINUS_LEXEME, PLUS_LEXEME, TILDE_LEXEME, and TRUE.

Referenced by parse_preference_specifier_without_referent().

{
switch (test_lexeme) {
return TRUE;
return TRUE;
return TRUE;
return TRUE;
return TRUE;
return TRUE;
return TRUE;
return TRUE;
default:
return FALSE;
}
}
test make_placeholder_test ( agent thisAgent,
char  first_letter 
)
Symbol* make_placeholder_var ( agent thisAgent,
char  first_letter 
)

Definition at line 62 of file parser.cpp.

References make_variable(), NIL, and agent_struct::placeholder_counter.

Referenced by make_placeholder_test(), and parse_attr_value_make().

{
Symbol *v;
char buf[30];
int i;
if (!isalpha(first_letter)) {
first_letter = 'v';
}
i = tolower(first_letter) - static_cast<int>('a');
assert (i >= 0 && i < 26);
/* --- create variable with "#" in its name: this couldn't possibly be a
variable in the user's code, since the lexer doesn't handle "#" --- */
SNPRINTF (buf, sizeof(buf)-1, "<#%c*%lu>", first_letter, static_cast<long unsigned int>(thisAgent->placeholder_counter[i]++));
buf[sizeof(buf)-1] = '\0';
v = make_variable(thisAgent, buf);
/* --- indicate that there is no corresponding "real" variable yet --- */
v->var.current_binding_value = NIL;
return v;
}
Symbol* make_symbol_for_current_lexeme ( agent thisAgent,
bool  allow_lti 
)

Definition at line 257 of file parser.cpp.

References abort_with_fatal_error(), BUFFER_MSG_SIZE, FLOAT_CONSTANT_LEXEME, lexeme_info::float_val, lexeme_info::id_letter, lexeme_info::id_number, IDENTIFIER_LEXEME, INT_CONSTANT_LEXEME, lexeme_info::int_val, agent_struct::lexeme, make_float_constant(), make_int_constant(), make_sym_constant(), make_variable(), NIL, smem_lti_get_id(), smem_lti_soar_make(), SMEM_LTI_UNKNOWN_LEVEL, lexeme_info::string, SYM_CONSTANT_LEXEME, lexeme_info::type, and VARIABLE_LEXEME.

Referenced by parse_disjunction_test(), parse_relational_test(), and parse_rhs_value().

{
switch (thisAgent->lexeme.type) {
case SYM_CONSTANT_LEXEME: return make_sym_constant (thisAgent, thisAgent->lexeme.string);
case VARIABLE_LEXEME: return make_variable (thisAgent, thisAgent->lexeme.string);
case INT_CONSTANT_LEXEME: return make_int_constant (thisAgent, thisAgent->lexeme.int_val);
case FLOAT_CONSTANT_LEXEME: return make_float_constant (thisAgent, thisAgent->lexeme.float_val);
if (!allow_lti) {
char msg[BUFFER_MSG_SIZE];
strncpy(msg, "parser.c: Internal error: ID found in make_symbol_for_current_lexeme\n", BUFFER_MSG_SIZE);
msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
abort_with_fatal_error(thisAgent, msg);
}
else {
smem_lti_id lti_id = smem_lti_get_id( thisAgent, thisAgent->lexeme.id_letter, thisAgent->lexeme.id_number );
if ( lti_id == NIL ) {
char msg[BUFFER_MSG_SIZE];
strncpy(msg, "parser.c: Internal error: invalid long-term identifier found in make_symbol_for_current_lexeme\n", BUFFER_MSG_SIZE);
msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
abort_with_fatal_error(thisAgent, msg);
}
else {
return smem_lti_soar_make( thisAgent, lti_id, thisAgent->lexeme.id_letter, thisAgent->lexeme.id_number, SMEM_LTI_UNKNOWN_LEVEL );
}
}
break;
default:
{ char msg[BUFFER_MSG_SIZE];
SNPRINTF(msg, BUFFER_MSG_SIZE, "parser.c: Internal error: bad lexeme type in make_symbol_for_current_lexeme\n, thisAgent->lexeme.string=%s\n", thisAgent->lexeme.string);
msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
abort_with_fatal_error(thisAgent, msg);
}
}
return NIL; /* unreachable, but without it, gcc -Wall warns here */
}
condition* negate_condition_list ( agent thisAgent,
condition conds 
)

Definition at line 592 of file parser.cpp.

References ncc_info_struct::bottom, agent_struct::condition_pool, CONJUNCTIVE_NEGATION_CONDITION, condition_struct::data, condition_struct::condition_main_data_union::ncc, NEGATIVE_CONDITION, condition_struct::next, NIL, POSITIVE_CONDITION, condition_struct::prev, ncc_info_struct::top, and condition_struct::type.

Referenced by parse_attr_value_tests(), and parse_cond().

{
condition *temp, *last;
if (conds->next==NIL) {
/* --- only one condition to negate, so toggle the type --- */
switch (conds->type) {
return conds;
return conds;
temp = conds->data.ncc.top;
free_with_pool (&thisAgent->condition_pool, conds);
return temp;
}
}
/* --- more than one condition; so build a conjunctive negation --- */
allocate_with_pool (thisAgent, &thisAgent->condition_pool, &temp);
temp->next = NIL;
temp->prev = NIL;
temp->data.ncc.top = conds;
for (last=conds; last->next!=NIL; last=last->next);
temp->data.ncc.bottom = last;
return temp;
}
action* parse_attr_value_make ( agent thisAgent,
Symbol id 
)

Definition at line 1616 of file parser.cpp.

References deallocate_action_list(), deallocate_rhs_value(), first_letter_from_rhs_value(), get_lexeme(), agent_struct::lexeme, make_placeholder_var(), action_struct::next, NIL, parse_preferences(), parse_preferences_soar8_non_operator(), parse_rhs_value(), PERIOD_LEXEME, print(), print_location_of_most_recent_lexeme(), R_PAREN_LEXEME, rhs_value_to_string(), symbol_remove_ref(), symbol_to_rhs_value(), lexeme_info::type, and UP_ARROW_LEXEME.

Referenced by parse_rhs_action().

{
rhs_value attr, value;
action *all_actions, *new_actions, *last;
Symbol *old_id, *new_var;
/* JC Added, need to store the attribute name */
char szAttribute[256];
if (thisAgent->lexeme.type!=UP_ARROW_LEXEME) {
print (thisAgent, "Expected ^ in RHS make action\n");
return NIL;
}
old_id = id;
get_lexeme(thisAgent); /* consume up-arrow, advance to attribute */
attr = parse_rhs_value(thisAgent);
if (! attr)
return NIL;
/* JC Added, we will need the attribute as a string, so we get it here */
rhs_value_to_string(thisAgent, attr, szAttribute, 256);
all_actions = NIL;
/* allow dot notation "." in RHS attribute path 10/15/98 KJC */
while (thisAgent->lexeme.type == PERIOD_LEXEME)
{
get_lexeme(thisAgent); /* consume the "." */
/* set up for next attribute in path: make dummy variable,
and create new action in the path */
new_var = make_placeholder_var(thisAgent, first_letter_from_rhs_value (attr));
/* parse_preferences actually creates the action. eventhough
there aren't really any preferences to read, we need the default
acceptable and parallel prefs created for all attributes in path */
if(strcmp(szAttribute,"operator") != 0)
{
new_actions = parse_preferences_soar8_non_operator (thisAgent, id, attr,
}
else
{
new_actions = parse_preferences (thisAgent, id, attr, symbol_to_rhs_value(new_var));
}
for (last=new_actions; last->next!=NIL; last=last->next)
/* continue */;
last->next = all_actions;
all_actions = new_actions;
/* NLD Added. Once we create an action for the
intermediate dot notation attribute/value pair,
remove references for each. Prevents memory
leaks for rules containing dot notation. */
deallocate_rhs_value (thisAgent, attr);
symbol_remove_ref(thisAgent, new_var);
/* if there was a "." then there must be another attribute
set id for next action and get the next attribute */
id = new_var;
attr = parse_rhs_value(thisAgent);
if (! attr)
return NIL;
/* JC Added. We need to get the new attribute's name */
rhs_value_to_string(thisAgent, attr, szAttribute, 256);
}
/* end of while (thisAgent->lexeme.type == PERIOD_LEXEME */
/* end KJC 10/15/98 */
do {
value = parse_rhs_value(thisAgent);
if (!value) {
deallocate_rhs_value (thisAgent, attr);
deallocate_action_list (thisAgent, all_actions);
return NIL;
}
if(strcmp(szAttribute,"operator") != 0)
{
new_actions = parse_preferences_soar8_non_operator (thisAgent, id, attr, value);
}
else
{
new_actions = parse_preferences (thisAgent, id, attr, value);
}
deallocate_rhs_value (thisAgent, value);
if (!new_actions) {
deallocate_rhs_value (thisAgent, attr);
return NIL;
}
for (last=new_actions; last->next!=NIL; last=last->next);
last->next = all_actions;
all_actions = new_actions;
} while ((thisAgent->lexeme.type!=R_PAREN_LEXEME) &&
(thisAgent->lexeme.type!=UP_ARROW_LEXEME));
deallocate_rhs_value (thisAgent, attr);
return all_actions;
}
condition* parse_attr_value_tests ( agent thisAgent)

Definition at line 706 of file parser.cpp.

References add_new_test_to_test(), three_field_tests_struct::attr_test, agent_struct::condition_pool, copy_test(), condition_struct::data, deallocate_condition_list(), deallocate_test(), FALSE, fill_in_attr_tests(), fill_in_id_tests(), first_letter_from_test(), get_lexeme(), three_field_tests_struct::id_test, agent_struct::lexeme, make_placeholder_test(), MINUS_LEXEME, negate_condition_list(), condition_struct::next, NIL, parse_test(), parse_value_test_star(), PERIOD_LEXEME, POSITIVE_CONDITION, condition_struct::prev, print(), print_location_of_most_recent_lexeme(), condition_struct::test_for_acceptable_preference, test_includes_equality_test_for_symbol(), condition_struct::condition_main_data_union::tests, TRUE, lexeme_info::type, condition_struct::type, UP_ARROW_LEXEME, and three_field_tests_struct::value_test.

Referenced by parse_tail_of_conds_for_one_id().

{
test id_test_to_use, attr_test;
Bool negate_it;
condition *first_c, *last_c, *c, *new_conds;
/* --- read optional minus sign --- */
negate_it = FALSE;
if (thisAgent->lexeme.type==MINUS_LEXEME) { negate_it = TRUE; get_lexeme(thisAgent); }
/* --- read up arrow --- */
if (thisAgent->lexeme.type!=UP_ARROW_LEXEME) {
print (thisAgent, "Expected ^ followed by attribute\n");
return NIL;
}
get_lexeme(thisAgent);
first_c = NIL;
last_c = NIL;
/* --- read first <attr_test> --- */
attr_test = parse_test(thisAgent);
if (!attr_test) return NIL;
add_new_test_to_test (thisAgent, &attr_test, make_placeholder_test (thisAgent, 'a'));
}
/* --- read optional attribute path --- */
id_test_to_use = NIL;
while (thisAgent->lexeme.type==PERIOD_LEXEME) {
get_lexeme(thisAgent); /* consume the "." */
/* --- setup for next attribute in path: make a dummy variable,
create a new condition in the path --- */
allocate_with_pool (thisAgent, &thisAgent->condition_pool, &c);
if (last_c) last_c->next = c; else first_c = c;
c->next = NIL;
c->prev = last_c;
last_c = c;
if (id_test_to_use)
c->data.tests.id_test = copy_test (thisAgent, id_test_to_use);
else
c->data.tests.attr_test = attr_test;
id_test_to_use = make_placeholder_test (thisAgent, first_letter_from_test(attr_test));
c->data.tests.value_test = id_test_to_use;
/* --- update id and attr tests for the next path element --- */
attr_test = parse_test (thisAgent);
if (!attr_test) {
deallocate_condition_list (thisAgent, first_c);
return NIL;
}
/* AGR 544 begin */
add_new_test_to_test (thisAgent, &attr_test,make_placeholder_test(thisAgent, 'a'));
}
/* AGR 544 end */
} /* end of while (thisAgent->lexeme.type==PERIOD_LEXEME) */
/* --- finally, do the <value_test>* part --- */
new_conds = parse_value_test_star (thisAgent, first_letter_from_test (attr_test));
if (!new_conds) {
deallocate_condition_list (thisAgent, first_c);
deallocate_test (thisAgent, attr_test);
return NIL;
}
fill_in_attr_tests (thisAgent, new_conds, attr_test);
if (id_test_to_use) fill_in_id_tests (thisAgent, new_conds, id_test_to_use);
deallocate_test (thisAgent, attr_test);
if (last_c) last_c->next = new_conds; else first_c = new_conds;
new_conds->prev = last_c;
/* should update last_c here, but it's not needed anymore */
/* --- negate everything if necessary --- */
if (negate_it) first_c = negate_condition_list (thisAgent, first_c);
return first_c;
}
condition* parse_cond ( agent thisAgent)

Definition at line 982 of file parser.cpp.

References deallocate_condition_list(), FALSE, get_lexeme(), L_BRACE_LEXEME, agent_struct::lexeme, MINUS_LEXEME, negate_condition_list(), NIL, parse_cond_plus(), parse_conds_for_one_id(), print(), print_location_of_most_recent_lexeme(), R_BRACE_LEXEME, TRUE, and lexeme_info::type.

Referenced by parse_cond_plus().

{
Bool negate_it;
/* --- look for leading "-" sign --- */
negate_it = FALSE;
if (thisAgent->lexeme.type==MINUS_LEXEME) { negate_it = TRUE; get_lexeme(thisAgent); }
/* --- parse <positive_cond> --- */
if (thisAgent->lexeme.type==L_BRACE_LEXEME) {
/* --- read conjunctive condition --- */
get_lexeme(thisAgent);
c = parse_cond_plus(thisAgent);
if (!c) return NIL;
if (thisAgent->lexeme.type!=R_BRACE_LEXEME) {
print (thisAgent, "Expected } to end conjunctive condition\n");
deallocate_condition_list (thisAgent, c);
return NIL;
}
get_lexeme(thisAgent); /* consume the R_BRACE */
} else {
/* --- read conds for one id --- */
c = parse_conds_for_one_id (thisAgent, 's', NULL);
if (!c) return NIL;
}
/* --- if necessary, handle the negation --- */
if (negate_it) c = negate_condition_list (thisAgent, c);
return c;
}
condition * parse_cond_plus ( agent thisAgent)

Definition at line 1021 of file parser.cpp.

References deallocate_condition_list(), L_BRACE_LEXEME, L_PAREN_LEXEME, agent_struct::lexeme, MINUS_LEXEME, condition_struct::next, NIL, parse_cond(), condition_struct::prev, and lexeme_info::type.

Referenced by parse_cond(), and parse_lhs().

{
condition *first_c, *last_c, *new_conds;
first_c = NIL;
last_c = NIL;
do {
/* --- get individual <cond> --- */
new_conds = parse_cond (thisAgent);
if (!new_conds) {
deallocate_condition_list (thisAgent, first_c);
return NIL;
}
if (last_c) last_c->next = new_conds; else first_c = new_conds;
new_conds->prev = last_c;
for (last_c=new_conds; last_c->next!=NIL; last_c=last_c->next);
} while ((thisAgent->lexeme.type==MINUS_LEXEME) ||
(thisAgent->lexeme.type==L_PAREN_LEXEME) ||
(thisAgent->lexeme.type==L_BRACE_LEXEME));
return first_c;
}
condition * parse_conds_for_one_id ( agent thisAgent,
char  first_letter_if_no_id_given,
test dest_id_test 
)

Definition at line 943 of file parser.cpp.

References copy_of_equality_test_found_in_test(), deallocate_test(), fill_in_id_tests(), NIL, parse_head_of_conds_for_one_id(), and parse_tail_of_conds_for_one_id().

Referenced by parse_cond(), and parse_value_test_star().

{
condition *conds;
test id_test, equality_test_from_id_test;
/* --- parse the head --- */
id_test = parse_head_of_conds_for_one_id (thisAgent, first_letter_if_no_id_given);
if (! id_test) return NIL;
/* --- parse the tail --- */
conds = parse_tail_of_conds_for_one_id (thisAgent);
if (! conds) {
deallocate_test (thisAgent, id_test);
return NIL;
}
/* --- fill in the id test in all the conditions just read --- */
if (dest_id_test) {
*dest_id_test = id_test;
equality_test_from_id_test = copy_of_equality_test_found_in_test (thisAgent, id_test);
fill_in_id_tests (thisAgent, conds, equality_test_from_id_test);
deallocate_test (thisAgent, equality_test_from_id_test);
} else {
fill_in_id_tests (thisAgent, conds, id_test);
deallocate_test (thisAgent, id_test);
}
return conds;
}
test parse_disjunction_test ( agent thisAgent)

Definition at line 403 of file parser.cpp.

References agent_struct::complex_test_pool, complex_test_struct::data, deallocate_test(), destructively_reverse_list(), complex_test_struct::test_info_union::disjunction_list, DISJUNCTION_TEST, FLOAT_CONSTANT_LEXEME, get_lexeme(), GREATER_GREATER_LEXEME, INT_CONSTANT_LEXEME, LESS_LESS_LEXEME, agent_struct::lexeme, make_symbol_for_current_lexeme(), make_test_from_complex_test(), NIL, print(), print_location_of_most_recent_lexeme(), push(), SYM_CONSTANT_LEXEME, lexeme_info::type, and complex_test_struct::type.

Referenced by parse_simple_test().

{
test t;
if (thisAgent->lexeme.type!=LESS_LESS_LEXEME) {
print (thisAgent, "Expected << to begin disjunction test\n");
return NIL;
}
get_lexeme(thisAgent);
allocate_with_pool (thisAgent, &thisAgent->complex_test_pool, &ct);
while (thisAgent->lexeme.type!=GREATER_GREATER_LEXEME) {
switch (thisAgent->lexeme.type) {
push (thisAgent, make_symbol_for_current_lexeme(thisAgent, false), ct->data.disjunction_list);
get_lexeme(thisAgent);
break;
default:
print (thisAgent, "Expected constant or >> while reading disjunction test\n");
deallocate_test (thisAgent, t);
return NIL;
}
}
get_lexeme(thisAgent); /* consume the >> */
return t;
}
rhs_value parse_function_call_after_lparen ( agent thisAgent,
Bool  is_stand_alone_action 
)

Definition at line 1141 of file parser.cpp.

References allocate_cons(), rhs_function_struct::can_be_rhs_value, rhs_function_struct::can_be_stand_alone_action, deallocate_rhs_value(), find_sym_constant(), cons_struct::first, funcall_list_to_rhs_value(), get_lexeme(), agent_struct::lexeme, lookup_rhs_function(), MINUS_LEXEME, sym_constant_struct::name, rhs_function_struct::name, NIL, rhs_function_struct::num_args_expected, parse_rhs_value(), PLUS_LEXEME, print(), print_location_of_most_recent_lexeme(), R_PAREN_LEXEME, cons_struct::rest, symbol_union::sc, lexeme_info::string, and lexeme_info::type.

Referenced by parse_rhs_action(), and parse_rhs_value().

{
Symbol *fun_name;
list *fl;
cons *c, *prev_c;
rhs_value arg_rv;
int num_args;
/* --- read function name, find the rhs_function structure --- */
if (thisAgent->lexeme.type==PLUS_LEXEME) fun_name = find_sym_constant (thisAgent, "+");
else if (thisAgent->lexeme.type==MINUS_LEXEME) fun_name = find_sym_constant (thisAgent, "-");
else fun_name = find_sym_constant (thisAgent, thisAgent->lexeme.string);
if (!fun_name) {
print (thisAgent, "No RHS function named %s\n",thisAgent->lexeme.string);
return NIL;
}
rf = lookup_rhs_function (thisAgent, fun_name);
if (!rf) {
print (thisAgent, "No RHS function named %s\n",thisAgent->lexeme.string);
return NIL;
}
/* --- make sure stand-alone/rhs_value is appropriate --- */
if (is_stand_alone_action && (! rf->can_be_stand_alone_action)) {
print (thisAgent, "Function %s cannot be used as a stand-alone action\n",
thisAgent->lexeme.string);
return NIL;
}
if ((! is_stand_alone_action) && (! rf->can_be_rhs_value)) {
print (thisAgent, "Function %s can only be used as a stand-alone action\n",
thisAgent->lexeme.string);
return NIL;
}
/* --- build list of rhs_function and arguments --- */
allocate_cons (thisAgent, &fl);
fl->first = rf;
prev_c = fl;
get_lexeme(thisAgent); /* consume function name, advance to argument list */
num_args = 0;
while (thisAgent->lexeme.type!=R_PAREN_LEXEME) {
arg_rv = parse_rhs_value (thisAgent);
if (!arg_rv) {
prev_c->rest = NIL;
return NIL;
}
num_args++;
allocate_cons (thisAgent, &c);
c->first = arg_rv;
prev_c->rest = c;
prev_c = c;
}
prev_c->rest = NIL;
/* --- check number of arguments --- */
if ((rf->num_args_expected != -1) && (rf->num_args_expected != num_args)) {
print (thisAgent, "Wrong number of arguments to function %s (expected %d)\n",
return NIL;
}
get_lexeme(thisAgent); /* consume the right parenthesis */
}
test parse_head_of_conds_for_one_id ( agent thisAgent,
char  first_letter_if_no_id_given 
)

Definition at line 797 of file parser.cpp.

References add_new_test_to_test(), add_to_growable_string(), agent_struct::complex_test_pool, copy_of_equality_test_found_in_test(), deallocate_test(), free_growable_string(), get_lexeme(), GOAL_ID_TEST, IDENTIFIER_SYMBOL_TYPE, IMPASSE_ID_TEST, L_PAREN_LEXEME, agent_struct::lexeme, make_blank_growable_string(), make_blank_test(), make_placeholder_test(), make_test_from_complex_test(), MINUS_LEXEME, NIL, parse_test(), print(), print_location_of_most_recent_lexeme(), print_with_symbols(), R_PAREN_LEXEME, referent_of_equality_test(), lexeme_info::string, SYM_CONSTANT_LEXEME, symbol_to_string(), test_includes_equality_test_for_symbol(), text_of_growable_string(), lexeme_info::type, complex_test_struct::type, UP_ARROW_LEXEME, VARIABLE_SYMBOL_TYPE, and xml_generate_warning().

Referenced by parse_conds_for_one_id().

{
test id_test, id_goal_impasse_test, check_for_symconstant;
Symbol *sym;
if (thisAgent->lexeme.type!=L_PAREN_LEXEME) {
print (thisAgent, "Expected ( to begin condition element\n");
return NIL;
}
get_lexeme(thisAgent);
/* --- look for goal/impasse indicator --- */
if (thisAgent->lexeme.type==SYM_CONSTANT_LEXEME) {
if (!strcmp(thisAgent->lexeme.string,"state")) {
allocate_with_pool (thisAgent, &thisAgent->complex_test_pool, &ct);
id_goal_impasse_test = make_test_from_complex_test(ct);
get_lexeme(thisAgent);
first_letter_if_no_id_given = 's';
} else if (!strcmp(thisAgent->lexeme.string,"impasse")) {
allocate_with_pool (thisAgent, &thisAgent->complex_test_pool, &ct);
id_goal_impasse_test = make_test_from_complex_test(ct);
get_lexeme(thisAgent);
first_letter_if_no_id_given = 'i';
} else {
id_goal_impasse_test = make_blank_test();
}
} else {
id_goal_impasse_test = make_blank_test();
}
/* --- read optional id test; create dummy one if none given --- */
if ((thisAgent->lexeme.type!=MINUS_LEXEME) &&
(thisAgent->lexeme.type!=UP_ARROW_LEXEME) &&
(thisAgent->lexeme.type!=R_PAREN_LEXEME)) {
id_test = parse_test(thisAgent);
if (!id_test) {
deallocate_test (thisAgent, id_goal_impasse_test);
return NIL;
}
(thisAgent, &id_test, make_placeholder_test (thisAgent, first_letter_if_no_id_given));
} else {
check_for_symconstant = copy_of_equality_test_found_in_test(thisAgent, id_test);
sym = referent_of_equality_test(check_for_symconstant);
deallocate_test (thisAgent, check_for_symconstant); /* RBD added 3/28/95 */
// Symbol type can only be IDENTIFIER_SYMBOL_TYPE if it is a long term identifier (lti),
// Otherwise, it isn't possible to have an IDENTIFIER_SYMBOL_TYPE here.
if((sym->common.symbol_type != VARIABLE_SYMBOL_TYPE) && (sym->common.symbol_type != IDENTIFIER_SYMBOL_TYPE)) {
print_with_symbols(thisAgent, "Warning: Constant %y in id field test.\n", sym);
print(thisAgent, " This will never match.\n");
add_to_growable_string(thisAgent, &gs, "Warning: Constant ");
add_to_growable_string(thisAgent, &gs, symbol_to_string(thisAgent, sym, true, 0, 0));
add_to_growable_string(thisAgent, &gs, " in id field test.\n This will never match.");
free_growable_string(thisAgent, gs);
//TODO: should we append this to the previous XML message or create a new message for it?
deallocate_test (thisAgent, id_test); /* AGR 527c */
return NIL; /* AGR 527c */
}
}
} else {
id_test = make_placeholder_test (thisAgent, first_letter_if_no_id_given);
}
/* --- add the goal/impasse test to the id test --- */
add_new_test_to_test (thisAgent, &id_test, id_goal_impasse_test);
/* --- return the resulting id test --- */
return id_test;
}
condition* parse_lhs ( agent thisAgent)

Definition at line 1050 of file parser.cpp.

References NIL, and parse_cond_plus().

Referenced by parse_production().

{
c = parse_cond_plus (thisAgent);
if (!c) return NIL;
return c;
}
bool parse_lti ( agent thisAgent)

Definition at line 1791 of file parser.cpp.

References AT_LEXEME, get_lexeme(), get_lexer_allow_ids(), agent_struct::lexeme, set_lexer_allow_ids(), and lexeme_info::type.

Referenced by parse_relational_test(), parse_rhs_action(), and parse_rhs_value().

{
switch(thisAgent->lexeme.type) {
case AT_LEXEME:
{
Bool saved = get_lexer_allow_ids(thisAgent);
set_lexer_allow_ids(thisAgent, true);
get_lexeme(thisAgent);
set_lexer_allow_ids(thisAgent, saved);
}
return true;
default:
break;
}
return false;
}
byte parse_preference_specifier_without_referent ( agent thisAgent)

Definition at line 1308 of file parser.cpp.

References ACCEPTABLE_PREFERENCE_TYPE, AMPERSAND_LEXEME, BEST_PREFERENCE_TYPE, BETTER_PREFERENCE_TYPE, BINARY_INDIFFERENT_PREFERENCE_TYPE, BINARY_PARALLEL_PREFERENCE_TYPE, COMMA_LEXEME, EQUAL_LEXEME, EXCLAMATION_POINT_LEXEME, FLOAT_CONSTANT_LEXEME, get_lexeme(), GREATER_LEXEME, INT_CONSTANT_LEXEME, is_preference_lexeme(), LESS_LEXEME, agent_struct::lexeme, MINUS_LEXEME, NUMERIC_INDIFFERENT_PREFERENCE_TYPE, PLUS_LEXEME, PROHIBIT_PREFERENCE_TYPE, R_PAREN_LEXEME, REJECT_PREFERENCE_TYPE, REQUIRE_PREFERENCE_TYPE, TILDE_LEXEME, lexeme_info::type, UNARY_INDIFFERENT_PREFERENCE_TYPE, UNARY_PARALLEL_PREFERENCE_TYPE, UP_ARROW_LEXEME, WORSE_PREFERENCE_TYPE, and WORST_PREFERENCE_TYPE.

Referenced by parse_preferences(), and parse_preferences_soar8_non_operator().

{
switch (thisAgent->lexeme.type) {
get_lexeme(thisAgent);
if (thisAgent->lexeme.type==COMMA_LEXEME) get_lexeme(thisAgent);
get_lexeme(thisAgent);
if (thisAgent->lexeme.type==COMMA_LEXEME) get_lexeme(thisAgent);
get_lexeme(thisAgent);
if (thisAgent->lexeme.type==COMMA_LEXEME) get_lexeme(thisAgent);
get_lexeme(thisAgent);
if (thisAgent->lexeme.type==COMMA_LEXEME) get_lexeme(thisAgent);
/****************************************************************************
* [Soar-Bugs #55] <forced-unary-preference> ::= <binary-preference>
* {<any-preference> | , | ) | ^}
*
* Forced unary preferences can now occur when a binary preference is
* followed by a ",", ")", "^" or any preference specifier
****************************************************************************/
get_lexeme(thisAgent);
if ((thisAgent->lexeme.type!=COMMA_LEXEME) &&
(thisAgent->lexeme.type!=R_PAREN_LEXEME) &&
(thisAgent->lexeme.type!=UP_ARROW_LEXEME) &&
/* --- forced unary preference --- */
if (thisAgent->lexeme.type==COMMA_LEXEME) get_lexeme(thisAgent);
get_lexeme(thisAgent);
if ((thisAgent->lexeme.type!=COMMA_LEXEME) &&
(thisAgent->lexeme.type!=R_PAREN_LEXEME) &&
(thisAgent->lexeme.type!=UP_ARROW_LEXEME) &&
{
if ((thisAgent->lexeme.type == INT_CONSTANT_LEXEME) ||
else
}
/* --- forced unary preference --- */
if (thisAgent->lexeme.type==COMMA_LEXEME) get_lexeme(thisAgent);
get_lexeme(thisAgent);
if ((thisAgent->lexeme.type!=COMMA_LEXEME) &&
(thisAgent->lexeme.type!=R_PAREN_LEXEME) &&
(thisAgent->lexeme.type!=UP_ARROW_LEXEME) &&
/* --- forced unary preference --- */
if (thisAgent->lexeme.type==COMMA_LEXEME) get_lexeme(thisAgent);
get_lexeme(thisAgent);
if ((thisAgent->lexeme.type!=COMMA_LEXEME) &&
(thisAgent->lexeme.type!=R_PAREN_LEXEME) &&
(thisAgent->lexeme.type!=UP_ARROW_LEXEME) &&
/* --- forced unary preference --- */
if (thisAgent->lexeme.type==COMMA_LEXEME) get_lexeme(thisAgent);
default:
/* --- if no preference given, make it an acceptable preference --- */
} /* end of switch statement */
}
action* parse_preferences ( agent thisAgent,
Symbol id,
rhs_value  attr,
rhs_value  value 
)

Definition at line 1412 of file parser.cpp.

References ACCEPTABLE_PREFERENCE_TYPE, agent_struct::action_pool, action_struct::attr, COMMA_LEXEME, copy_rhs_value(), deallocate_action_list(), get_lexeme(), action_struct::id, agent_struct::lexeme, MAKE_ACTION, action_struct::next, NIL, parse_preference_specifier_without_referent(), parse_rhs_value(), PLUS_LEXEME, preference_is_binary(), action_struct::preference_type, action_struct::referent, symbol_add_ref(), symbol_to_rhs_value(), TRUE, lexeme_info::type, action_struct::type, and action_struct::value.

Referenced by parse_attr_value_make().

{
action *a;
action *prev_a;
rhs_value referent;
byte preference_type;
Bool saw_plus_sign;
/* --- Note: this routine is set up so if there's not preference type
indicator at all, we return a single acceptable preference make --- */
prev_a = NIL;
saw_plus_sign = (thisAgent->lexeme.type==PLUS_LEXEME);
preference_type = parse_preference_specifier_without_referent (thisAgent);
if ((preference_type==ACCEPTABLE_PREFERENCE_TYPE) && (! saw_plus_sign)) {
/* If the routine gave us a + pref without seeing a + sign, then it's
just giving us the default acceptable preference. Look for optional
comma. */
if (thisAgent->lexeme.type==COMMA_LEXEME) get_lexeme(thisAgent);
}
while (TRUE) {
/* --- read referent --- */
if (preference_is_binary(preference_type)) {
referent = parse_rhs_value(thisAgent);
if (! referent) {
deallocate_action_list (thisAgent, prev_a);
return NIL;
}
if (thisAgent->lexeme.type==COMMA_LEXEME) get_lexeme(thisAgent);
} else {
referent = NIL; /* unnecessary, but gcc -Wall warns without it */
}
/* --- create the appropriate action --- */
allocate_with_pool (thisAgent, &thisAgent->action_pool, &a);
a->next = prev_a;
prev_a = a;
a->preference_type = preference_type;
a->attr = copy_rhs_value (thisAgent, attr);
a->value = copy_rhs_value (thisAgent, value);
if (preference_is_binary(preference_type)) a->referent = referent;
/* --- look for another preference type specifier --- */
saw_plus_sign = (thisAgent->lexeme.type==PLUS_LEXEME);
preference_type = parse_preference_specifier_without_referent (thisAgent);
/* --- exit loop when done reading preferences --- */
if ((preference_type==ACCEPTABLE_PREFERENCE_TYPE) && (! saw_plus_sign))
/* If the routine gave us a + pref without seeing a + sign, then it's
just giving us the default acceptable preference, it didn't see any
more preferences specified. */
return prev_a;
}
}
action* parse_preferences_soar8_non_operator ( agent thisAgent,
Symbol id,
rhs_value  attr,
rhs_value  value 
)

Definition at line 1493 of file parser.cpp.

References ACCEPTABLE_PREFERENCE_TYPE, agent_struct::action_pool, action_struct::attr, COMMA_LEXEME, copy_rhs_value(), deallocate_action_list(), get_lexeme(), action_struct::id, agent_struct::lexeme, MAKE_ACTION, action_struct::next, NIL, parse_preference_specifier_without_referent(), PLUS_LEXEME, preference_is_binary(), action_struct::preference_type, print(), print_location_of_most_recent_lexeme(), REJECT_PREFERENCE_TYPE, rhs_value_to_string(), symbol_add_ref(), symbol_to_rhs_value(), symbol_to_string(), TRUE, lexeme_info::type, action_struct::type, action_struct::value, and xml_generate_warning().

Referenced by parse_attr_value_make().

{
action *a;
action *prev_a;
rhs_value referent;
byte preference_type;
Bool saw_plus_sign;
/* JC ADDED: for printint */
char szPrintAttr[256];
char szPrintValue[256];
char szPrintId[256];
/* --- Note: this routine is set up so if there's not preference type
indicator at all, we return an acceptable preference make
and a parallel preference make. For non-operators, allow
only REJECT_PREFERENCE_TYPE, (and UNARY_PARALLEL and ACCEPTABLE).
If any other preference type indicator is found, a warning or
error msg (error only on binary prefs) is printed. --- */
prev_a = NIL;
saw_plus_sign = (thisAgent->lexeme.type==PLUS_LEXEME);
preference_type = parse_preference_specifier_without_referent (thisAgent);
if ((preference_type==ACCEPTABLE_PREFERENCE_TYPE) && (! saw_plus_sign)) {
/* If the routine gave us a + pref without seeing a + sign, then it's
just giving us the default acceptable preference. Look for optional
comma. */
if (thisAgent->lexeme.type==COMMA_LEXEME) get_lexeme(thisAgent);
}
while (TRUE) {
/* step through the pref list, print warning messages when necessary. */
/* --- read referent --- */
if (preference_is_binary(preference_type))
{
print (thisAgent, "\nERROR: in Soar8, binary preference illegal for non-operator.");
/* JC BUG FIX: Have to check to make sure that the rhs_values are converted to strings
correctly before we print */
rhs_value_to_string(thisAgent, attr, szPrintAttr, 256);
rhs_value_to_string(thisAgent, value, szPrintValue, 256);
symbol_to_string(thisAgent, id, TRUE, szPrintId, 256);
print(thisAgent, "id = %s\t attr = %s\t value = %s\n", szPrintId, szPrintAttr, szPrintValue);
deallocate_action_list (thisAgent, prev_a);
return NIL;
} else {
referent = NIL; /* unnecessary, but gcc -Wall warns without it */
}
if ( (preference_type != ACCEPTABLE_PREFERENCE_TYPE) &&
(preference_type != REJECT_PREFERENCE_TYPE) ) {
print (thisAgent, "\nWARNING: in Soar8, the only allowable non-operator preference \nis REJECT - .\nIgnoring specified preferences.\n");
xml_generate_warning(thisAgent, "WARNING: in Soar8, the only allowable non-operator preference \nis REJECT - .\nIgnoring specified preferences.");
/* JC BUG FIX: Have to check to make sure that the rhs_values are converted to strings
correctly before we print */
rhs_value_to_string(thisAgent, attr, szPrintAttr, 256);
rhs_value_to_string(thisAgent, value, szPrintValue, 256);
symbol_to_string(thisAgent, id, TRUE, szPrintId, 256);
print(thisAgent, "id = %s\t attr = %s\t value = %s\n", szPrintId, szPrintAttr, szPrintValue);
}
if (preference_type == REJECT_PREFERENCE_TYPE) {
/* --- create the appropriate action --- */
allocate_with_pool (thisAgent, &thisAgent->action_pool, &a);
a->next = prev_a;
prev_a = a;
a->preference_type = preference_type;
a->attr = copy_rhs_value (thisAgent, attr);
a->value = copy_rhs_value (thisAgent, value);
}
/* --- look for another preference type specifier --- */
saw_plus_sign = (thisAgent->lexeme.type==PLUS_LEXEME);
preference_type = parse_preference_specifier_without_referent (thisAgent);
/* --- exit loop when done reading preferences --- */
if ((preference_type==ACCEPTABLE_PREFERENCE_TYPE) && (! saw_plus_sign)) {
/* If the routine gave us a + pref without seeing a + sign, then it's
just giving us the default acceptable preference, it didn't see any
more preferences specified. */
/* for soar8, if this wasn't a REJECT preference, then
create acceptable preference makes. */
if (prev_a == NIL) {
allocate_with_pool (thisAgent, &thisAgent->action_pool, &a);
a->next = prev_a;
prev_a = a;
a->attr = copy_rhs_value (thisAgent, attr);
a->value = copy_rhs_value (thisAgent, value);
}
return prev_a;
}
}
}
production* parse_production ( agent thisAgent,
unsigned char *  rete_addition_result 
)
read

Definition at line 1878 of file parser.cpp.

References add_production_to_rete(), CHUNK_PRODUCTION_TYPE, deallocate_action_list(), deallocate_condition_list(), DECLARED_I_SUPPORT, DECLARED_O_SUPPORT, production_struct::declared_support, DEFAULT_PRODUCTION_TYPE, destructively_reverse_action_list(), production_struct::documentation, DUPLICATE_PRODUCTION, excise_production(), FALSE, free_memory_block_for_string(), get_lexeme(), production_struct::interrupt, agent_struct::lexeme, make_memory_block_for_string(), make_production(), make_sym_constant(), agent_struct::name, condition_struct::next, NIL, parse_lhs(), parse_rhs(), print(), print_location_of_most_recent_lexeme(), print_with_symbols(), sym_constant_struct::production, QUOTED_STRING_LEXEME, R_PAREN_LEXEME, reset_placeholder_variable_generator(), reset_variable_generator(), RIGHT_ARROW_LEXEME, production_struct::rl_rule, rl_rule_meta(), rl_valid_template(), symbol_union::sc, lexeme_info::string, substitute_for_placeholders_in_action_list(), substitute_for_placeholders_in_condition_list(), SYM_CONSTANT_LEXEME, symbol_remove_ref(), agent_struct::sysparams, TEMPLATE_PRODUCTION_TYPE, TRACE_LOADING_SYSPARAM, TRUE, lexeme_info::type, UNDECLARED_SUPPORT, and USER_PRODUCTION_TYPE.

{
Symbol *name;
char *documentation;
condition *lhs, *lhs_top, *lhs_bottom;
action *rhs;
byte declared_support;
byte prod_type;
// voigtjr: added to parameter list so that CLI can ignore the error
// of a duplicate production with a different name
//byte rete_addition_result;
Bool rhs_okay;
Bool interrupt_on_match;
/* --- read production name --- */
if (thisAgent->lexeme.type!=SYM_CONSTANT_LEXEME) {
print (thisAgent, "Expected symbol for production name\n");
return NIL;
}
name = make_sym_constant (thisAgent, thisAgent->lexeme.string);
get_lexeme(thisAgent);
/* --- if there's already a prod with this name, excise it --- */
if (name->sc.production) {
excise_production (thisAgent, name->sc.production, (TRUE && thisAgent->sysparams[TRACE_LOADING_SYSPARAM]));
}
/* --- read optional documentation string --- */
if (thisAgent->lexeme.type==QUOTED_STRING_LEXEME) {
documentation = make_memory_block_for_string (thisAgent, thisAgent->lexeme.string);
get_lexeme(thisAgent);
} else {
documentation = NIL;
}
/* --- read optional flags --- */
declared_support = UNDECLARED_SUPPORT;
prod_type = USER_PRODUCTION_TYPE;
interrupt_on_match = FALSE;
while (TRUE) {
if (thisAgent->lexeme.type!=SYM_CONSTANT_LEXEME) break;
if (!strcmp(thisAgent->lexeme.string,":o-support")) {
declared_support = DECLARED_O_SUPPORT;
get_lexeme(thisAgent);
continue;
}
if (!strcmp(thisAgent->lexeme.string,":i-support")) {
declared_support = DECLARED_I_SUPPORT;
get_lexeme(thisAgent);
continue;
}
if (!strcmp(thisAgent->lexeme.string,":chunk")) {
prod_type = CHUNK_PRODUCTION_TYPE;
get_lexeme(thisAgent);
continue;
}
if (!strcmp(thisAgent->lexeme.string,":default")) {
get_lexeme(thisAgent);
continue;
}
if (!strcmp(thisAgent->lexeme.string,":template")) {
get_lexeme(thisAgent);
continue;
}
if (!strcmp(thisAgent->lexeme.string, ":interrupt")) {
interrupt_on_match = TRUE;
get_lexeme(thisAgent);
continue;
}
break;
} /* end of while (TRUE) */
/* --- read the LHS --- */
lhs = parse_lhs(thisAgent);
if (! lhs) {
print_with_symbols (thisAgent, "(Ignoring production %y)\n\n", name);
if (documentation) free_memory_block_for_string (thisAgent, documentation);
symbol_remove_ref (thisAgent, name);
/* if (! reading_from_top_level()) respond_to_load_errors (); AGR 527c */
return NIL;
}
/* --- read the "-->" --- */
if (thisAgent->lexeme.type!=RIGHT_ARROW_LEXEME) {
print (thisAgent, "Expected --> in production\n");
print_with_symbols (thisAgent, "(Ignoring production %y)\n\n", name);
if (documentation) free_memory_block_for_string (thisAgent, documentation);
symbol_remove_ref (thisAgent, name);
deallocate_condition_list (thisAgent, lhs);
/* if (! reading_from_top_level()) respond_to_load_errors (); AGR 527c */
return NIL;
}
get_lexeme(thisAgent);
/* --- read the RHS --- */
rhs_okay = parse_rhs (thisAgent, &rhs);
if (!rhs_okay) {
print_with_symbols (thisAgent, "(Ignoring production %y)\n\n", name);
if (documentation) free_memory_block_for_string (thisAgent, documentation);
symbol_remove_ref (thisAgent, name);
deallocate_condition_list (thisAgent, lhs);
/* if (! reading_from_top_level()) respond_to_load_errors (); AGR 527c */
return NIL;
}
/* --- finally, make sure there's a closing right parenthesis (but
don't consume it) --- */
if (thisAgent->lexeme.type!=R_PAREN_LEXEME) {
print (thisAgent, "Expected ) to end production\n");
if (documentation) free_memory_block_for_string (thisAgent, documentation);
print_with_symbols (thisAgent, "(Ignoring production %y)\n\n", name);
symbol_remove_ref (thisAgent, name);
deallocate_condition_list (thisAgent, lhs);
deallocate_action_list (thisAgent, rhs);
/* if (! reading_from_top_level()) respond_to_load_errors (); AGR 527c */
return NIL;
}
/* --- replace placeholder variables with real variables --- */
reset_variable_generator (thisAgent, lhs, rhs);
/* --- everything parsed okay, so make the production structure --- */
lhs_top = lhs;
for (lhs_bottom=lhs; lhs_bottom->next!=NIL; lhs_bottom=lhs_bottom->next);
p = make_production (thisAgent, prod_type, name, &lhs_top, &lhs_bottom, &rhs, TRUE);
if (!p) {
if (documentation) free_memory_block_for_string (thisAgent, documentation);
print_with_symbols (thisAgent, "(Ignoring production %y)\n\n", name);
symbol_remove_ref (thisAgent, name);
deallocate_condition_list (thisAgent, lhs_top);
deallocate_action_list (thisAgent, rhs);
/* if (! reading_from_top_level()) respond_to_load_errors (); AGR 527c */
return NIL;
}
if ( prod_type == TEMPLATE_PRODUCTION_TYPE )
{
if ( !rl_valid_template( p ) )
{
print_with_symbols( thisAgent, "Invalid Soar-RL template (%y)\n\n", name );
excise_production( thisAgent, p, false );
return NIL;
}
}
p->documentation = documentation;
p->declared_support = declared_support;
p->interrupt = interrupt_on_match;
*rete_addition_result = add_production_to_rete (thisAgent, p, lhs_top, NIL, TRUE);
deallocate_condition_list (thisAgent, lhs_top);
if (*rete_addition_result==DUPLICATE_PRODUCTION) {
excise_production (thisAgent, p, FALSE);
p = NIL;
}
if ( p && p->rl_rule && p->documentation )
{
rl_rule_meta( thisAgent, p );
}
return p;
}
test parse_relational_test ( agent thisAgent)

Definition at line 315 of file parser.cpp.

References agent_struct::complex_test_pool, complex_test_struct::data, EQUAL_LEXEME, FALSE, FLOAT_CONSTANT_LEXEME, get_lexeme(), GREATER_EQUAL_LEXEME, GREATER_LEXEME, GREATER_OR_EQUAL_TEST, GREATER_TEST, IDENTIFIER_LEXEME, INT_CONSTANT_LEXEME, LESS_EQUAL_GREATER_LEXEME, LESS_EQUAL_LEXEME, LESS_LEXEME, LESS_OR_EQUAL_TEST, LESS_TEST, agent_struct::lexeme, make_equality_test_without_adding_reference(), make_symbol_for_current_lexeme(), make_test_from_complex_test(), NIL, NOT_EQUAL_LEXEME, NOT_EQUAL_TEST, parse_lti(), print(), print_location_of_most_recent_lexeme(), complex_test_struct::test_info_union::referent, SAME_TYPE_TEST, SYM_CONSTANT_LEXEME, TRUE, lexeme_info::type, complex_test_struct::type, and VARIABLE_LEXEME.

Referenced by parse_simple_test().

{
byte test_type;
Bool use_equality_test;
test t;
Symbol *referent;
use_equality_test = FALSE;
test_type = NOT_EQUAL_TEST; /* unnecessary, but gcc -Wall warns without it */
/* --- read optional relation symbol --- */
switch(thisAgent->lexeme.type) {
use_equality_test = TRUE;
get_lexeme(thisAgent);
break;
test_type = NOT_EQUAL_TEST;
get_lexeme(thisAgent);
break;
test_type = LESS_TEST;
get_lexeme(thisAgent);
break;
test_type = GREATER_TEST;
get_lexeme(thisAgent);
break;
test_type = LESS_OR_EQUAL_TEST;
get_lexeme(thisAgent);
break;
test_type = GREATER_OR_EQUAL_TEST;
get_lexeme(thisAgent);
break;
test_type = SAME_TYPE_TEST;
get_lexeme(thisAgent);
break;
default:
use_equality_test = TRUE;
break;
}
// Check for long term identifier notation
bool id_lti = parse_lti(thisAgent);
/* --- read variable or constant --- */
switch (thisAgent->lexeme.type) {
case IDENTIFIER_LEXEME: // IDENTIFIER_LEXEME only possible if id_lti true due to set_lexer_allow_ids above
referent = make_symbol_for_current_lexeme(thisAgent, id_lti);
get_lexeme(thisAgent);
if (use_equality_test) {
} else {
allocate_with_pool (thisAgent, &thisAgent->complex_test_pool, &ct);
ct->type = test_type;
ct->data.referent = referent;
}
return t;
default:
print (thisAgent, "Expected variable or constant for test\n");
return NIL;
}
}
Bool parse_rhs ( agent thisAgent,
action **  dest_rhs 
)

Definition at line 1817 of file parser.cpp.

References deallocate_action_list(), FALSE, agent_struct::lexeme, action_struct::next, NIL, parse_rhs_action(), R_PAREN_LEXEME, TRUE, and lexeme_info::type.

Referenced by parse_production().

{
action *all_actions, *new_actions, *last;
all_actions = NIL;
while (thisAgent->lexeme.type!=R_PAREN_LEXEME) {
new_actions = parse_rhs_action (thisAgent);
if (new_actions) {
for (last=new_actions; last->next!=NIL; last=last->next);
last->next = all_actions;
all_actions = new_actions;
} else {
deallocate_action_list (thisAgent, all_actions);
return FALSE;
}
}
*dest_rhs = all_actions;
return TRUE;
}
action* parse_rhs_action ( agent thisAgent)

Definition at line 1729 of file parser.cpp.

References abort_with_fatal_error(), agent_struct::action_pool, BUFFER_MSG_SIZE, deallocate_action_list(), FUNCALL_ACTION, get_lexeme(), lexeme_info::id_letter, lexeme_info::id_number, IDENTIFIER_LEXEME, L_PAREN_LEXEME, agent_struct::lexeme, make_variable(), action_struct::next, NIL, parse_attr_value_make(), parse_function_call_after_lparen(), parse_lti(), print(), print_location_of_most_recent_lexeme(), R_PAREN_LEXEME, smem_lti_get_id(), smem_lti_soar_make(), SMEM_LTI_UNKNOWN_LEVEL, lexeme_info::string, symbol_remove_ref(), TRUE, lexeme_info::type, action_struct::type, action_struct::value, and VARIABLE_LEXEME.

Referenced by parse_rhs().

{
action *all_actions, *new_actions, *last;
Symbol *var = NULL;
rhs_value funcall_value;
if (thisAgent->lexeme.type!=L_PAREN_LEXEME) {
print (thisAgent, "Expected ( to begin RHS action\n");
return NIL;
}
get_lexeme(thisAgent);
// Check for long term identifier notation
bool id_lti = parse_lti(thisAgent);
if ((thisAgent->lexeme.type!=VARIABLE_LEXEME) && (thisAgent->lexeme.type!=IDENTIFIER_LEXEME)) {
/* --- the action is a function call --- */
funcall_value = parse_function_call_after_lparen (thisAgent, TRUE);
if (!funcall_value) return NIL;
allocate_with_pool (thisAgent, &thisAgent->action_pool, &all_actions);
all_actions->type = FUNCALL_ACTION;
all_actions->next = NIL;
all_actions->value = funcall_value;
return all_actions;
}
/* --- the action is a regular make action --- */
if (id_lti) {
smem_lti_id lti_id = smem_lti_get_id( thisAgent, thisAgent->lexeme.id_letter, thisAgent->lexeme.id_number );
if ( lti_id == NIL ) {
char msg[BUFFER_MSG_SIZE];
strncpy(msg, "parser.c: Internal error: invalid long-term identifier found in make_symbol_for_current_lexeme\n", BUFFER_MSG_SIZE);
msg[BUFFER_MSG_SIZE - 1] = 0; /* ensure null termination */
abort_with_fatal_error(thisAgent, msg);
}
else {
var = smem_lti_soar_make( thisAgent, lti_id, thisAgent->lexeme.id_letter, thisAgent->lexeme.id_number, SMEM_LTI_UNKNOWN_LEVEL );
}
}
else {
var = make_variable (thisAgent, thisAgent->lexeme.string);
}
get_lexeme(thisAgent);
all_actions = NIL;
while (thisAgent->lexeme.type!=R_PAREN_LEXEME) {
new_actions = parse_attr_value_make (thisAgent, var);
if (new_actions) {
for (last=new_actions; last->next!=NIL; last=last->next);
last->next = all_actions;
all_actions = new_actions;
} else {
symbol_remove_ref (thisAgent, var);
deallocate_action_list (thisAgent, all_actions);
return NIL;
}
}
get_lexeme(thisAgent); /* consume the right parenthesis */
symbol_remove_ref (thisAgent, var);
return all_actions;
}
rhs_value parse_rhs_value ( agent thisAgent)

Definition at line 1225 of file parser.cpp.

References FALSE, FLOAT_CONSTANT_LEXEME, get_lexeme(), IDENTIFIER_LEXEME, INT_CONSTANT_LEXEME, L_PAREN_LEXEME, agent_struct::lexeme, make_symbol_for_current_lexeme(), parse_function_call_after_lparen(), parse_lti(), print(), print_location_of_most_recent_lexeme(), SYM_CONSTANT_LEXEME, symbol_to_rhs_value(), lexeme_info::type, and VARIABLE_LEXEME.

Referenced by parse_attr_value_make(), parse_function_call_after_lparen(), and parse_preferences().

{
if (thisAgent->lexeme.type==L_PAREN_LEXEME) {
get_lexeme(thisAgent);
}
// Check for long term identifier notation
bool id_lti = parse_lti(thisAgent);
if ((thisAgent->lexeme.type==SYM_CONSTANT_LEXEME) ||
(thisAgent->lexeme.type==INT_CONSTANT_LEXEME) ||
(thisAgent->lexeme.type==VARIABLE_LEXEME) ||
(thisAgent->lexeme.type==IDENTIFIER_LEXEME)) {
// IDENTIFIER_LEXEME only possible if id_lti true due to set_lexer_allow_ids above
get_lexeme(thisAgent);
return rv;
}
print (thisAgent, "Illegal value for RHS value\n");
return FALSE;
}
test parse_simple_test ( agent thisAgent)

Definition at line 446 of file parser.cpp.

References LESS_LESS_LEXEME, agent_struct::lexeme, parse_disjunction_test(), parse_relational_test(), and lexeme_info::type.

Referenced by parse_test().

{
if (thisAgent->lexeme.type==LESS_LESS_LEXEME)
return parse_disjunction_test(thisAgent);
return parse_relational_test(thisAgent);
}
condition* parse_tail_of_conds_for_one_id ( agent thisAgent)

Definition at line 887 of file parser.cpp.

References three_field_tests_struct::attr_test, agent_struct::condition_pool, condition_struct::data, deallocate_condition_list(), FALSE, get_lexeme(), three_field_tests_struct::id_test, agent_struct::lexeme, make_placeholder_test(), condition_struct::next, NIL, parse_attr_value_tests(), POSITIVE_CONDITION, condition_struct::prev, R_PAREN_LEXEME, condition_struct::test_for_acceptable_preference, condition_struct::condition_main_data_union::tests, lexeme_info::type, condition_struct::type, and three_field_tests_struct::value_test.

Referenced by parse_conds_for_one_id().

{
condition *first_c, *last_c, *new_conds;
/* --- if no <attr_value_tests> are given, create a dummy one --- */
if (thisAgent->lexeme.type==R_PAREN_LEXEME) {
get_lexeme(thisAgent); /* consume the right parenthesis */
allocate_with_pool (thisAgent, &thisAgent->condition_pool, &c);
c->next = NIL;
c->prev = NIL;
c->data.tests.attr_test = make_placeholder_test (thisAgent, 'a');
c->data.tests.value_test = make_placeholder_test (thisAgent, 'v');
return c;
}
/* --- read <attr_value_tests>* --- */
first_c = NIL;
last_c = NIL;
while (thisAgent->lexeme.type!=R_PAREN_LEXEME) {
new_conds = parse_attr_value_tests (thisAgent);
if (!new_conds) {
deallocate_condition_list (thisAgent, first_c);
return NIL;
}
if (last_c) last_c->next = new_conds; else first_c = new_conds;
new_conds->prev = last_c;
for (last_c=new_conds; last_c->next!=NIL; last_c=last_c->next);
}
/* --- reached the end of the condition --- */
get_lexeme(thisAgent); /* consume the right parenthesis */
return first_c;
}
test parse_test ( agent thisAgent)
condition* parse_value_test_star ( agent thisAgent,
char  first_letter 
)

Definition at line 634 of file parser.cpp.

References add_new_test_to_test(), three_field_tests_struct::attr_test, agent_struct::condition_pool, condition_struct::data, deallocate_condition_list(), FALSE, get_lexeme(), three_field_tests_struct::id_test, insert_at_head_of_dll, L_PAREN_LEXEME, agent_struct::lexeme, make_placeholder_test(), MINUS_LEXEME, condition_struct::next, NIL, parse_conds_for_one_id(), parse_test(), PLUS_LEXEME, POSITIVE_CONDITION, condition_struct::prev, R_PAREN_LEXEME, condition_struct::test_for_acceptable_preference, test_includes_equality_test_for_symbol(), condition_struct::condition_main_data_union::tests, TRUE, lexeme_info::type, condition_struct::type, UP_ARROW_LEXEME, and three_field_tests_struct::value_test.

Referenced by parse_attr_value_tests().

{
condition *c, *last_c, *first_c, *new_conds;
test value_test;
Bool acceptable;
if ((thisAgent->lexeme.type==MINUS_LEXEME) ||
(thisAgent->lexeme.type==UP_ARROW_LEXEME) ||
(thisAgent->lexeme.type==R_PAREN_LEXEME)) {
/* --- value omitted, so create dummy value test --- */
allocate_with_pool (thisAgent, &thisAgent->condition_pool, &c);
c->next = c->prev = NIL;
c->data.tests.value_test = make_placeholder_test (thisAgent, first_letter);
return c;
}
first_c = NIL;
last_c = NIL;
do {
if (thisAgent->lexeme.type==L_PAREN_LEXEME) {
/* --- read <conds_for_one_id>, take the id_test from it --- */
new_conds = parse_conds_for_one_id (thisAgent, first_letter, &value_test);
if (!new_conds) {
deallocate_condition_list (thisAgent, first_c);
return NIL;
}
} else {
/* --- read <value_test> --- */
new_conds = NIL;
value_test = parse_test(thisAgent);
if (!value_test) {
deallocate_condition_list (thisAgent, first_c);
return NIL;
}
add_new_test_to_test (thisAgent, &value_test,make_placeholder_test(thisAgent, first_letter));
}
}
/* --- check for acceptable preference indicator --- */
acceptable = FALSE;
if (thisAgent->lexeme.type==PLUS_LEXEME) { acceptable = TRUE; get_lexeme(thisAgent); }
/* --- build condition using the new value test --- */
allocate_with_pool (thisAgent, &thisAgent->condition_pool, &c);
insert_at_head_of_dll (new_conds, c, next, prev);
c->data.tests.value_test = value_test;
/* --- add new conditions to the end of the list --- */
if (last_c) last_c->next = new_conds; else first_c = new_conds;
new_conds->prev = last_c;
for (last_c=new_conds; last_c->next!=NIL; last_c=last_c->next);
} while ((thisAgent->lexeme.type!=MINUS_LEXEME) &&
(thisAgent->lexeme.type!=UP_ARROW_LEXEME) &&
(thisAgent->lexeme.type!=R_PAREN_LEXEME));
return first_c;
}
void reset_placeholder_variable_generator ( agent thisAgent)

Definition at line 57 of file parser.cpp.

References agent_struct::placeholder_counter.

Referenced by parse_production().

{
int i;
for (i=0; i<26; i++) thisAgent->placeholder_counter[i] = 1;
}
void substitute_for_placeholders_in_action_list ( agent thisAgent,
action a 
)
void substitute_for_placeholders_in_condition_list ( agent thisAgent,
condition cond 
)
void substitute_for_placeholders_in_symbol ( agent thisAgent,
Symbol **  sym 
)

Definition at line 113 of file parser.cpp.

References variable_struct::current_binding_value, FALSE, generate_new_variable(), symbol_add_ref(), symbol_remove_ref(), TRUE, symbol_union::var, and VARIABLE_SYMBOL_TYPE.

Referenced by substitute_for_placeholders_in_action_list(), and substitute_for_placeholders_in_test().

{
char prefix[3];
Symbol *var;
Bool just_created;
/* --- if not a variable, do nothing --- */
if ((*sym)->common.symbol_type!=VARIABLE_SYMBOL_TYPE) return;
/* --- if not a placeholder variable, do nothing --- */
if (*((*sym)->var.name + 1) != '#') return;
just_created = FALSE;
if (! (*sym)->var.current_binding_value) {
prefix[0] = *((*sym)->var.name + 2);
prefix[1] = '*';
prefix[2] = 0;
(*sym)->var.current_binding_value = generate_new_variable (thisAgent, prefix);
just_created = TRUE;
}
var = (*sym)->var.current_binding_value;
symbol_remove_ref (thisAgent, *sym);
*sym = var;
if (!just_created) symbol_add_ref (var);
}
void substitute_for_placeholders_in_test ( agent thisAgent,
test t 
)

Variable Documentation

const char* help_on_lhs_grammar[]
Initial value:
{
"Grammar for left hand sides of productions:",
"",
" <lhs> ::= <cond>+",
" <cond> ::= <positive_cond> | - <positive_cond>",
" <positive_cond> ::= <conds_for_one_id> | { <cond>+ }",
" <conds_for_one_id> ::= ( [state|impasse] [<id_test>] <attr_value_tests>* )",
" <id_test> ::= <test>",
" <attr_value_tests> ::= [-] ^ <attr_test> [.<attr_test>]* <value_test>*",
" <attr_test> ::= <test>",
" <value_test> ::= <test> [+] | <conds_for_one_id> [+]",
"",
" <test> ::= <conjunctive_test> | <simple_test>",
" <conjunctive_test> ::= { <simple_test>+ }",
" <simple_test> ::= <disjunction_test> | <relational_test>",
" <disjunction_test> ::= << <constant>* >>",
" <relational_test> ::= [<relation>] <single_test>",
" <relation> ::= <> | < | > | <= | >= | = | <=>",
" <single_test> ::= <variable> | <constant>",
" <constant> ::= sym_constant | int_constant | float_constant",
" <variable> ::= variable | lti",
"",
"See also: rhs-grammar, sp",
0 }

Definition at line 224 of file parser.cpp.

const char* help_on_rhs_grammar[]
Initial value:
{
"Grammar for right hand sides of productions:",
"",
" <rhs> ::= <rhs_action>*",
" <rhs_action> ::= ( <variable> <attr_value_make>+ ) | <function_call>",
" <function_call> ::= ( <function_name> <rhs_value>* )",
" <function_name> ::= sym_constant | + | -",
" <rhs_value> ::= <constant> | <function_call> | <variable>",
" <constant> ::= sym_constant | int_constant | float_constant",
" <attr_value_make> ::= ^ <rhs_value> <value_make>+",
" <value_make> ::= <rhs_value> <preferences>",
" <variable> ::= variable | lti",
"",
" <preferences> ::= [,] | <preference_specifier>+",
" <preference-specifier> ::= <naturally-unary-preference> [,]",
" | <forced-unary-preference>",
" | <binary-preference> <rhs_value> [,]",
" <naturally-unary-preference> ::= + | - | ! | ~ | @",
" <binary-preference> ::= > | = | < | &",
" <any-preference> ::= <naturally-unary-preference> | <binary-preference>",
" <forced-unary-preference> ::= <binary-preference> ",
" {<any-preference> | , | ) | ^}",
" ;but the parser shouldn't consume the <any-preference>, \")\" or \"^\"",
" lexeme here",
"",
"See also: lhs-grammar, sp",
0 }

Definition at line 1099 of file parser.cpp.