00001 %{
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <plang/term.h>
00022 #include <plang/context.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <stdarg.h>
00026 #include <stdlib.h>
00027 #include <errno.h>
00028 #include "parser.h"
00029 #include "term-priv.h"
00030 #include "parser-priv.h"
00031 #include "context-priv.h"
00032
00033 extern int yylex(YYSTYPE *lval, YYLTYPE *loc, p_context *context, yyscan_t yyscanner);
00034 extern p_input_stream *p_term_get_extra(yyscan_t yyscanner);
00035 extern p_term *p_term_lex_create_variable
00036 (p_context *context, p_input_stream *stream, const char *name);
00037 extern unsigned int p_term_lex_variable_count
00038 (p_input_stream *stream, p_term *var);
00039
00040 #define input_stream (p_term_get_extra(yyscanner))
00041
00042 static void yyerror(YYLTYPE *loc, p_context *context, yyscan_t yyscanner, const char *msg)
00043 {
00044 p_input_stream *stream = p_term_get_extra(yyscanner);
00045 if (stream->filename)
00046 fprintf(stderr, "%s:%d: %s\n", stream->filename, loc->first_line, msg);
00047 else
00048 fprintf(stderr, "%d: %s\n", loc->first_line, msg);
00049 ++(stream->error_count);
00050 }
00051
00052 static void yyerror_printf(YYLTYPE *loc, p_context *context, p_input_stream *stream, const char *format, ...)
00053 {
00054 va_list va;
00055 va_start(va, format);
00056 if (stream && stream->filename)
00057 fprintf(stderr, "%s:%d: ", stream->filename, loc->first_line);
00058 else if (stream)
00059 fprintf(stderr, "%d: ", loc->first_line);
00060 vfprintf(stderr, format, va);
00061 putc('\n', stderr);
00062 if (stream)
00063 ++(stream->error_count);
00064 va_end(va);
00065 }
00066
00067
00068
00069
00070 #define YYMALLOC GC_MALLOC
00071 #define YYFREE GC_FREE
00072
00073
00074 static p_term *make_unary_term(p_context *context, const char *name, p_term *term)
00075 {
00076 p_term *result = p_term_create_functor
00077 (context, p_term_create_atom(context, (name)), 1);
00078 p_term_bind_functor_arg(result, 0, (term));
00079 return result;
00080 }
00081 #define unary_term(name,term) make_unary_term(context, (name), (term))
00082
00083
00084 static p_term *make_binary_term(p_context *context, const char *name, p_term *term1, p_term *term2)
00085 {
00086 p_term *result = p_term_create_functor
00087 (context, p_term_create_atom(context, (name)), 2);
00088 p_term_bind_functor_arg(result, 0, (term1));
00089 p_term_bind_functor_arg(result, 1, (term2));
00090 return result;
00091 }
00092 #define binary_term(name,term1,term2) make_binary_term(context, (name), (term1), (term2))
00093
00094
00095 static p_term *make_ternary_term(p_context *context, const char *name, p_term *term1, p_term *term2, p_term *term3)
00096 {
00097 p_term *result = p_term_create_functor
00098 (context, p_term_create_atom(context, (name)), 3);
00099 p_term_bind_functor_arg(result, 0, (term1));
00100 p_term_bind_functor_arg(result, 1, (term2));
00101 p_term_bind_functor_arg(result, 2, (term3));
00102 return result;
00103 }
00104 #define ternary_term(name,term1,term2,term3) make_ternary_term(context, (name), (term1), (term2), (term3))
00105
00106
00107
00108 #define append_r_list(dest, src, new_term, oper) \
00109 do { \
00110 p_term *term; \
00111 if (src.r_hole) { \
00112 term = p_term_create_functor \
00113 (context, p_term_create_atom(context, oper), 2); \
00114 p_term_bind_functor_arg(term, 0, src.r_tail); \
00115 p_term_bind_functor_arg(src.r_hole, 1, term); \
00116 dest.r_head = src.r_head; \
00117 dest.r_hole = term; \
00118 dest.r_tail = new_term; \
00119 } else { \
00120 term = p_term_create_functor \
00121 (context, p_term_create_atom(context, oper), 2); \
00122 p_term_bind_functor_arg(term, 0, src.r_tail); \
00123 dest.r_head = term; \
00124 dest.r_hole = term; \
00125 dest.r_tail = new_term; \
00126 } \
00127 } while (0)
00128 #define finalize_r_list(list) \
00129 (list.r_hole ? \
00130 (p_term_bind_functor_arg(list.r_hole, 1, list.r_tail), \
00131 list.r_head) : list.r_tail)
00132 #define create_r_list(list,term) \
00133 do { \
00134 list.r_head = 0; \
00135 list.r_hole = 0; \
00136 list.r_tail = term; \
00137 } while (0)
00138
00139
00140 #define append_list(dest,src,term) \
00141 do { \
00142 dest.l_head = src.l_head; \
00143 dest.l_tail = p_term_create_list(context, term, 0); \
00144 p_term_set_tail(src.l_tail, dest.l_tail); \
00145 } while (0)
00146 #define append_lists(dest,src1,src2) \
00147 do { \
00148 if (src1.l_head && src2.l_head) { \
00149 dest.l_head = src1.l_head; \
00150 dest.l_tail = src2.l_tail; \
00151 p_term_set_tail(src1.l_tail, src2.l_head); \
00152 } else if (src1.l_head) { \
00153 dest.l_head = src1.l_head; \
00154 dest.l_tail = src1.l_tail; \
00155 } else if (src2.l_head) { \
00156 dest.l_head = src2.l_head; \
00157 dest.l_tail = src2.l_tail; \
00158 } else { \
00159 dest.l_head = 0; \
00160 dest.l_tail = 0; \
00161 } \
00162 } while (0)
00163 #define create_list(list,term) \
00164 do { \
00165 list.l_head = p_term_create_list(context, term, 0); \
00166 list.l_tail = list.l_head; \
00167 } while (0)
00168 #define create_empty_list(list) \
00169 do { \
00170 list.l_head = 0; \
00171 list.l_tail = 0; \
00172 } while (0)
00173 #define finalize_list(list) \
00174 ((list).l_head ? \
00175 (p_term_set_tail((list).l_tail, p_term_nil_atom(context)), \
00176 (list).l_head) : p_term_nil_atom(context))
00177 #define finalize_list_tail(list,tail) \
00178 (p_term_set_tail((list).l_tail, (tail)), (list).l_head)
00179
00180
00181
00182 static p_term *make_class_declaration
00183 (p_context *context, p_term *name, p_term *parent,
00184 p_term *vars, p_term *clauses)
00185 {
00186 p_term *term;
00187 term = p_term_create_functor
00188 (context, p_term_create_atom(context, "new_class"), 4);
00189 p_term_bind_functor_arg(term, 0, name);
00190 p_term_bind_functor_arg(term, 1, parent);
00191 p_term_bind_functor_arg(term, 2, vars);
00192 p_term_bind_functor_arg(term, 3, clauses);
00193 return make_unary_term(context, "?-", term);
00194 }
00195
00196
00197 #define clear_variables() (input_stream->num_variables = 0)
00198
00199
00200 static p_term *add_debug_line
00201 (p_context *context, p_input_stream *stream,
00202 YYLTYPE *loc, p_term *term)
00203 {
00204 p_term *line;
00205 if (!context->debug)
00206 return term;
00207 if (!stream->filename_string) {
00208 stream->filename_string =
00209 p_term_create_string(context, stream->filename);
00210 }
00211 line = p_term_create_functor(context, context->line_atom, 3);
00212 p_term_bind_functor_arg(line, 0, stream->filename_string);
00213 p_term_bind_functor_arg
00214 (line, 1, p_term_create_integer(context, loc->first_line));
00215 p_term_bind_functor_arg(line, 2, term);
00216 return line;
00217 }
00218 #define add_debug(loc, term) \
00219 (add_debug_line(context, input_stream, &(loc), term))
00220
00221 static char *p_concat_strings
00222 (const char *str1, size_t len1, const char *str2, size_t len2,
00223 const char *str3, size_t len3, const char *str4, size_t len4)
00224 {
00225 char *str = (char *)malloc(len1 + len2 + len3 + len4 + 1);
00226 if (len1 > 0)
00227 memcpy(str, str1, len1);
00228 if (len2 > 0)
00229 memcpy(str + len1, str2, len2);
00230 if (len3 > 0)
00231 memcpy(str + len1 + len2, str3, len3);
00232 if (len4 > 0)
00233 memcpy(str + len1 + len2 + len3, str4, len4);
00234 str[len1 + len2 + len3 + len4] = '\0';
00235 return str;
00236 }
00237
00238 static int p_context_consult_file_in_path
00239 (p_context *context, const char *pathname, const char *name,
00240 int has_extn, p_input_stream *stream)
00241 {
00242 int error;
00243 char *path;
00244 size_t len = strlen(pathname);
00245 const char *sep = 0;
00246 size_t sep_len = 0;
00247 #if defined(P_WIN32)
00248 if (len > 0 && pathname[len - 1] != '/' && pathname[len - 1] != '\\') {
00249 sep = "\\";
00250 sep_len = 1;
00251 }
00252 #else
00253 if (len > 0 && pathname[len - 1] != '/') {
00254 sep = "/";
00255 sep_len = 1;
00256 }
00257 #endif
00258 if (has_extn) {
00259 path = p_concat_strings
00260 (pathname, strlen(pathname), sep, sep_len,
00261 name, strlen(name), 0, 0);
00262 } else {
00263 path = p_concat_strings
00264 (pathname, strlen(pathname), sep, sep_len,
00265 name, strlen(name), ".lp", 3);
00266 }
00267 error = p_context_consult_file(context, path, P_CONSULT_ONCE);
00268 if (error == 0) {
00269
00270 free(path);
00271 return 1;
00272 } else if (error == EINVAL) {
00273
00274 if (stream)
00275 ++(stream->error_count);
00276 free(path);
00277 return 0;
00278 }
00279 free(path);
00280 return -1;
00281 }
00282
00283 static int p_context_import
00284 (YYLTYPE *loc, p_context *context, p_input_stream *stream,
00285 const char *name)
00286 {
00287 const char *parent_filename;
00288 size_t len, len2;
00289 int has_extn, has_dir, is_root, error;
00290 char *path;
00291 int result;
00292
00293
00294 parent_filename = (stream ? stream->filename : 0);
00295 len = parent_filename ? strlen(parent_filename) : 0;
00296 while (len > 0) {
00297 #if defined(P_WIN32)
00298 if (parent_filename[len - 1] == '/' ||
00299 parent_filename[len - 1] == '\\')
00300 break;
00301 #else
00302 if (parent_filename[len - 1] == '/')
00303 break;
00304 #endif
00305 --len;
00306 }
00307 if (!len) {
00308 #if defined(P_WIN32)
00309 parent_filename = ".\\";
00310 #else
00311 parent_filename = "./";
00312 #endif
00313 len = 2;
00314 }
00315
00316
00317
00318 len2 = strlen(name);
00319 if (!len2) {
00320 yyerror_printf(loc, context, stream, "empty import name");
00321 return 0;
00322 }
00323 has_extn = 0;
00324 while (len2 > 0) {
00325 #if defined(P_WIN32)
00326 if (name[len2 - 1] == '/' || name[len2 - 1] == '\\')
00327 break;
00328 #else
00329 if (name[len2 - 1] == '/')
00330 break;
00331 #endif
00332 if (name[len2 - 1] == '.')
00333 has_extn = 1;
00334 --len2;
00335 }
00336 has_dir = (len2 > 0);
00337
00338
00339 is_root = 0;
00340 if (name[0] == '/') {
00341 is_root = 1;
00342 #if defined(P_WIN32)
00343 } else if (name[0] == '\\') {
00344 is_root = 1;
00345 } else if (((name[0] >= 'a' && name[0] <= 'z') ||
00346 (name[0] >= 'A' && name[0] <= 'Z'))) {
00347 if (name[1] == ':' && (name[2] == '/' || name[2] == '\\'))
00348 is_root = 1;
00349 #endif
00350 }
00351
00352
00353 if (is_root) {
00354 if (has_extn)
00355 path = p_concat_strings(name, strlen(name), 0, 0, 0, 0, 0, 0);
00356 else
00357 path = p_concat_strings(name, strlen(name), ".lp", 3, 0, 0, 0, 0);
00358 } else {
00359 if (has_extn) {
00360 path = p_concat_strings
00361 (parent_filename, len, name, strlen(name), 0, 0, 0, 0);
00362 } else {
00363 path = p_concat_strings
00364 (parent_filename, len, name, strlen(name), ".lp", 3, 0, 0);
00365 }
00366 }
00367 error = p_context_consult_file(context, path, P_CONSULT_ONCE);
00368 if (error == 0) {
00369
00370 free(path);
00371 return 1;
00372 } else if (error == EINVAL) {
00373
00374 if (stream)
00375 ++(stream->error_count);
00376 free(path);
00377 return 0;
00378 }
00379 free(path);
00380
00381
00382 if (!has_dir) {
00383 size_t index;
00384 for (index = 0; index < context->user_imports.num_paths; ++index) {
00385 result = p_context_consult_file_in_path
00386 (context, context->user_imports.paths[index],
00387 name, has_extn, stream);
00388 if (result >= 0)
00389 return result;
00390 }
00391 for (index = 0; index < context->system_imports.num_paths; ++index) {
00392 result = p_context_consult_file_in_path
00393 (context, context->system_imports.paths[index],
00394 name, has_extn, stream);
00395 if (result >= 0)
00396 return result;
00397 }
00398 }
00399
00400
00401 return -1;
00402 }
00403
00404 int p_context_builtin_import(p_context *context, const char *name)
00405 {
00406 return p_context_import(0, context, 0, name);
00407 }
00408
00409
00410 static p_term *create_clause_head
00411 (p_context *context, p_input_stream *stream,
00412 p_term *member_name, p_term **args, size_t num_args,
00413 int is_static)
00414 {
00415 size_t index;
00416 p_term *head = p_term_create_functor
00417 (context, p_term_create_member_name
00418 (context, stream->class_name, member_name),
00419 (int)(num_args + (is_static ? 0 : 1)));
00420 if (is_static) {
00421 for (index = 0; index < num_args; ++index)
00422 p_term_bind_functor_arg(head, index, args[index]);
00423 } else {
00424 p_term *self = p_term_lex_create_variable
00425 (context, stream, "Self");
00426 p_term_bind_functor_arg(head, 0, self);
00427 for (index = 0; index < num_args; ++index)
00428 p_term_bind_functor_arg(head, index + 1, args[index]);
00429 }
00430 if (args)
00431 GC_FREE(args);
00432 return head;
00433 }
00434
00435 %}
00436
00437
00438 %name-prefix="p_term_"
00439 %pure-parser
00440 %error-verbose
00441 %locations
00442 %parse-param {p_context *context}
00443 %parse-param {yyscan_t yyscanner}
00444 %lex-param {p_context *context}
00445 %lex-param {yyscan_t yyscanner}
00446
00447
00448 %union {
00449 p_term *term;
00450 struct {
00451 p_term *l_head;
00452 p_term *l_tail;
00453 } list;
00454 struct {
00455 p_term **args;
00456 size_t num_args;
00457 size_t max_args;
00458 } arg_list;
00459 struct {
00460 p_term *r_head;
00461 p_term *r_tail;
00462 p_term *r_hole;
00463 } r_list;
00464 struct {
00465 p_term *vars;
00466 p_term *clauses;
00467 int has_constructor;
00468 } class_body;
00469 struct {
00470 struct {
00471 p_term *l_head;
00472 p_term *l_tail;
00473 } vars;
00474 struct {
00475 p_term *l_head;
00476 p_term *l_tail;
00477 } clauses;
00478 int has_constructor;
00479 } member_list;
00480 struct {
00481 p_term *object;
00482 p_term *name;
00483 int auto_create;
00484 } member_ref;
00485 struct {
00486 p_term *name;
00487 p_term *kind;
00488 p_term *head;
00489 p_term *body;
00490 int has_constructor;
00491 } clause;
00492 struct {
00493 p_term *l_head;
00494 p_term *l_tail;
00495 int is_default;
00496 } case_labels;
00497 struct {
00498 p_term *l_head;
00499 p_term *l_tail;
00500 p_term *default_case;
00501 int is_default;
00502 } switch_case;
00503 struct {
00504 p_term *case_list;
00505 p_term *default_case;
00506 } switch_body;
00507 }
00508
00509
00510 %token K_ATOM "an atom"
00511 %token K_INTEGER "an integer"
00512 %token K_REAL "a floating-point number"
00513 %token K_STRING "a string"
00514 %token K_VARIABLE "a variable"
00515 %token K_COLON_DASH "`:-'"
00516 %token K_QUEST_DASH "`?-'"
00517 %token K_TEST_GOAL "`??--'"
00518 %token K_READ_TERM "`??-'"
00519 %token K_ARROW "`->'"
00520 %token K_DARROW "`-->'"
00521 %token K_DOT_TERMINATOR "`.'"
00522 %token K_OR "`||'"
00523 %token K_AND "`&&'"
00524 %token K_NOT "`\\+'"
00525 %token K_NE "`!='"
00526 %token K_TERM_EQ "`=='"
00527 %token K_TERM_NE "`!=='"
00528 %token K_TERM_LT "`@<'"
00529 %token K_TERM_LE "`@<='"
00530 %token K_TERM_GT "`@>'"
00531 %token K_TERM_GE "`@>='"
00532 %token K_UNIV "`=..'"
00533 %token K_NUM_EQ "`=:='"
00534 %token K_NUM_NE "`=!='"
00535 %token K_NUM_LT "`<'"
00536 %token K_NUM_LE "`<='"
00537 %token K_NUM_GT "`>'"
00538 %token K_NUM_GE "`>='"
00539 %token K_NUM_GETS "`::='"
00540 %token K_NUM_BT_GETS "`::=='"
00541 %token K_BITWISE_AND "`/\\'"
00542 %token K_BITWISE_OR "`\\/'"
00543 %token K_BITWISE_NOT "`\\'"
00544 %token K_SHIFT_LEFT "`<<'"
00545 %token K_SHIFT_RIGHT "`>>'"
00546 %token K_USHIFT_RIGHT "`>>>'"
00547 %token K_EXP "`**'"
00548 %token K_DOT_DOT "`..'"
00549 %token K_GETS "`:='"
00550 %token K_BT_GETS "`:=='"
00551 %token K_IMPLIES "`=>'"
00552 %token K_EQUIV "`<=>'"
00553 %token K_ABSTRACT "`abstract'"
00554 %token K_CASE "`case'"
00555 %token K_CATCH "`catch'"
00556 %token K_CLASS "`class'"
00557 %token K_DEFAULT "`default'"
00558 %token K_DO "`do'"
00559 %token K_ELSE "`else'"
00560 %token K_FOR "`for'"
00561 %token K_IF "`if'"
00562 %token K_IN "`in'"
00563 %token K_IS "`is'"
00564 %token K_MOD "`mod'"
00565 %token K_NEW "`new'"
00566 %token K_REM "`rem'"
00567 %token K_STATIC "`static'"
00568 %token K_SWITCH "`switch'"
00569 %token K_TRY "`try'"
00570 %token K_WHILE "`while'"
00571 %token K_VAR "`var'"
00572
00573
00574 %type <term> K_ATOM K_INTEGER K_REAL K_STRING K_VARIABLE
00575
00576 %type <term> declaration directive goal clause callable_term
00577 %type <term> class_declaration atom opt_parent member_name
00578
00579 %type <term> term not_term compare_term additive_term
00580 %type <term> multiplicative_term power_term unary_term
00581 %type <term> primary_term condition if_term argument_term
00582 %type <term> new_term member_var bracketed_term head_argument_term
00583 %type <term> implies_term or_term
00584 %type <term> argument_implies_term argument_or_term
00585
00586 %type <term> statement if_statement compound_statement
00587 %type <term> loop_statement unbind_vars try_statement
00588 %type <term> catch_clause switch_statement clause_body
00589 %type <term> confidence
00590
00591 %type <term> dcg_clause dcg_body dcg_unary_term
00592 %type <term> dcg_primitive_term
00593
00594 %type <case_labels> case_label case_labels
00595 %type <switch_case> switch_cases switch_case
00596 %type <switch_body> switch_body
00597
00598 %type <list> list_members declaration_list
00599 %type <list> member_vars unbind_var_list catch_clauses
00600
00601 %type <arg_list> arguments
00602 %type <r_list> statements and_term argument_and_term dcg_term
00603 %type <class_body> class_body
00604 %type <member_list> class_members class_member
00605 %type <member_ref> member_reference
00606 %type <clause> member_clause member_clause_head
00607 %type <clause> regular_member_clause_head
00608
00609
00610
00611
00612 %expect 3
00613
00614 %start file
00615 %%
00616
00617 file
00618 : declaration_list {
00619 input_stream->declarations = finalize_list($1);
00620 }
00621 | K_READ_TERM term K_DOT_TERMINATOR {
00622 input_stream->declarations =
00623 p_term_create_list
00624 (context, unary_term("\?\?-", $2),
00625 context->nil_atom);
00626 }
00627 |
00628 ;
00629
00630 declaration_list
00631 : declaration_list declaration {
00632 p_term *decl = add_debug(@2, $2);
00633 append_list($$, $1, decl);
00634 clear_variables();
00635 }
00636 | declaration {
00637 p_term *decl = add_debug(@1, $1);
00638 create_list($$, decl);
00639 clear_variables();
00640 }
00641 ;
00642
00643 declaration
00644 : clause { $$ = $1; }
00645 | directive { $$ = $1; }
00646 | goal { $$ = $1; }
00647 | class_declaration { $$ = $1; }
00648 | dcg_clause { $$ = $1; }
00649 | error K_DOT_TERMINATOR {
00650
00651 $$ = unary_term("?-", context->true_atom);
00652 }
00653 ;
00654
00655 directive
00656 : K_COLON_DASH callable_term K_DOT_TERMINATOR {
00657 if (p_term_type($2) == P_TERM_FUNCTOR &&
00658 p_term_arg_count($2) == 1 &&
00659 p_term_functor($2) ==
00660 p_term_create_atom(context, "initialization")) {
00661
00662 $$ = unary_term("?-", add_debug(@2, p_term_arg($2, 0)));
00663 } else if (p_term_type($2) == P_TERM_FUNCTOR &&
00664 p_term_arg_count($2) == 1 &&
00665 p_term_functor($2) ==
00666 p_term_create_atom(context, "import")) {
00667
00668 p_term *name = p_term_deref(p_term_arg($2, 0));
00669 if (!name || (name->header.type != P_TERM_ATOM &&
00670 name->header.type != P_TERM_STRING)) {
00671 yyerror_printf
00672 (&(@2), context, input_stream,
00673 "import name is not an atom or string");
00674 } else {
00675 int result = p_context_import
00676 (&(@2), context, input_stream,
00677 p_term_name(name));
00678 if (result < 0) {
00679 yyerror_printf
00680 (&(@2), context, input_stream,
00681 "cannot locate import `%s'", name);
00682 }
00683 }
00684 $$ = unary_term(":-", $2);
00685 } else {
00686
00687 if (p_goal_call_from_parser(context, add_debug(@2, $2))
00688 != P_RESULT_TRUE) {
00689 ++(input_stream->error_count);
00690 }
00691 $$ = unary_term(":-", $2);
00692 }
00693 }
00694 ;
00695
00696 goal
00697 : K_QUEST_DASH term K_DOT_TERMINATOR {
00698 $$ = unary_term("?-", add_debug(@2, $2));
00699 }
00700 | K_QUEST_DASH compound_statement {
00701 $$ = unary_term("?-", add_debug(@2, $2));
00702 }
00703 | K_TEST_GOAL term K_DOT_TERMINATOR {
00704
00705
00706 $$ = unary_term("\?\?--", $2);
00707 }
00708 | K_TEST_GOAL compound_statement {
00709 $$ = unary_term("\?\?--", $2);
00710 }
00711 ;
00712
00713 clause
00714 : callable_term clause_body { $$ = binary_term(":-", $1, $2); }
00715 ;
00716
00717 clause_body
00718 : K_DOT_TERMINATOR { $$ = context->true_atom; }
00719 | compound_statement { $$ = $1; }
00720 | K_SHIFT_LEFT confidence K_SHIFT_RIGHT K_DOT_TERMINATOR {
00721 $$ = unary_term("$$fuzzy", $2);
00722 }
00723 | K_SHIFT_LEFT confidence K_SHIFT_RIGHT compound_statement {
00724 $$ = binary_term(",", unary_term("$$fuzzy", $2), $4);
00725 }
00726 ;
00727
00728 confidence
00729 : K_INTEGER { $$ = $1; }
00730 | K_REAL { $$ = $1; }
00731 ;
00732
00733 callable_term
00734 : atom { $$ = $1; }
00735 | atom '(' ')' { $$ = $1; }
00736 | atom '(' arguments ')' {
00737 if ($1 == context->dot_atom && $3.num_args == 2) {
00738 yyerror_printf
00739 (&(@1), context, input_stream,
00740 "(.)/2 cannot be used as a predicate name");
00741 }
00742 $$ = p_term_create_functor_with_args
00743 (context, $1, $3.args, (int)($3.num_args));
00744 GC_FREE($3.args);
00745 }
00746 ;
00747
00748
00749 atom
00750 : K_ATOM { $$ = $1; }
00751 | K_VAR { $$ = p_term_create_atom(context, "var"); }
00752 | K_CATCH { $$ = p_term_create_atom(context, "catch"); }
00753 | K_CLASS { $$ = p_term_create_atom(context, "class"); }
00754 | K_STATIC { $$ = p_term_create_atom(context, "static"); }
00755 | K_ABSTRACT { $$ = p_term_create_atom(context, "abstract"); }
00756 ;
00757
00758 arguments
00759 : arguments ',' head_argument_term {
00760 $$ = $1;
00761 if ($$.num_args > $$.max_args) {
00762 $$.max_args *= 2;
00763 $$.args = GC_REALLOC($$.args, sizeof(p_term *) * $$.max_args);
00764 }
00765 $$.args[($$.num_args)++] = $3;
00766 }
00767 | head_argument_term {
00768 $$.args = GC_MALLOC(sizeof(p_term *) * 4);
00769 $$.args[0] = $1;
00770 $$.num_args = 1;
00771 $$.max_args = 4;
00772 }
00773 ;
00774
00775 head_argument_term
00776 : K_IN argument_term { $$ = unary_term("in", $2); }
00777 | argument_term { $$ = $1; }
00778 ;
00779
00780 bracketed_term
00781 : term { $$ = $1; }
00782 | term K_COLON_DASH term { $$ = binary_term(":-", $1, $3); }
00783 | term K_DARROW term { $$ = binary_term("-->", $1, $3); }
00784 | K_COLON_DASH term { $$ = unary_term(":-", $2); }
00785 | K_QUEST_DASH term { $$ = unary_term("?-", $2); }
00786 ;
00787
00788 term
00789 : term K_EQUIV implies_term { $$ = binary_term("<=>", $1, $3); }
00790 | implies_term { $$ = $1; }
00791 ;
00792
00793 implies_term
00794 : implies_term K_IMPLIES or_term {
00795 $$ = binary_term("=>", $1, $3);
00796 }
00797 | or_term { $$ = $1; }
00798 ;
00799
00800 or_term
00801 : or_term K_OR if_term { $$ = binary_term("||", $1, $3); }
00802 | if_term { $$ = $1; }
00803 ;
00804
00805 if_term
00806 : and_term K_ARROW if_term {
00807 $$ = binary_term("->", finalize_r_list($1), $3);
00808 }
00809 | and_term { $$ = finalize_r_list($1); }
00810 ;
00811
00812 and_term
00813 : and_term K_AND not_term { append_r_list($$, $1, $3, "&&"); }
00814 | and_term ',' not_term { append_r_list($$, $1, $3, ","); }
00815 | not_term { create_r_list($$, $1); }
00816 ;
00817
00818 argument_term
00819 : argument_term K_EQUIV argument_implies_term {
00820 $$ = binary_term("<=>", $1, $3);
00821 }
00822 | argument_implies_term { $$ = $1; }
00823 ;
00824
00825 argument_implies_term
00826 : argument_implies_term K_IMPLIES argument_or_term {
00827 $$ = binary_term("=>", $1, $3);
00828 }
00829 | argument_or_term { $$ = $1; }
00830 ;
00831
00832 argument_or_term
00833 : argument_or_term K_OR argument_and_term {
00834 $$ = binary_term("||", $1, finalize_r_list($3));
00835 }
00836 | argument_and_term { $$ = finalize_r_list($1); }
00837 ;
00838
00839 argument_and_term
00840 : argument_and_term K_AND not_term { append_r_list($$, $1, $3, "&&"); }
00841 | not_term { create_r_list($$, $1); }
00842 ;
00843
00844 not_term
00845 : K_NOT not_term { $$ = unary_term("!", $2); }
00846 | '!' not_term { $$ = unary_term("!", $2); }
00847 | compare_term { $$ = $1; }
00848 ;
00849
00850 compare_term
00851 : additive_term '=' additive_term {
00852 $$ = binary_term("=", $1, $3);
00853 }
00854 | additive_term K_NE additive_term {
00855 $$ = binary_term("!=", $1, $3);
00856 }
00857 | additive_term K_TERM_EQ additive_term {
00858 $$ = binary_term("==", $1, $3);
00859 }
00860 | additive_term K_TERM_NE additive_term {
00861 $$ = binary_term("!==", $1, $3);
00862 }
00863 | additive_term K_TERM_LT additive_term {
00864 $$ = binary_term("@<", $1, $3);
00865 }
00866 | additive_term K_TERM_LE additive_term {
00867 $$ = binary_term("@<=", $1, $3);
00868 }
00869 | additive_term K_TERM_GT additive_term {
00870 $$ = binary_term("@>", $1, $3);
00871 }
00872 | additive_term K_TERM_GE additive_term {
00873 $$ = binary_term("@>=", $1, $3);
00874 }
00875 | additive_term K_UNIV additive_term {
00876 $$ = binary_term("=..", $1, $3);
00877 }
00878 | additive_term K_IS additive_term {
00879 $$ = binary_term("is", $1, $3);
00880 }
00881 | additive_term K_NUM_EQ additive_term {
00882 $$ = binary_term("=:=", $1, $3);
00883 }
00884 | additive_term K_NUM_NE additive_term {
00885 $$ = binary_term("=!=", $1, $3);
00886 }
00887 | additive_term K_NUM_LT additive_term {
00888 $$ = binary_term("<", $1, $3);
00889 }
00890 | additive_term K_NUM_LE additive_term {
00891 $$ = binary_term("<=", $1, $3);
00892 }
00893 | additive_term K_NUM_GT additive_term {
00894 $$ = binary_term(">", $1, $3);
00895 }
00896 | additive_term K_NUM_GE additive_term {
00897 $$ = binary_term(">=", $1, $3);
00898 }
00899 | additive_term K_IN additive_term {
00900 $$ = binary_term("in", $1, $3);
00901 }
00902 | additive_term K_GETS additive_term {
00903 $$ = binary_term(":=", $1, $3);
00904 }
00905 | additive_term K_BT_GETS additive_term {
00906 $$ = binary_term(":==", $1, $3);
00907 }
00908 | additive_term K_NUM_GETS additive_term {
00909 $$ = binary_term("::=", $1, $3);
00910 }
00911 | additive_term K_NUM_BT_GETS additive_term {
00912 $$ = binary_term("::==", $1, $3);
00913 }
00914 | additive_term { $$ = $1; }
00915 ;
00916
00917 additive_term
00918 : additive_term '+' multiplicative_term {
00919 $$ = binary_term("+", $1, $3);
00920 }
00921 | additive_term '-' multiplicative_term {
00922 $$ = binary_term("-", $1, $3);
00923 }
00924 | additive_term K_BITWISE_AND multiplicative_term {
00925 $$ = binary_term("/\\", $1, $3);
00926 }
00927 | additive_term K_BITWISE_OR multiplicative_term {
00928 $$ = binary_term("\\/", $1, $3);
00929 }
00930 | multiplicative_term { $$ = $1; }
00931 ;
00932
00933 multiplicative_term
00934 : multiplicative_term '*' power_term {
00935 $$ = binary_term("*", $1, $3);
00936 }
00937 | multiplicative_term '/' power_term {
00938 $$ = binary_term("/", $1, $3);
00939 }
00940 | multiplicative_term '%' power_term {
00941 $$ = binary_term("%", $1, $3);
00942 }
00943 | multiplicative_term K_MOD power_term {
00944 $$ = binary_term("mod", $1, $3);
00945 }
00946 | multiplicative_term K_REM power_term {
00947 $$ = binary_term("rem", $1, $3);
00948 }
00949 | multiplicative_term K_SHIFT_LEFT power_term {
00950 $$ = binary_term("<<", $1, $3);
00951 }
00952 | multiplicative_term K_SHIFT_RIGHT power_term {
00953 $$ = binary_term(">>", $1, $3);
00954 }
00955 | multiplicative_term K_USHIFT_RIGHT power_term {
00956 $$ = binary_term(">>>", $1, $3);
00957 }
00958 | power_term { $$ = $1; }
00959 ;
00960
00961 power_term
00962 : unary_term K_EXP unary_term {
00963 $$ = binary_term("**", $1, $3);
00964 }
00965 | unary_term '^' power_term {
00966 $$ = binary_term("^", $1, $3);
00967 }
00968 | unary_term { $$ = $1; }
00969 ;
00970
00971 unary_term
00972 : '-' unary_term { $$ = unary_term("-", $2); }
00973 | K_BITWISE_NOT unary_term { $$ = unary_term("~", $2); }
00974 | '~' unary_term { $$ = unary_term("~", $2); }
00975 | primary_term { $$ = $1; }
00976 ;
00977
00978 primary_term
00979 : atom { $$ = $1; }
00980 | K_INTEGER { $$ = $1; }
00981 | K_REAL { $$ = $1; }
00982 | K_STRING { $$ = $1; }
00983 | K_VARIABLE { $$ = $1; }
00984 | '!' {
00985 $$ = p_term_create_atom(context, "!");
00986 }
00987 | atom '(' arguments ')' {
00988 if ($1 == context->dot_atom && $3.num_args == 2) {
00989 $$ = p_term_create_list
00990 (context, $3.args[0], $3.args[1]);
00991 } else {
00992 $$ = p_term_create_functor_with_args
00993 (context, $1, $3.args, (int)($3.num_args));
00994 }
00995 GC_FREE($3.args);
00996 }
00997 | atom '(' ')' { $$ = $1; }
00998 | '[' ']' { $$ = p_term_nil_atom(context); }
00999 | '[' list_members ']' { $$ = finalize_list($2); }
01000 | '[' list_members '|' term ']' { $$ = finalize_list_tail($2, $4); }
01001 | '(' bracketed_term ')' { $$ = $2; }
01002 | member_reference {
01003 $$ = p_term_create_member_variable
01004 (context, $1.object, $1.name, $1.auto_create);
01005 }
01006 | member_reference '(' arguments ')' {
01007
01008 p_term *term = p_term_create_functor
01009 (context, p_term_create_atom(context, "$$"),
01010 (int)($3.num_args + 1));
01011 size_t index;
01012 p_term_bind_functor_arg(term, 0, $1.object);
01013 for (index = 0; index < $3.num_args; ++index) {
01014 p_term_bind_functor_arg
01015 (term, (int)(index + 1), $3.args[index]);
01016 }
01017 GC_FREE($3.args);
01018 $$ = p_term_create_functor
01019 (context, p_term_create_atom
01020 (context, "$$call_member"), 2);
01021 p_term_bind_functor_arg
01022 ($$, 0, p_term_create_member_variable
01023 (context, $1.object, $1.name, $1.auto_create));
01024 p_term_bind_functor_arg($$, 1, term);
01025 }
01026 | member_reference '(' ')' {
01027
01028 p_term *term = p_term_create_functor
01029 (context, p_term_create_atom(context, "$$"), 1);
01030 p_term_bind_functor_arg(term, 0, $1.object);
01031 $$ = p_term_create_functor
01032 (context, p_term_create_atom
01033 (context, "$$call_member"), 2);
01034 p_term_bind_functor_arg
01035 ($$, 0, p_term_create_member_variable
01036 (context, $1.object, $1.name, $1.auto_create));
01037 p_term_bind_functor_arg($$, 1, term);
01038 }
01039 | new_term { $$ = $1; }
01040 ;
01041
01042 list_members
01043 : list_members ',' argument_term { append_list($$, $1, $3); }
01044 | argument_term { create_list($$, $1); }
01045 ;
01046
01047 member_reference
01048 : K_VARIABLE '.' atom {
01049 $$.object = $1;
01050 $$.name = $3;
01051 $$.auto_create = 0;
01052 }
01053 | K_VARIABLE K_DOT_DOT atom {
01054 $$.object = $1;
01055 $$.name = $3;
01056 $$.auto_create = 1;
01057 }
01058 | member_reference '.' atom {
01059 $$.object = p_term_create_member_variable
01060 (context, $1.object, $1.name, $1.auto_create);
01061 $$.name = $3;
01062 $$.auto_create = 0;
01063 }
01064 | member_reference K_DOT_DOT atom {
01065 $$.object = p_term_create_member_variable
01066 (context, $1.object, $1.name, $1.auto_create);
01067 $$.name = $3;
01068 $$.auto_create = 1;
01069 }
01070 ;
01071
01072 new_term
01073 : K_NEW atom '(' arguments ')' {
01074
01075
01076
01077 p_term *obj = $4.args[0];
01078 p_term *call_new = p_term_create_functor
01079 (context, p_term_create_atom(context, "$$new"), 2);
01080 p_term *ctor_name = p_term_create_member_name
01081 (context, $2, p_term_create_atom(context, "new"));
01082 p_term *call_ctor = p_term_create_functor_with_args
01083 (context, ctor_name, $4.args, (int)($4.num_args));
01084 GC_FREE($4.args);
01085 p_term_bind_functor_arg(call_new, 0, $2);
01086 p_term_bind_functor_arg(call_new, 1, obj);
01087 $$ = binary_term(",", call_new, call_ctor);
01088 }
01089 ;
01090
01091 statements
01092 : statements statement {
01093 p_term *stmt = add_debug(@2, $2);
01094 append_r_list($$, $1, stmt, ",");
01095 }
01096 | statement {
01097 p_term *stmt = add_debug(@1, $1);
01098 create_r_list($$, stmt);
01099 }
01100 ;
01101
01102 statement
01103 : argument_term ';' { $$ = $1; }
01104 | if_statement { $$ = $1; }
01105 | compound_statement { $$ = $1; }
01106 | loop_statement { $$ = $1; }
01107 | try_statement { $$ = $1; }
01108 | switch_statement { $$ = $1; }
01109 | ';' {
01110 $$ = add_debug(@1, context->true_atom);
01111 }
01112 ;
01113
01114 if_statement
01115 : K_IF condition statement {
01116
01117 p_term *if_stmt = p_term_create_functor
01118 (context, p_term_create_atom(context, "->"), 2);
01119 p_term_bind_functor_arg(if_stmt, 0, $2);
01120 p_term_bind_functor_arg(if_stmt, 1, $3);
01121 $$ = p_term_create_functor
01122 (context, p_term_create_atom(context, "||"), 2);
01123 p_term_bind_functor_arg($$, 0, if_stmt);
01124 p_term_bind_functor_arg($$, 1, context->true_atom);
01125 }
01126 | K_IF condition statement K_ELSE statement {
01127
01128 p_term *if_stmt = p_term_create_functor
01129 (context, p_term_create_atom(context, "->"), 2);
01130 p_term_bind_functor_arg(if_stmt, 0, $2);
01131 p_term_bind_functor_arg(if_stmt, 1, $3);
01132 $$ = p_term_create_functor
01133 (context, p_term_create_atom(context, "||"), 2);
01134 p_term_bind_functor_arg($$, 0, if_stmt);
01135 p_term_bind_functor_arg($$, 1, $5);
01136 }
01137 ;
01138
01139 condition
01140 : '(' term ')' { $$ = $2; }
01141 | '(' error ')' { $$ = context->fail_atom; }
01142 ;
01143
01144 compound_statement
01145 : '{' statements '}' { $$ = finalize_r_list($2); }
01146 | '{' '}' { $$ = context->true_atom; }
01147 | '{' error '}' { $$ = context->true_atom; }
01148 ;
01149
01150 loop_statement
01151 : K_WHILE unbind_vars condition statement {
01152 if ($2 == p_term_nil_atom(context))
01153 $$ = binary_term("$$while", $3, $4);
01154 else
01155 $$ = ternary_term("$$while", $2, $3, $4);
01156 }
01157 | K_DO unbind_vars compound_statement K_WHILE condition ';' {
01158 if ($2 == p_term_nil_atom(context))
01159 $$ = binary_term("$$do", $3, $5);
01160 else
01161 $$ = ternary_term("$$do", $2, $3, $5);
01162 }
01163 | K_FOR unbind_vars '(' K_VARIABLE {
01164 if (p_term_lex_variable_count(input_stream, $4) > 1) {
01165
01166
01167 yyerror_printf
01168 (&(@4), context, input_stream,
01169 "for loop variable `%s' has been referenced previously",
01170 p_term_name($4));
01171 }
01172 }
01173 K_IN primary_term ')' statement {
01174 $$ = p_term_create_functor
01175 (context, p_term_create_atom(context, "$$for"), 4);
01176 p_term_bind_functor_arg($$, 0, $2);
01177 p_term_bind_functor_arg($$, 1, unary_term("$$loopvar", $4));
01178 p_term_bind_functor_arg($$, 2, $7);
01179 p_term_bind_functor_arg($$, 3, $9);
01180 }
01181 ;
01182
01183 unbind_vars
01184 : '[' unbind_var_list ']' { $$ = finalize_list($2); }
01185 | '[' ']' { $$ = p_term_nil_atom(context); }
01186 | { $$ = p_term_nil_atom(context); }
01187 ;
01188
01189 unbind_var_list
01190 : unbind_var_list ',' K_VARIABLE { append_list($$, $1, $3); }
01191 | K_VARIABLE { create_list($$, $1); }
01192 ;
01193
01194 try_statement
01195 : K_TRY compound_statement catch_clauses {
01196 $$ = binary_term("$$try", $2, finalize_list($3));
01197 }
01198 ;
01199
01200 catch_clauses
01201 : catch_clauses catch_clause { append_list($$, $1, $2); }
01202 | catch_clause { create_list($$, $1); }
01203 ;
01204
01205 catch_clause
01206 : K_CATCH '(' argument_term ')' compound_statement {
01207 $$ = binary_term("$$catch", $3, $5);
01208 }
01209 ;
01210
01211 switch_statement
01212 : K_SWITCH '(' argument_term ')' '{' switch_body '}' {
01213 $$ = ternary_term
01214 ("$$switch", $3, $6.case_list, $6.default_case);
01215 }
01216 ;
01217
01218 switch_body
01219 : switch_cases {
01220 $$.case_list = finalize_list($1);
01221 if ($1.default_case)
01222 $$.default_case = $1.default_case;
01223 else
01224 $$.default_case = context->fail_atom;
01225 }
01226 | {
01227 $$.case_list = p_term_nil_atom(context);
01228 $$.default_case = context->fail_atom;
01229 }
01230 ;
01231
01232 switch_cases
01233 : switch_cases switch_case {
01234 append_lists($$, $1, $2);
01235 if ($1.is_default) {
01236 $$.default_case = $1.default_case;
01237 if ($1.is_default == 2 || $2.is_default == 2) {
01238
01239 $$.is_default = 2;
01240 } else if ($1.is_default && $2.is_default) {
01241 yyerror_printf
01242 (&(@2), context, input_stream,
01243 "multiple `default' cases in `switch'");
01244 $$.is_default = 2;
01245 } else {
01246 $$.is_default = $1.is_default;
01247 }
01248 } else if ($2.is_default) {
01249 $$.default_case = $2.default_case;
01250 $$.is_default = $2.is_default;
01251 } else {
01252 $$.default_case = 0;
01253 $$.is_default = 0;
01254 }
01255 }
01256 | switch_case { $$ = $1; }
01257 ;
01258
01259 switch_case
01260 : case_labels statement {
01261 p_term *case_list = finalize_list($1);
01262 if (case_list != context->nil_atom) {
01263 p_term *term = p_term_create_functor
01264 (context, p_term_create_atom(context, "$$case"), 2);
01265 p_term_bind_functor_arg(term, 0, case_list);
01266 p_term_bind_functor_arg(term, 1, $2);
01267 create_list($$, term);
01268 } else {
01269 create_empty_list($$);
01270 }
01271 if ($1.is_default) {
01272 $$.default_case = $2;
01273 $$.is_default = $1.is_default;
01274 } else {
01275 $$.default_case = 0;
01276 $$.is_default = 0;
01277 }
01278 }
01279 ;
01280
01281 case_labels
01282 : case_labels case_label {
01283 if ($2.is_default) {
01284 append_lists($$, $1, $2);
01285 if ($1.is_default) {
01286 yyerror_printf
01287 (&(@2), context, input_stream,
01288 "multiple `default' cases in `switch'");
01289 $$.is_default = 2;
01290 } else {
01291 $$.is_default = 1;
01292 }
01293 } else {
01294 append_lists($$, $1, $2);
01295 $$.is_default = $1.is_default;
01296 }
01297 }
01298 | case_label { $$ = $1; }
01299 ;
01300
01301 case_label
01302 : K_CASE argument_term ':' {
01303 create_list($$, $2);
01304 $$.is_default = 0;
01305 }
01306 | K_DEFAULT ':' {
01307 create_empty_list($$);
01308 $$.is_default = 1;
01309 }
01310 ;
01311
01312 class_declaration
01313 : K_CLASS atom {
01314 input_stream->class_name = $2;
01315 } opt_parent class_body opt_semi {
01316 p_term *clauses = $5.clauses;
01317 if (!($5.has_constructor)) {
01318
01319 p_term *ctor = create_clause_head
01320 (context, input_stream,
01321 p_term_create_atom(context, "new"), 0, 0, 0);
01322 ctor = binary_term(":-", ctor, context->true_atom);
01323 ctor = ternary_term
01324 ("clause",
01325 p_term_create_atom(context, "new"),
01326 p_term_create_atom(context, "constructor"),
01327 ctor);
01328 ctor = add_debug(@2, ctor);
01329 clauses = p_term_create_list(context, ctor, clauses);
01330 clear_variables();
01331 }
01332 $$ = make_class_declaration
01333 (context, $2, $4, $5.vars, clauses);
01334 input_stream->class_name = 0;
01335 }
01336 ;
01337
01338 opt_parent
01339 : { $$ = p_term_nil_atom(context); }
01340 | ':' '[' ']' { $$ = p_term_nil_atom(context); }
01341 | ':' atom { $$ = $2; }
01342 ;
01343
01344 opt_semi
01345 :
01346 | ';'
01347 ;
01348
01349 class_body
01350 : '{' class_members '}' {
01351 $$.vars = finalize_list($2.vars);
01352 $$.clauses = finalize_list($2.clauses);
01353 $$.has_constructor = $2.has_constructor;
01354 }
01355 | '{' '}' {
01356 $$.vars = p_term_nil_atom(context);
01357 $$.clauses = p_term_nil_atom(context);
01358 $$.has_constructor = 0;
01359 }
01360 | '{' error '}' {
01361 $$.vars = p_term_nil_atom(context);
01362 $$.clauses = p_term_nil_atom(context);
01363 $$.has_constructor = 0;
01364 }
01365 ;
01366
01367 class_members
01368 : class_members class_member {
01369 append_lists($$.vars, $1.vars, $2.vars);
01370 append_lists($$.clauses, $1.clauses, $2.clauses);
01371 $$.has_constructor =
01372 ($1.has_constructor || $2.has_constructor);
01373 }
01374 | class_member { $$ = $1; }
01375 ;
01376
01377 class_member
01378 : K_VAR member_vars opt_semi {
01379 $$.vars.l_head = $2.l_head;
01380 $$.vars.l_tail = $2.l_tail;
01381 create_empty_list($$.clauses);
01382 $$.has_constructor = 0;
01383 }
01384 | member_clause {
01385 p_term *clause = ternary_term
01386 ("clause", $1.name, $1.kind,
01387 binary_term(":-", $1.head, $1.body));
01388 clause = add_debug(@1, clause);
01389 create_empty_list($$.vars);
01390 create_list($$.clauses, clause);
01391 $$.has_constructor = $1.has_constructor;
01392 clear_variables();
01393 }
01394 ;
01395
01396 member_clause
01397 : member_clause_head clause_body {
01398 $$ = $1;
01399 $$.body = $2;
01400 }
01401 | K_ABSTRACT regular_member_clause_head K_DOT_TERMINATOR {
01402
01403
01404 p_term *pred;
01405 p_term *error;
01406 pred = p_term_create_functor
01407 (context, context->slash_atom, 2);
01408 p_term_bind_functor_arg(pred, 0, p_term_functor($2.head));
01409 p_term_bind_functor_arg
01410 (pred, 1, p_term_create_integer
01411 (context, p_term_arg_count($2.head)));
01412 error = binary_term
01413 ("existence_error",
01414 p_term_create_atom(context, "member_predicate"), pred);
01415 error = binary_term("error", error, pred);
01416 $$ = $2;
01417 $$.body = unary_term("throw", error);
01418 }
01419 ;
01420
01421 member_clause_head
01422 : regular_member_clause_head { $$ = $1; }
01423 | K_STATIC member_name {
01424 $$.name = $2;
01425 $$.kind = p_term_create_atom(context, "static");
01426 $$.head = create_clause_head
01427 (context, input_stream, $2, 0, 0, 1);
01428 $$.body = 0;
01429 $$.has_constructor = 0;
01430 }
01431 | K_STATIC member_name '(' ')' {
01432 $$.name = $2;
01433 $$.kind = p_term_create_atom(context, "static");
01434 $$.head = create_clause_head
01435 (context, input_stream, $2, 0, 0, 1);
01436 $$.body = 0;
01437 $$.has_constructor = 0;
01438 }
01439 | K_STATIC member_name '(' arguments ')' {
01440 $$.name = $2;
01441 $$.kind = p_term_create_atom(context, "static");
01442 $$.head = create_clause_head
01443 (context, input_stream, $2, $4.args, $4.num_args, 1);
01444 $$.body = 0;
01445 $$.has_constructor = 0;
01446 }
01447 | K_NEW {
01448 $$.name = p_term_create_atom(context, "new");
01449 $$.kind = p_term_create_atom(context, "constructor");
01450 $$.head = create_clause_head
01451 (context, input_stream,
01452 p_term_create_atom(context, "new"), 0, 0, 0);
01453 $$.body = 0;
01454 $$.has_constructor = 1;
01455 }
01456 | K_NEW '(' ')' {
01457 $$.name = p_term_create_atom(context, "new");
01458 $$.kind = p_term_create_atom(context, "constructor");
01459 $$.head = create_clause_head
01460 (context, input_stream,
01461 p_term_create_atom(context, "new"), 0, 0, 0);
01462 $$.body = 0;
01463 $$.has_constructor = 1;
01464 }
01465 | K_NEW '(' arguments ')' {
01466 $$.name = p_term_create_atom(context, "new");
01467 $$.kind = p_term_create_atom(context, "constructor");
01468 $$.head = create_clause_head
01469 (context, input_stream,
01470 p_term_create_atom(context, "new"),
01471 $3.args, $3.num_args, 0);
01472 $$.body = 0;
01473 $$.has_constructor = 1;
01474 }
01475 ;
01476
01477 regular_member_clause_head
01478 : member_name {
01479 $$.name = $1;
01480 $$.kind = p_term_create_atom(context, "member");
01481 $$.head = create_clause_head
01482 (context, input_stream, $1, 0, 0, 0);
01483 $$.body = 0;
01484 $$.has_constructor = 0;
01485 }
01486 | member_name '(' ')' {
01487 $$.name = $1;
01488 $$.kind = p_term_create_atom(context, "member");
01489 $$.head = create_clause_head
01490 (context, input_stream, $1, 0, 0, 0);
01491 $$.body = 0;
01492 $$.has_constructor = 0;
01493 }
01494 | member_name '(' arguments ')' {
01495 $$.name = $1;
01496 $$.kind = p_term_create_atom(context, "member");
01497 $$.head = create_clause_head
01498 (context, input_stream, $1, $3.args, $3.num_args, 0);
01499 $$.body = 0;
01500 $$.has_constructor = 0;
01501 }
01502 ;
01503
01504 member_vars
01505 : member_vars ',' member_var { append_list($$, $1, $3); }
01506 | member_var { create_list($$, $1); }
01507 ;
01508
01509 member_var
01510 : member_name { $$ = add_debug(@1, $1); }
01511 ;
01512
01513 member_name
01514 : atom {
01515 if ($1 == context->class_name_atom ||
01516 $1 == context->prototype_atom) {
01517 yyerror_printf
01518 (&(@1), context, input_stream,
01519 "`%s' is not allowed as a member name",
01520 p_term_name($1));
01521 }
01522 $$ = $1;
01523 }
01524 ;
01525
01526 dcg_clause
01527 : callable_term K_DARROW dcg_body K_DOT_TERMINATOR {
01528 $$ = p_term_expand_dcg(context, binary_term("-->", $1, $3));
01529 }
01530 | callable_term K_DARROW dcg_body K_SHIFT_LEFT confidence
01531 K_SHIFT_RIGHT K_DOT_TERMINATOR {
01532 p_term *body = unary_term("{}", unary_term("$$fuzzy", $5));
01533 body = binary_term(",", $3, body);
01534 $$ = p_term_expand_dcg
01535 (context, binary_term("-->", $1, body));
01536 }
01537 ;
01538
01539 dcg_body
01540 : dcg_body K_OR dcg_term {
01541 $$ = binary_term("||", $1, finalize_r_list($3));
01542 }
01543 | dcg_term {
01544 $$ = finalize_r_list($1);
01545 }
01546 ;
01547
01548 dcg_term
01549 : dcg_term ',' dcg_unary_term { append_r_list($$, $1, $3, ","); }
01550 | dcg_unary_term { create_r_list($$, $1); }
01551 ;
01552
01553 dcg_unary_term
01554 : '!' dcg_primitive_term { $$ = unary_term("!", $2); }
01555 | dcg_primitive_term { $$ = $1; }
01556 ;
01557
01558 dcg_primitive_term
01559 : callable_term { $$ = $1; }
01560 | compound_statement { $$ = unary_term("{}", $1); }
01561 | '[' ']' { $$ = context->nil_atom; }
01562 | '[' list_members ']' { $$ = finalize_list($2); }
01563 | K_STRING { $$ = $1; }
01564 | '(' dcg_body ')' { $$ = $2; }
01565 | '!' { $$ = context->commit_atom; }
01566 ;