home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / FUZZY.ZIP / PARSER.B < prev    next >
Text File  |  1986-11-30  |  27KB  |  753 lines

  1.  
  2. -------------------------------------------------------------------------------
  3. --                                                                           --
  4. --  Library Unit:  Parser                                                    --
  5. --                                                                           --
  6. --  Author:  Bradley L. Richards                                             --
  7. --                                                                           --
  8. --     Version     Date     Notes . . .                                      --
  9. --    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -    --
  10. --       1.0    22 May 86   Initial Version                                  --
  11. --       1.1    19 Jun 86   Lotsa revisions due to Prover design             --
  12. --       2.0    20 Jun 86   Version number change only (for consistancy)     --
  13. --       2.05   13 Jul 86   Split spec and body into separate files          --
  14. --       2.1    21 Jul 86   Demonstration Version                            --
  15. --       2.2    28 Jul 86   Added parse_read.  Initial operational version   --
  16. --       3.0    10 Oct 86   Final thesis product                             --
  17. --    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -    --
  18. --                                                                           --
  19. --  Library units used:  Data_def, listing, token, unchecked_deallocation    --
  20. --                                                                           --
  21. --  Description:  This package parses an input program, and constructs an    --
  22. --     abstract syntax tree for the program.  Procedures appear in           --
  23. --     alphabetical order.  Start_parser and stop_parser are the             --
  24. --     initialization and clean up routines.  Parse_file, parse_read, and    --
  25. --     parse_request are also externally visible routines.   Release is      --
  26. --     the routine which deallocated ASTs when they are no longer needed.    --
  27. --                                                                           --
  28. -------------------------------------------------------------------------------
  29. --                                                                           --
  30. --                              Package Body                                 --
  31. --                                                                           --
  32. -------------------------------------------------------------------------------
  33. package body parser is
  34.  
  35.  
  36.     --
  37.     --  some forward definitions for our parsing routines
  38.     --
  39.     function parse_element return argument_ptr;
  40.     function parse_expression return AST_ptr;
  41.     function parse_head return AST_ptr;
  42.     function parse_list return p_list_ptr;
  43.     function parse_predicate return AST_ptr;
  44.     function parse_term return AST_ptr;
  45.  
  46.  
  47.     --
  48.     --  Parse_to_bracket -- Parse to the first unbalanced right bracket to
  49.     --     reach the end of the current string expression.  Reaching an
  50.     --     unbalanced right paren or a period also suffices.
  51.     --
  52.     procedure parse_to_bracket is
  53.     bracket_level : natural := 0;
  54.     paren_level : natural := 0;
  55.       begin
  56.     loop
  57.       exit when current_token.is_a = period;
  58.       exit when current_token.is_a = end_of_file;
  59.       exit when paren_level = 0 and current_token.is_a = right_paren;
  60.       exit when bracket_level = 0 and current_token.is_a = right_bracket;
  61.       if current_token.is_a = left_paren then
  62.         paren_level := paren_level + 1;
  63.       elsif current_token.is_a = right_paren then
  64.         paren_level := paren_level - 1;
  65.       elsif current_token.is_a = left_bracket then
  66.         bracket_level := bracket_level + 1;
  67.       elsif current_token.is_a = right_bracket then
  68.         bracket_level := bracket_level - 1;
  69.       end if;
  70.       get_token;
  71.     end loop;
  72.       end parse_to_bracket;
  73.  
  74.     --
  75.     --  Parse_to_paren -- Parse to the first unbalanced right paren, or to
  76.     --     a period.  Skip embedded parentheses pairs.
  77.     --
  78.     procedure parse_to_paren is
  79.     paren_level : natural := 0;
  80.       begin
  81.     loop
  82.       exit when current_token.is_a = period;
  83.       exit when current_token.is_a = end_of_file;
  84.       exit when paren_level = 0 and current_token.is_a = right_paren;
  85.       if current_token.is_a = left_paren then
  86.         paren_level := paren_level + 1;
  87.       elsif current_token.is_a = right_paren then
  88.         paren_level := paren_level - 1;
  89.       end if;
  90.       get_token;
  91.     end loop;
  92.       end parse_to_paren;
  93.  
  94.     procedure parse_to_period is
  95.       begin
  96.     loop
  97.       exit when current_token.is_a = period;
  98.       exit when current_token.is_a = end_of_file;
  99.       get_token;
  100.     end loop;
  101.       end parse_to_period;
  102.  
  103.  
  104. --
  105. --  Release -- Return memory to the system using UNCHECKED_DEALLOCATION.
  106. --             These routines must be filled in for an efficient system
  107. --             since the current Verdix Compiler does not include an
  108. --             automatic garbage collector.  Routines deallocate all
  109. --             items within the passed structure UP TO the "stop" value.
  110. --
  111. procedure release( tree, stop : AST_ptr ) is
  112.  
  113.     ptr : AST_ptr := tree;
  114.  
  115.   begin
  116.  
  117.     if ptr /= stop then
  118.       case ptr.node_type is
  119.     when implication =>
  120.       release(ptr.head, stop);
  121.       release(ptr.tail, stop);
  122.     when binary_operator =>
  123.       release(ptr.left_operand, stop);
  124.       release(ptr.right_operand, stop);
  125.     when unary_operator =>
  126.       release(ptr.operand, stop);
  127.     when resolution_marker =>
  128.       release(ptr.subgoals, stop);
  129.     when others => null;
  130.       end case;
  131.       free_AST(ptr);
  132.     end if;
  133.  
  134.   end release;
  135.  
  136.     procedure start_parser( input_file, output_file : in string ) is
  137.       begin
  138.     start_token(input_file, output_file);
  139.       end start_parser;
  140.  
  141.     procedure stop_parser is
  142.       begin
  143.     stop_token;
  144.       end stop_parser;
  145.  
  146.  
  147. -------------------------------------------------------------------------------
  148. --                                                                           --
  149. --                         Parsing Routines                                  --
  150. --                      (in alphabetical order)                              --
  151. --                                                                           --
  152. -------------------------------------------------------------------------------
  153. --
  154. --     A general convention honored by the parsing routines is that each will
  155. --  leave current_token pointing to the token after whatever the routine just
  156. --  parsed.  In the case of an error where the routine got lost, it calls one
  157. --  of parse_to_bracket, parse_to_paren, or parse_to_period to get the parser
  158. --  back into known territory.  Note that these are hierarchical routines in
  159. --  a sense; parse_to_bracket will also stop when it finds an unbalanced
  160. --  right parenthesis or a period, and parse_to_paren will stop when it sees
  161. --  a period.  The parsing routines are careful, in this case, not to parse
  162. --  past the token that represents the termination condition for one of the
  163. --  routines higher up in the call stack.
  164. --
  165.  
  166. --
  167. --  parse_arguments  --  parses the argument list associated with a
  168. --                       predicate call.
  169. --
  170. function parse_arguments return argument_ptr is
  171.     arg, return_list : argument_ptr;
  172.   begin
  173.     --
  174.     --  on entry we know that the current token is a left parenthesis
  175.     --
  176.     get_token;
  177.     arg := parse_element;
  178.     return_list := arg; -- we'll return a pointer to the front of the list
  179.     loop
  180.     if current_token.is_a = comma then -- another argument coming
  181.         get_token;
  182.       elsif current_token.is_a = right_bracket then
  183.         error(pointer, "unbalanced right bracket");
  184.         get_token;
  185.       elsif current_token.is_a = right_paren then -- end of argument list
  186.         get_token;
  187.         exit;
  188.       elsif current_token.is_a = period then
  189.         error(pointer, "no terminating ')' for argument list");
  190.         exit;
  191.       else -- must be a syntax error
  192.         error(pointer,"missing argument separator; comma inserted");
  193.         get_token;
  194.         exit;
  195.       end if;
  196.     arg.next_arg := parse_element;
  197.     if arg.next_arg /= null then -- parse_element succeeded
  198.       arg := arg.next_arg;
  199.     end if;
  200.       end loop;
  201.     return return_list;
  202.   end parse_arguments;
  203.  
  204.  
  205. function parse_clause return AST_ptr is
  206.     clause : AST_ptr := null;
  207.   begin
  208.     if current_token.is_a /= identifier
  209.       then
  210.     error(pointer,"invalid predicate name; clause ignored");
  211.     parse_to_period;
  212.       else
  213.     clause := new AST(implication);
  214.     clause.head := parse_head;
  215.     if current_token.is_a = period then -- just an assertion
  216.         clause.tail := new AST'(fuzzy_value,1.0);
  217.       elsif current_token.is_a = implication then -- we already knew that
  218.         get_token;                 -- so skip it...
  219.         clause.tail := parse_expression;
  220.       else
  221.         error(pointer,"':-' inserted");
  222.         clause.tail := parse_expression;
  223.       end if;
  224.       end if;
  225.     if current_token.is_a /= period then
  226.     if current_token.is_a = right_paren then
  227.         error(pointer,"unbalanced right parenthesis");
  228.         parse_to_period;
  229.       else
  230.         error(pointer,"unknown parsing error");
  231.       end if;
  232.       end if;
  233.     get_token;
  234.     return clause;
  235.   end parse_clause;
  236.  
  237. function parse_element return argument_ptr is
  238.     arg, old : argument_ptr := null;
  239.     duplicate, error_flg : boolean := false;
  240.   begin
  241.     case current_token.is_a is
  242.         when character_lit     => arg := new argument(character_lit);
  243.                       arg.char := current_token.char;
  244.         when float_num         => arg := new argument(float_num);
  245.                       arg.fp_num := current_token.fp_num;
  246.         when integer_num       => arg := new argument(integer_num);
  247.                       arg.int_num := current_token.int_num;
  248.         when left_bracket      => arg := new argument(prolog_list);
  249.                       arg.list := parse_list;
  250.         when identifier        => arg := new argument(predicate);
  251.                       arg.name := current_token.ident_name;
  252.                   get_token;
  253.                   if current_token.is_a = left_paren then
  254.                     arg.p_arguments := parse_arguments;
  255.                   end if;
  256.         when variable          => arg := new argument(variable);
  257.                       arg.v_name := current_token.var_name;
  258.     when underline         => arg := new argument(variable);
  259.                   arg.v_name := null;          -- it's anonymous
  260.     when others            => error(pointer,"illegal or missing element");
  261.                   --
  262.                   --  if the next token isn't an element
  263.                   --  separator then we are totally lost,
  264.                   --  so give up on this argument list.
  265.                   --
  266.                   if (current_token.is_a /= bar) and
  267.                      (current_token.is_a /= comma) then
  268.                     parse_to_paren;
  269.                   end if;
  270.                   error_flg := true;
  271.       end case;
  272.     if not error_flg then -- we're ok, and arg.is_a has a value
  273.         if (arg.is_a /= prolog_list) and (arg.is_a /= predicate) then
  274.             get_token;
  275.       end if;
  276.       end if;
  277.     return arg;
  278.   end parse_element;
  279.  
  280. function parse_expression return AST_ptr is
  281.     --
  282.     --     The basic parsing routines for expressions (which is to say the
  283.     --  entire right half of a clause) are "parse_expression" and "parse_term."
  284.     --  Basically, the parse grammar looks like this:
  285.     --
  286.     --            E  -->  E binary_op T  |  unary_op T  |  T  |
  287.     --                    E binary_op E  |  unary_op E
  288.     --            T  -->  ( E )  |  predicate_name
  289.     --
  290.     --
  291.     --     Define a couple of characteristics of operators
  292.     --
  293.     type ary_ness is (unary, binary);
  294.     subtype precedence_value is integer range 0..255;
  295.     --
  296.     --     Define the relative precedence of operators.  In keeping with
  297.     --  "Programming in Prolog" by Clocksin and Mellish, lower precedence
  298.     --  operators are executed FIRST.  This is counter-intuitive, but seemed
  299.     --  better than conflicting with the definitions in such a popular book.
  300.     --  The values assigned to operators is the same as given in the book.
  301.     --  In the case of two operators of the same precedence, left-to-right
  302.     --  execution occurs.  The left-side/right-side precedence referred to
  303.     --  in Clocksin & Mellish is NOT implemented.
  304.     --
  305.     precedence : array (operators) of precedence_value :=
  306.     (semicolon => 254,       comma => 253,
  307.      bar => 252,             hat => 251,             rw_spy => 250,
  308.      rw_nospy => 250,        rw_not => 60,           rw_is => 40,
  309.      univ => 40,             equal => 40,            not_equal => 40,
  310.      less_than => 40,        less_or_equal => 40,    greater_or_equal => 40,
  311.      greater_than => 40,     equality => 40,         not_equality => 40,
  312.      minus => 31,            plus => 31,             slash => 21,
  313.      asterisk => 21,         rw_mod => 11);
  314.     --
  315.     --     miscellaneous variables
  316.     --
  317.     left, right : AST_ptr;
  318.     operator : token_type := null_token; -- initialize so we can test it later
  319.     
  320.     --
  321.     --  Ary -- returns unary or binary as the type of an operator
  322.     --
  323.     function ary( operator : operators ) return ary_ness is
  324.       begin
  325.     if operator in binary_operators then return binary;
  326.       elsif operator in unary_operators then return unary;
  327.       else error(pointer,"parser.expression.ary called with invalid operator");
  328.            return binary;  -- have to return something
  329.       end if;
  330.       end ary;
  331.  
  332.     --
  333.     --  Get_operator -- Since some operators are reserved words, where the
  334.     --                  specific word is buried as "current_token.word" this
  335.     --                  routine digs it out if necessary and returns a
  336.     --                  consistant item of subtype operators.
  337.     --
  338.     function get_operator( thing : token_ptr ) return operators is
  339.       begin
  340.     if thing.is_a in operators then return thing.is_a;
  341.       elsif thing.is_a = reserved_word then
  342.         if (thing.word = rw_is) or else (thing.word = rw_mod) or else
  343.            (thing.word = rw_nospy) or else (thing.word = rw_not) or else
  344.            (thing.word = rw_spy) then return thing.word;
  345.           end if;
  346.       else
  347.        error(pointer,"parser.expression.get_operator called with invalid operator");
  348.        return comma;  -- have to return something
  349.       end if;
  350.       end get_operator;
  351.  
  352.     --
  353.     --  Not_operator -- We need to be able to tell if the current token is or
  354.     --                  is not an operator.  It happens that "not_operator" is
  355.     --                  the version we need.
  356.     --
  357.     function not_operator( thing : token_ptr ) return boolean is
  358.       begin
  359.     if thing.is_a in operators then return false;
  360.       elsif thing.is_a = reserved_word then
  361.         if (thing.word = rw_is) or else (thing.word = rw_mod) or else
  362.            (thing.word = rw_nospy) or else (thing.word = rw_not) or else
  363.            (thing.word = rw_spy) then return false;
  364.           else return true;
  365.           end if;
  366.       else return true;
  367.       end if;
  368.       end not_operator;
  369.  
  370.     --
  371.     --  Build_expr -- This is the recursive routine which actually does most of
  372.     --                the work.  A single pass of this routine takes the
  373.     --                input operator and its operands and builds an AST node
  374.     --                which is returned as the new left operand.
  375.     --
  376.     procedure build_expr( pending : precedence_value; left : in out AST_ptr;
  377.               in_operator : operators; in_right : AST_ptr ) is
  378.     
  379.     operator : operators := in_operator;
  380.     right : AST_ptr := in_right;
  381.     op2, next_op : operators;
  382.     right2 : AST_ptr;
  383.       begin
  384.     loop
  385.         if not_operator(current_token) then
  386.         --
  387.         --  At the end of this expression or subexpression?
  388.         --
  389.         if current_token.is_a = period or
  390.                        current_token.is_a = right_paren then
  391.             if ary(operator) = unary then
  392.             left := new AST'(unary_operator, operator, right);
  393.               else
  394.             left := new AST'(binary_operator, operator, left,right);
  395.               end if;
  396.           else
  397.             --
  398.             --  Hmmm...at this point the current token should be an
  399.             --  operator of some sort.  Since it isn't, give up.
  400.             --
  401.             error(pointer,"invalid operator");
  402.             parse_to_paren;
  403.           end if;
  404.         exit;  -- one way or another, we're done.
  405.           else
  406.         next_op := get_operator(current_token);
  407.         --
  408.         --  If the next operator has a higher precedence, then execute
  409.         --  it LATER.  This means that we go ahead and compress the
  410.         --  current operator and its operands into an AST node.  But,
  411.         --  if the right-hand side is null, it is a unary operator
  412.         --  which must be evaluated before we'll even have an operand.
  413.         --
  414.         if (precedence(next_op) >= precedence(operator)) and
  415.            (right /= null) then
  416.             if ary(operator) = unary then
  417.             left := new AST'(unary_operator, operator, right);
  418.               else
  419.             left := new AST'(binary_operator, operator, left,right);
  420.               end if;
  421.             --
  422.             --  If the pending operator has a LOWER precedence then
  423.             --  it needs executed before the next operator.  Hence we
  424.             --  exit to allow it to execute.
  425.             --
  426.             exit when precedence(next_op) >= pending;
  427.             --
  428.             --  still here, so shift in the next operator and operand
  429.             --
  430.             operator := next_op;
  431.             get_token;
  432.             if not_operator(current_token) then
  433.               right := parse_term;
  434.             elsif ary(get_operator(current_token)) = unary then
  435.               right := null; -- unary operator is legitimate operand
  436.             else
  437.               error(pointer,"illegal use of operator");
  438.             end if;
  439.           else
  440.             --
  441.             --  The next operator has to be executed before the current
  442.             --  one.  Make a recursive call to take care of it.
  443.             --
  444.             op2 := next_op;
  445.             get_token;
  446.             if not_operator(current_token) then
  447.               right2 := parse_term;
  448.             elsif ary(get_operator(current_token)) = unary then
  449.               right2 := null; -- unary operator is legitimate operand
  450.             else
  451.               error(pointer,"illegal use of operator");
  452.             end if;
  453.             build_expr(precedence(operator), right, op2, right2);
  454.           end if;
  455.           end if;
  456.       end loop;
  457.       end build_expr;
  458.  
  459.   begin -- parse_expression
  460.     if not_operator(current_token) then -- it must be the left-hand operand of
  461.                     -- a binary operator
  462.     left := parse_term;
  463.       else
  464.     operator := get_operator(current_token);
  465.     if ary(operator) /= unary then
  466.         error(pointer,"missing left-hand operand for binary operator");
  467.         parse_to_paren;
  468.       end if;
  469.       end if;
  470.     if not_operator(current_token) then
  471.     --
  472.     --  A predicate name by itself is ok, so if the current token is a
  473.     --  period things are fine.  If it's anything else (we already know
  474.     --  it's not a legal operator) we're lost.
  475.     --
  476.     if current_token.is_a /= period then
  477.         if operator = null_token then
  478.         error(pointer,"missing operator");
  479.           else
  480.             error(pointer,"missing operand");
  481.           end if;
  482.         parse_to_paren;
  483.       end if;
  484.       else
  485.     operator := get_operator(current_token);
  486.     get_token;
  487.     if not_operator(current_token) then
  488.       right := parse_term;
  489.     elsif ary(get_operator(current_token)) = unary then
  490.       right := null; -- unary operator is legitimate operand
  491.     else
  492.       error(pointer,"illegal use of operator");
  493.     end if;
  494.     build_expr(255, left, operator, right);
  495.       end if;
  496.     return left;
  497.   end parse_expression;
  498.  
  499.  
  500. procedure parse_file( abstract_syntax_tree : out AST_ptr ) is
  501.  
  502.     clause, FP_program : AST_ptr := null;
  503.  
  504.     function first_node(node : AST_ptr) return AST_ptr is
  505.     temp_node : AST_ptr := node;
  506.       begin
  507.     if temp_node /= null
  508.       then
  509.         while temp_node.prev /= null loop
  510.         temp_node := temp_node.prev;
  511.           end loop;
  512.       end if;
  513.     return temp_node;
  514.       end first_node;
  515.  
  516.   begin
  517.     get_token;
  518.     while current_token.is_a /= end_of_file loop
  519.     clause := parse_clause;
  520.     if clause /= null then
  521.         --
  522.         -- append new node to the last node in FP_program.  Note that
  523.         -- FP_program points to the last clause parsed.  After appending
  524.         -- the new node, then set the "next" pointer in the previous node.
  525.         --
  526.         if FP_program /= null then -- this is not the first node
  527.           FP_program.next := clause;
  528.           clause.prev := FP_program;
  529.         end if;
  530.         FP_program := clause;
  531.       end if;
  532.       end loop;
  533.     --
  534.     -- Point abstract_syntax_tree to the very first node in FP_program
  535.     --
  536.     abstract_syntax_tree := first_node(FP_program);
  537.   exception
  538.     when unexpected_end_of_file  =>
  539.       error(pointer,"unexpected end of file");
  540.       abstract_syntax_tree := first_node(FP_program);
  541.   end parse_file;
  542.  
  543. --
  544. --  Parse_head -- Parse the head of a clause.  This is currently limited to
  545. --                parsing a single predicate.
  546. --
  547. function parse_head return AST_ptr is
  548.     node : AST_ptr;
  549.   begin
  550.     node := parse_predicate;
  551.     return node;
  552.   end parse_head;
  553.  
  554. --
  555. --  Parse_list -- Parse a Prolog list structure.  Note that lists appear
  556. --     only in argument lists.  they can contain any of the elements which
  557. --     can occur elsewhere in an argument list.  The structure of a list is
  558. --     similar to a LISP "cons" cell.
  559. --
  560. function parse_list return p_list_ptr is
  561.     has_tail, need_elt : boolean;
  562.     temp_elt : argument_ptr;
  563.     root, ptr, ptr2 : p_list_ptr;
  564.   begin
  565.     --
  566.     -- we know the current token is a left bracket
  567.     --
  568.     get_token;
  569.     need_elt := false;
  570.     while current_token.is_a /= right_bracket loop
  571.     temp_elt := parse_element;
  572.     need_elt := false;
  573.     if current_token.is_a = comma then
  574.       has_tail := false;
  575.       need_elt := true;
  576.       get_token;
  577.     elsif current_token.is_a = bar then
  578.       has_tail := true;
  579.       need_elt := true;
  580.       get_token;
  581.     elsif current_token.is_a = right_bracket then
  582.       has_tail := false;
  583.     elsif (current_token.is_a = period) or
  584.           (current_token.is_a = right_paren) then
  585.       error(pointer,"no terminating ']' for list");
  586.       exit;
  587.     else -- we don't have what we expected
  588.       error(pointer,"missing separator; comma inserted");
  589.       has_tail := false;
  590.       need_elt := true;
  591.     end if;
  592.     if root = null then -- first element
  593.       root := new p_list(has_tail);
  594.       root.elt := temp_elt;
  595.       ptr := root;
  596.     else
  597.       if ptr.has_tail then -- this element is the tail
  598.         ptr.tail := temp_elt;
  599.         if need_elt then
  600.           error(pointer,"only a single element allowed in a tail");
  601.           parse_to_bracket;
  602.           need_elt := false;
  603.         end if;
  604.       else -- a normal continuation of the list
  605.         ptr2 := new p_list(has_tail);
  606.         ptr2.elt := temp_elt;
  607.         ptr.next_elt := ptr2;
  608.         ptr := ptr2;
  609.       end if;
  610.     end if;
  611.       end loop;
  612.     if need_elt then
  613.       error(pointer,"missing element in list");
  614.     end if;
  615.     if current_token.is_a = right_bracket then -- finish off list
  616.     get_token;
  617.       end if;
  618.     return root;
  619.   end parse_list;
  620.  
  621.  
  622. --
  623. --  Parse_predicate -- Parse a single predicate call
  624. --
  625. function parse_predicate return AST_ptr is
  626.     node, temp_node : AST_ptr := null;
  627.   begin
  628.     if current_token.is_a = reserved_word then
  629.     if current_token.word in reserved_predicates then
  630.             node := new AST(reserved_predicate);
  631.             node.predicate := current_token.word;
  632.             get_token;
  633.             if current_token.is_a = left_paren then
  634.           node.r_arguments := parse_arguments;
  635.             end if;
  636.         --
  637.         --  This section of code implements special handling for certain
  638.         --  Fuzzy Prolog reserved predicates.  For example, when the
  639.         --  "fuzzy" predicate has an explicit floating point number as
  640.         --  its argument, we go ahead and establish a fuzzy_value node.
  641.         --
  642.         case node.predicate is
  643.           when rw_fuzzy =>
  644.         if node.r_arguments.is_a = float_num then
  645.           temp_node := new AST'(fuzzy_value, node.r_arguments.fp_num);
  646.           release(node, null);
  647.           node := temp_node;
  648.         end if;
  649.           when others  =>  -- no special handling (or not implemented)
  650.         null;
  651.         end case;
  652.       else
  653.         error(pointer,"illegal use of operator");
  654.       end if;
  655.       elsif current_token.is_a = identifier then
  656.         node := new AST(predicate);
  657.         node.name := current_token.ident_name;
  658.         get_token;
  659.         if current_token.is_a = left_paren then
  660.         node.p_arguments := parse_arguments;
  661.           end if;
  662.       elsif current_token.is_a = cut then
  663.         node := new AST'(reserved_predicate,cut,null);
  664.         get_token;
  665.       else
  666.     error(pointer,"illegal use of operator");
  667.       end if;
  668.     return node;
  669.   end parse_predicate;
  670.  
  671.  
  672. --
  673. --  Parse_read -- Return a single element for a READ predicate.  Disallow
  674. --                variables as they make no sense in this context.
  675. --
  676. procedure parse_read( elt : out argument_ptr; eof : out boolean ) is
  677.     temp_elt : argument_ptr;
  678.   begin
  679.     get_token;
  680.     temp_elt := parse_element;
  681.     if current_token.is_a = end_of_file then
  682.       eof := true;
  683.     else
  684.       if temp_elt.is_a = variable then
  685.         error(pointer, "Variable not allowed on READ");
  686.         elt := null;
  687.       else
  688.         elt := temp_elt;
  689.       end if;
  690.       eof := false;
  691.     end if;
  692.   end parse_read;
  693.  
  694.  
  695. --
  696. --  Parse_request -- Parse an interactive user request.  This is assumed to be
  697. --                   some expression (just like the tail of a clause).  The
  698. --                   short-hand list notation for file consultations is not
  699. --                   currently supported.
  700. --
  701. procedure parse_request( abstract_syntax_tree : out AST_ptr;
  702.              eof : out boolean ) is
  703.   begin
  704.     get_token;
  705.     abstract_syntax_tree := parse_expression;
  706.     eof := (current_token.is_a = end_of_file);
  707.   end parse_request;
  708.  
  709.  
  710. --
  711. --  Parse_term -- Parse a term within an expression.  Terms will either be
  712. --                predicate calls or subexpressions enclosed within
  713. --                parentheses.
  714. --
  715. function parse_term return AST_ptr is
  716.     node : AST_ptr;
  717.   begin
  718.     if current_token.is_a = left_paren then -- parse a subexpression
  719.     get_token; -- consume the left parenthesis
  720.     node := parse_expression;
  721.     if current_token.is_a = right_paren then -- normal condition
  722.         get_token; -- consume the right parenthesis
  723.       elsif current_token.is_a = period then -- missing right parenthesis
  724.         error(pointer,"right parenthesis inserted");
  725.       else
  726.         error(pointer,"unknown parsing error in parse_term");
  727.       end if;
  728.       elsif current_token.is_a = identifier then -- a predicate
  729.     node := parse_predicate;
  730.       elsif current_token.is_a = reserved_word then -- still a predicate
  731.     node := parse_predicate;
  732.       elsif current_token.is_a = cut then -- the "cut" predicate
  733.     node := parse_predicate;
  734.       elsif current_token.is_a = integer_num then
  735.     node := new AST'(integer_num, current_token.int_num);
  736.     get_token;
  737.       elsif current_token.is_a = float_num then
  738.     node := new AST'(float_num, current_token.fp_num);
  739.     get_token;
  740.       elsif current_token.is_a = character_lit then
  741.     node := new AST'(character_lit, current_token.char);
  742.     get_token;
  743.       elsif current_token.is_a = variable then
  744.     node := new AST'(variable, current_token.var_name);
  745.     get_token;
  746.       else
  747.     error(pointer,"illegal or missing term");
  748.       end if;
  749.     return node;
  750.   end parse_term;
  751.  
  752. end parser;
  753.