PreviousUp

15.5.2  src/lib/compiler/front/parser/yacc/mythryl.grammar

##  mythryl.grammar
#
# This is the Mythryl syntax grammar file.
#
# Mythryl-Yacc consumes this and spits out an LALR (1)
# parser which accepts tokens produced by the lexer from
#
#    src/lib/compiler/front/parser/lex/mythryl.lex
#
# and produces raw syntax trees.
#
# Mythryl-Yacc puts the generated code for the parser in the files
#
#     mythryl.grammar.api
#     mythryl.grammar.pkg
#
# with the former containing
#
#       api Mythryl_Tokens {
#           Token (X,Y);
#           Semantic_Value;
#           colon: (X, X) -> Token (Semantic_Value,X);
#           ...
#       };
#       api Mythryl_Lrvals{
#           package tokens:  Mythryl_Tokens;
#           package parser_data: Parser_Data;
#           sharing parser_data::token::Token == tokens::Token;
#           sharing parser_data::Semantic_Value == tokens::Semantic_Value;
#       };
#
# and the latter containing
#
#       generic package mythryl_lr_vals_fun (package token:  Token;)
#       : (weak) api {  package parser_data : Parser_Data;
#                       package tokens : Mythryl_Tokens;
#                   }
#       { 
#           package parser_data {
#               package header { 
#                   <header code from mythryl.grammar>
#               };
#               package lr_table = token::lr_table;
#               package token = token;
#               ...
#           };
#           package tokens : (weak) Mythryl_Tokens {
#               Semantic_Value = parser_data::Semantic_Value;
#               Token (X,Y) = token::Token(X,Y);
#               ...
#           };
#       };
#
# The above generic gets invoked in
#
#     src/lib/compiler/front/parser/main/mythryl-parser-guts.pkg
#
# which assembles a complete parser from the lexer, the Mythryl-Yacc output, and
#
#     src/app/yacc/lib/make-complete-yacc-parser-with-custom-argument-g.pkg

# The Mythryl parser gets invoked by
#     prompt_read_parse_and_return_one_toplevel_mythryl_expression
#     parse_complete_mythryl_file
# in  src/lib/compiler/front/parser/main/parse-mythryl.pkg
#
# For further higher-level context see:
#
#     src/A.COMPILER-PASSES.OVERVIEW

# Mythryl-Yacc also produces a file
#
#     mythryl.grammar.desc
#
# as human-readable documentation of the parser.
#
# The invocation of Mythryl-Yacc and compilation of
# the resulting code is driven by
#
#     src/lib/compiler/front/parser/parser.sublib
#
# The raw-syntax trees we produce at runtime are defined in:
#
#     compiler/parse/raw-syntax/raw-syntax.api
#     compiler/parse/raw-syntax/raw-syntax.pkg
#
# The file syntax here is very close to classic
# YACC input syntax, with Mythryl substituted
# for C in the actions.  The biggest difference
# is that when we declare nonterminal symbols via
# '%nonterm', we also declare types for them.
#
# The top section (to the first double-percent-sign
# separator) contains arbitrary Mythryl code -- support
# for rule actions.


#     Appel's 1992 Critique http://www.cs.princetone.edu/research/techforms/TR-364-92
#     points out a case in which SML implementations (of the time at least)
#     would in fact "go wrong":  If we're to use Mythryl as a trusted environment
#     in which to run untrusted code from the internet, this will need to be
#     reviewed and if necessary repaired in some fashion.               XXX BUGGO FIXME




###             "Bilbo had a shirt of mithril rings that Thorin gave him.
###              I never told him, but its worth was greater than the
###              value of the Shire."
### 
###                                           -- Gandalf



###             "I think it is extraordinarily important that
###              we in computer science keep fun in computing.
###
###              When it started out, it was an awful lot of fun.
###
###              Of course, the paying customers got shafted every
###              now and then, and after awhile we began to take
###              their complaints seriously.  We began to feel as
###              if we really were responsible for the successful,
###              error-free perfect use of these machines.
###
###              I don't think we are.
###
###              I think we're responsible for stretching them,
###              setting them off in new directions, and keeping
###              fun in the house.  I hope the field of computer
###              science never loses its sense of fun.
###
###              Above all, I hope we don't become missionaries.
###              Don't feel as if you're Bible salesmen.  The
###              world has too many of those already.  What you
###              know about computing other people will learn.
###              Don't feel as if the key to successful computing
###              is only in your hands.
###
###              What's in your hands, I think and hope, is
###              intelligence:  The ability to see the machine
###              as more than when you were first led up to it,
###              that you can make it more."   
###
###                 -- Alan J Perlis
###
###                     (Quoted in the excellent MIT
###                      introductory programming text
###                       "Structure and Interpretation
###                        of Computer Programs".)



###             "I have heard from many different people that they
###              find the ML syntax confusing, ugly, and difficult
###              to learn.  As a long-time ML programmer, I am quite
###              comfortable with ML syntax; but perhaps the frequency
###              of these comments might serve as a hint that there is
###              an opportunity for a syntax designer of rare taste and
###              genius."
###
###                                         -- Andrew W Appel  1992


package raw =  raw_syntax;                      # raw_syntax                            is from   src/lib/compiler/front/parser/raw-syntax/raw-syntax.pkg

                                                # hash_string                           is from   src/lib/src/hash-string.pkg
include package   raw_syntax;                   # raw_syntax                            is from   src/lib/compiler/front/parser/raw-syntax/raw-syntax.pkg
include package   make_raw_syntax;              # make_raw_syntax                       is from   src/lib/compiler/front/parser/raw-syntax/make-raw-syntax.pkg
include package   error_message;                # error_message                         is from   src/lib/compiler/front/basics/errormsg/error-message.pkg
include package   symbol;                       # symbol                                is from   src/lib/compiler/front/basics/map/symbol.pkg
include package   fast_symbol;                  # fast_symbol                           is from   src/lib/compiler/front/basics/map/fast-symbol.pkg
include package   raw_syntax_junk;              # raw_syntax_junk                       is from   src/lib/compiler/front/parser/raw-syntax/raw-syntax-junk.pkg
include package   regex_to_raw_syntax;          # regex_to_raw_syntax                   is from   src/lib/compiler/front/parser/raw-syntax/regex-to-raw-syntax.pkg
include package   fixity;                       # fixity                                is from   src/lib/compiler/front/basics/map/fixity.pkg

package elc = expand_list_comprehension_syntax; # expand_list_comprehension_syntax      is from   src/lib/compiler/front/parser/raw-syntax/expand-list-comprehension-syntax.pkg
package hs  = hash_string;                      # hash_string                           is from   src/lib/src/hash-string.pkg

include package   printf_format_string_to_raw_syntax;   # printf_format_string_to_raw_syntax    is from   src/lib/compiler/front/parser/raw-syntax/printf-format-string-to-raw-syntax.pkg


Raw_Symbol
    =
    fast_symbol::Raw_Symbol;



# fun mark_expression (e as SOURCE_CODE_REGION_FOR_EXPRESSION    _, _, _) =>  e;
#     mark_expression (e,                                           a, b) =>  SOURCE_CODE_REGION_FOR_EXPRESSION (e, (a, b));
# end;

# fun mark_declaration (d as SOURCE_CODE_REGION_FOR_DECLARATION _, _, _) =>  d;
#     mark_declaration (d,                                          a, b) =>  SOURCE_CODE_REGION_FOR_DECLARATION (d, (a, b));
# end;


# fun dropit (id, idleft, idright)
#     =
#     {   my RAWSYM( word, string )
#            =
#            id;

#         fun log_change new_string
#             =
#           case  *mythryl_parser::edit_request_stream 

#                THE stream
#                     =>
#                     {   file::write (
#                             stream,
#                             (   (int::to_string (idleft - 2))
#                             +   ": `" + string + "` -> `" + new_string + "`\n"
#                             )
#                         );
#                         id;
#                     };

#                NULL => id;

#           esac;



#       fun munge ([], _, done)
#                 =>
#                 log_change (implode (reverse done));

#           munge (c ! to_do, last, done)
#               =>
#               {   if  (char::is_lower last
#                     and  char::is_upper c
#                         ) 
#                       munge( to_do, c, (char::to_lower c) ! '_' ! done );
#                   else
#                   if (char::is_upper c )
#                       munge( to_do, c, (char::to_lower c) ! done );
#                   else
#                       munge( to_do, c, c ! done );
#                   fi; fi;
#               };
#       end;

#         fun its_big_enough char_list
#             =
#             length( char_list ) > 1;

# #            case char_list
# #              'a' ! _ => length( char_list ) > 7;
# #              'b' ! _ => length( char_list ) > 7;
# #              'c' ! _ => length( char_list ) > 7;
# #              'd' ! _ => length( char_list ) > 7;
# #              'e' ! _ => length( char_list ) > 7;
# #              'f' ! _ => length( char_list ) > 7;
# #              'g' ! _ => length( char_list ) > 7;
# #              'h' ! _ => length( char_list ) > 7;
# #              'i' ! _ => length( char_list ) > 7;
# #              'j' ! _ => length( char_list ) > 7;
# #              'k' ! _ => length( char_list ) > 7;
# #              'l' ! _ => length( char_list ) > 7;
# #              'm' ! _ => length( char_list ) > 7;
# #              'n' ! _ => length( char_list ) > 7;
# #              'o' ! _ => length( char_list ) > 7;
# #              'p' ! _ => length( char_list ) > 7;
# #              'q' ! _ => length( char_list ) > 7;
# #              'r' ! _ => length( char_list ) > 7;
# #              's' ! _ => length( char_list ) > 7;
# #              't' ! _ => length( char_list ) > 7;
# #              'u' ! _ => length( char_list ) > 7;
# #              'v' ! _ => length( char_list ) > 7;
# #              'w' ! _ => length( char_list ) > 7;
# #              'x' ! _ => length( char_list ) > 7;
# #              'y' ! _ => length( char_list ) > 7;
# #              'z' ! _ => length( char_list ) > 7;
# #              _ => FALSE;
# #            esac;

#         char_list = explode string;

#       has_lower = list::exists char::is_lower char_list;
#       has_upper = list::exists char::is_upper char_list;

#       case (has_lower, has_upper)

#            (TRUE,  TRUE )
#                =>
#                if   (its_big_enough char_list)
#                    
#                     munge (char_list, '_', [] );
#                else
#                     id;
#                fi;
#            _              =>   id;

#       esac;

#     };

# Given "a::b::c", return ["a", "b", "c"]:
#
fun explode_path string
    =
    loop (char_list, [], [])
    where
         char_list = explode string;

         fun loop (chars_left, chars_done, result_strings)
             =
             case  chars_left

                  []  =>
                      reverse ((implode (reverse chars_done)) ! result_strings);

                  (':' ! ':' ! rest)    # Found a path divider.
                      =>
                      loop( rest, [], (implode (reverse chars_done)) ! result_strings );

                  ('`' ! rest)          # chars_left == `++` or such -- must be last string in path.
                      =>
                      reverse ((implode chars_left) ! result_strings);

                  (c ! rest)
                      =>
                      loop( rest, c ! chars_done, result_strings );

             esac;  
    end;



# The grammar token declaration section starts after this marker:


%%


# First we declare the terminal symbols returned by
# the lexer -- the various constant types, the keywords,
# and the identifier classes (ID, ANTIQUOTE_ID, TYVAR) that do
# most of the real work:

%term
      EOF
    | SEMI
#    | ID of fast_symbol::Raw_Symbol
    | IMPLICIT_THUNK_PARAMETER of fast_symbol::Raw_Symbol
    | LOWERCASE_ID of fast_symbol::Raw_Symbol    | LOWERCASE_PATH of fast_symbol::Raw_Symbol
    | MIXEDCASE_ID of fast_symbol::Raw_Symbol    | MIXEDCASE_PATH of fast_symbol::Raw_Symbol
    | UPPERCASE_ID of fast_symbol::Raw_Symbol    | UPPERCASE_PATH of fast_symbol::Raw_Symbol
    | OPERATORS_ID of fast_symbol::Raw_Symbol    | OPERATORS_PATH of fast_symbol::Raw_Symbol
    | PASSIVEOP_ID of fast_symbol::Raw_Symbol
    | PREFIX_OP_ID of fast_symbol::Raw_Symbol
    | POSTFIX_OP_ID of fast_symbol::Raw_Symbol
    | BOGUSCASE_ID of fast_symbol::Raw_Symbol
    | TYVAR of fast_symbol::Raw_Symbol                  # Vanilla  typevars:  A  B  C ...  X  Y  Z
                                                        # Equality typevars: _A _B _C ... _X _Y _Z
                                                        # Long vanillas:      A_foo  Z_bar ...
                                                        # Long equalities:   _A_foo _Z_bar ...
                                                        # The leading '_' marking equality variables gets interpreted in   extract_variable_name_information  from  src/lib/compiler/front/typer-stuff/types/type-junk.pkg

    | INT of  multiword_int::Int
    | INT0 of multiword_int::Int
    | UNT of  multiword_int::Int
    | FLOAT of String
    # NB: We should treat int and float literals as redefinable quotation forms
    #     just like BACKTICKS and DOT_BACKTICKS and such.  Since the existing
    #     "definitions"  of these forms are interpreted at compiletime, this means
    #     formalizing a mechanism for user-defined functions to take effect at
    #     compiletime.  XXX SUCKO FIXME.
    | BACKTICKS         of String 
    | DOT_BACKTICKS     of String 
    | DOT_QQUOTES       of String 
    | DOT_QUOTES        of String 
    | DOT_BROKETS       of String 
    | DOT_BARETS        of String 
    | DOT_SLASHETS      of String 
    | DOT_HASHETS       of String 
    | PRE_COMPILE_CODE  of String
    | STRING of String 
    | CHAR of String
    | ALSO_T
    | API_T
    | ARROW
    | AS_T | CASE_T | CLASS_T | CLASS2_T | DOTDOTDOT | ELSE_T | ELIF_T | END_T | EQUAL_OP | EQEQ_OP
    | EQTYPE_T | ESAC_T | EXCEPTION_T | DARROW
#    | EQ_TILDA

    | PRE_PLUSPLUS | PLUS_PLUS | PLUSPLUS_EQ | POST_PLUSPLUS
    | PRE_DASHDASH | DASH_DASH | DASHDASH_EQ | POST_DASHDASH

    | PRE_BAR    | BAR    |    BAR_EQ | POST_BAR
    | PRE_LANGLE | LANGLE                               # "langle" == "left  angle bracket"
                 | RANGLE             | POST_RANGLE     # "rangle" == "right angle bracket"
    | PRE_LBRACE | LBRACE                               # "lbrace" == "left  brace"
                 | RBRACE             | POST_RBRACE     # "rbrace" == "right brace"

    | LBRACKET                        | POST_LBRACKET

    | PRE_AMPER  | AMPER  |  AMPER_EQ | POST_AMPER
    | PRE_ATSIGN | ATSIGN | ATSIGN_EQ | POST_ATSIGN
    | PRE_BACK   | BACK   |   BACK_EQ | POST_BACK       # backslash
    | PRE_BANG   | BANG   |   BANG_EQ | POST_BANG
    | PRE_BUCK   | BUCK   |   BUCK_EQ | POST_BUCK
    | PRE_CARET  | CARET  |  CARET_EQ | POST_CARET
    | PRE_DASH   | DASH   |   DASH_EQ | POST_DASH
    | PRE_DOT    | DOT    |    DOT_EQ
    | PRE_DOTDOT | DOTDOT | DOTDOT_EQ | POST_DOTDOT
    | PRE_PERCNT | PERCNT | PERCNT_EQ | POST_PERCNT
    | PRE_PLUS   | PLUS   |   PLUS_EQ | POST_PLUS
    | PRE_QMARK  | QMARK  |  QMARK_EQ | POST_QMARK
    | PRE_SLASH  | SLASH  |  SLASH_EQ | POST_SLASH
    | PRE_STAR   | STAR   |   STAR_EQ | POST_STAR
    | PRE_TILDA  | TILDA  |  TILDA_EQ | POST_TILDA
    | EXCEPT_T  | FI_T  | FIELD_T  | FN_T  | FOR_T     | FUN_T   | FPRINTF_T | POSTFIX_ARROW
    | GENERIC_T | HASH  | HEREIN_T | IF_T  | IN_T      | INCLUDE_T | INFIX_T | INFIXR_T | LAZY_T | MESSAGE_T | METHOD_T | MY_T | NONFIX_T
    | OVERLOADED_T      | RAISE_T  | RECURSIVE_T | SHARING_T | SPRINTF_T
    | PACKAGE_T | PRINTF_T | STIPULATE_T   | TILDA_TILDA 
    | WHAT_WHAT | WHERE_T | WILD | WITHTYPE_T                                                                                           # 2014-11-22: Experimentally, replacing WITHTYPE_T with ALSO_T does not work. (Parse errors while recompiling the system.) Ah well.
    | COLON | WEAK_PACKAGE_CAST | PARTIAL_PACKAGE_CAST | COLON_COLON | COLON_WHAT  | WHAT_COLON | COMMA | LBRACE_DOT | LPAREN
    | RBRACKET | RPAREN | OR_T | AND_T | VECTORSTART | BEGINQ 
    | ENDQ of String
    | CHUNKL of String
    | ANTIQUOTE_ID of fast_symbol::Raw_Symbol



# Next we declare the grammar's
# nonterminal symbols, which is
# to say, the rule names:

%nonterm value_id         of fast_symbol::Raw_Symbol
       | value_or_bar     of fast_symbol::Raw_Symbol
       | nonprefix_value_or_bar    of fast_symbol::Raw_Symbol
       | prefix_op        of fast_symbol::Raw_Symbol
       | postfix_op       of fast_symbol::Raw_Symbol
       | lvalue_id        of fast_symbol::Raw_Symbol
       | lowercase_id     of fast_symbol::Raw_Symbol
       | lvalue_or_bar    of fast_symbol::Raw_Symbol
       | operators_id     of fast_symbol::Raw_Symbol
       | bar              of fast_symbol::Raw_Symbol
       | package          of Void
       | int              of multiword_int::Int
       | uppercase_path   of (fast_symbol::Raw_Symbol -> Symbol) -> List Symbol
       | mixedcase_path   of (fast_symbol::Raw_Symbol -> Symbol) -> List Symbol
       | lowercase_path   of (fast_symbol::Raw_Symbol -> Symbol) -> List Symbol
       | operators_path   of (fast_symbol::Raw_Symbol -> Symbol) -> List Symbol
       | lowercase        of (fast_symbol::Raw_Symbol -> Symbol) -> List Symbol
       | mixedcase        of (fast_symbol::Raw_Symbol -> Symbol) -> List Symbol
       | uppercase        of (fast_symbol::Raw_Symbol -> Symbol) -> List Symbol
       | value_path       of (fast_symbol::Raw_Symbol -> Symbol) -> List Symbol
       | selector         of Symbol
       | type             of List Symbol
       | typed_selector   of (Symbol, Any_Type)
       | typed_selectors  of List( (Symbol, Any_Type) )
       | anytype'         of Any_Type
       | tuple_ty         of List Any_Type
       | anytype          of Any_Type
       | ty0_pc           of List Any_Type
       | case_match       of List Case_Rule
       | darrow_rules     of List Case_Rule
       | eq_rule          of Case_Rule
       | darrow_rule      of Case_Rule
       | record_element   of (Symbol, Raw_Expression)
       | record_elements  of List( (Symbol, Raw_Expression))
       | init_expressions of List( ((Raw_Symbol, Int, Int), (Raw_Expression, Int, Int)))
       | loop_declarations of List( (Declaration, Int, Int) )
       | expression       of Raw_Expression 
       | expressionb      of Raw_Expression 
       | expressionc      of Raw_Expression 
       | modified_regular_expression   of Regular_Expression
       | regular_expression            of Regular_Expression
       | regular_expressions     of List( Regular_Expression )
       | block_contents  of Raw_Expression
       | block_declarations_and_expressions  of List Declaration
       | declaration_or_expression     of Declaration
       | app_exp         of List Fixity_Item Raw_Expression
       | prefix_exp      of List Fixity_Item Raw_Expression
       | postfix_exp     of List Fixity_Item Raw_Expression
       | dot_exp         of List Fixity_Item Raw_Expression
       | atomic_exp      of Raw_Expression
       | list_comprehension               of Raw_Expression
       | list_comprehension_result_clause of       elc::List_Comprehension_Clause
       | list_comprehension_for_clause    of       elc::List_Comprehension_Clause
       | list_comprehension_where_clause  of       elc::List_Comprehension_Clause
       | list_comprehension_clauses       of List( elc::List_Comprehension_Clause )

       | elifs           of Raw_Expression
       | expressions_1_n of List Raw_Expression
       | expressions_2_n of List Raw_Expression
       | quote           of List Raw_Expression
       | ot_list         of List Raw_Expression
       | pattern         of Case_Pattern
       | fun_apat        of Fixity_Item Case_Pattern
       | apat            of Fixity_Item Case_Pattern
       | apat'           of Case_Pattern
       | postfix_pat     of Fixity_Item Case_Pattern
       | plabel          of (Symbol, Case_Pattern)
       | plabels         of (List ((Symbol, Case_Pattern)), Bool)
       | pat_2c          of List Case_Pattern
       | pat_list        of List Case_Pattern
       | or_pat_list     of List Case_Pattern
       | vb              of List Named_Value
       | fields          of List Named_Field
       | constraint      of Null_Or Any_Type
       | rvb             of List Named_Recursive_Value
       | fun_clauses     of List Pattern_Clause
       | darrow_clauses  of List Pattern_Clause
       | fun_decls       of List Named_Function
       | maybe_lazy      of Bool
       | method_decls    of List Named_Function
       | message_decls   of List Named_Function
       | apats           of List Fixity_Item Case_Pattern
       | fun_apats       of List Fixity_Item Case_Pattern
       | eq_clause       of Pattern_Clause
       | darrow_clause   of Pattern_Clause
       | named_types     of List Named_Type
       | typevars  of List Typevar
       | tyvarseq        of List Typevar
       | tyvar_pc        of List Typevar
       | sumtypes of List Sumtype
       | constructors    of List( (Symbol, Null_Or Any_Type ))
       | constructor     of (Symbol, Null_Or Any_Type)
       | eb              of List Named_Exception 
       | package_in_import           of List List symbol::Symbol
       | fixity          of Fixity
       | declaration     of Declaration
       | declaration_or_local   of Declaration
       | overloaded_expressions of List Raw_Expression
       | overloaded_expression  of      Raw_Expression
       | maybe_declarations     of Declaration
       | declarations    of Declaration
       | ops             of List Symbol
       | api_elements    of List Api_Element
       | maybe_api_elements     of List Api_Element
       | api_element     of List Api_Element
#       | mixedcase_ids   of List Api_Element
       | package_in_api  of List( (Symbol, Api_Expression, Null_Or Path) )
       | generic_in_api   of List( (Symbol, Generic_Api_Expression) )
       | type_in_api     of List( (Symbol, List Typevar, Null_Or Any_Type) )
       | value_in_api    of List( (Symbol, Any_Type) )
       | exception_in_api     of List( (Symbol, Null_Or Any_Type) )
       | sharespec       of List Api_Element
       | patheqn         of (fast_symbol::Raw_Symbol -> Symbol) -> List List Symbol
       | typepatheqn     of (fast_symbol::Raw_Symbol -> Symbol) -> List List Symbol
       | where_spec      of List Where_Spec
       | an_api          of Api_Expression
       | maybe_api_constraint_op                 of Package_Cast Api_Expression
       | maybe_generic_api_constraint_op         of Package_Cast Generic_Api_Expression
       | api_naming          of List Named_Api
       | generic_api_naming    of List Named_Generic_Api
       | fsig                        of Generic_Api_Expression
       | a_package                   of Package_Expression
       | generic_arg                 of List( (Package_Expression, Bool) )
       | pkg_element                 of Declaration
       | pkg_elements                of Declaration
       | maybe_pkg_elements          of Declaration
       | toplevel                    of Declaration
       | toplevel_declaration        of Declaration
       | maybe_toplevel_declarations of Declaration
       | toplevel_declarations       of Declaration
       | named_packages              of List Named_Package
       | named_classes               of List Named_Package
       | named_class2es              of List Named_Package
       | generic_parameter     of (Null_Or Symbol, Api_Expression)
       | generic_parameter_list of List( (Null_Or Symbol, Api_Expression) )
       | generic_naming        of List Named_Generic
       | generic_expression    of Package_Cast Generic_Api_Expression -> Generic_Expression



# Finally, various random incidental declarations
# and settings. (See the mythryl-yacc docs for details.)
#
# The most important is the '%start' declaration,
# which specifies which rule is the top level of
# the grammar:


%start toplevel

%verbose
%pos Int
%arg (error) : ((Source_Position, Source_Position) -> error_message::Plaint_Sink)
%eop EOF SEMI
%noshift EOF

%nonassoc WITHTYPE_T
%nonassoc WHAT_COLON
%nonassoc COLON_WHAT
%nonassoc ELIF_T
%right ALSO_T
%right ARROW
%right BAR
%right DARROW 
%left  ELSE_T
%left  TILDA_TILDA
%right EXCEPT_T
%right OR_T
%right AND_T
%right AS_T
%left  COLON
%left  WEAK_PACKAGE_CAST
%left  PARTIAL_PACKAGE_CAST


%name Mythryl

%keyword ALSO_T AS_T CASE_T CLASS_T CLASS2_T DOTDOTDOT ELSE_T ELIF_T END_T 
  EQTYPE_T EXCEPTION_T  DARROW  FIELD_T  FN_T  FOR_T FUN_T  GENERIC_T EXCEPT_T
  HEREIN_T IF_T INCLUDE_T  INFIX_T  INFIXR_T  LAZY_T METHOD_T MY_T NONFIX_T
  RAISE_T  SHARING_T  API_T  
  PACKAGE_T STIPULATE_T WHERE_T WITHTYPE_T
  OR_T AND_T 

%change -> MY_T | -> ELSE_T | -> LPAREN | -> SEMI | 
        DARROW -> EQUAL_OP | EQUAL_OP -> DARROW | ALSO_T -> AND_T |
        SEMI -> COMMA | COMMA -> SEMI |
        -> ELSE_T LOWERCASE_ID

# %value ID (raw_symbol (bogus_hash, bogus_string))
%value LOWERCASE_PATH (raw_symbol (bogus_hash, bogus_string))
%value MIXEDCASE_PATH (raw_symbol (bogus_hash, bogus_string))
%value UPPERCASE_PATH (raw_symbol (bogus_hash, bogus_string))
%value OPERATORS_PATH (raw_symbol (bogus_hash, bogus_string))
%value LOWERCASE_ID (raw_symbol (bogus_hash, bogus_string))
%value MIXEDCASE_ID (raw_symbol (bogus_hash, bogus_string))
%value UPPERCASE_ID (raw_symbol (bogus_hash, bogus_string))
%value BOGUSCASE_ID (raw_symbol (bogus_hash, bogus_string))
%value OPERATORS_ID (raw_symbol (bogus_hash, bogus_string))
%value PASSIVEOP_ID (raw_symbol (bogus_hash, bogus_string))
%value PREFIX_OP_ID (raw_symbol (bogus_hash, bogus_string))
%value POSTFIX_OP_ID (raw_symbol (bogus_hash, bogus_string))
%value TYVAR (raw_symbol (dollar_bogus_hash, dollar_bogus_string))
%value INT  (multiword_int::from_int 1)
%value INT0 (multiword_int::from_int 0)
%value UNT (multiword_int::from_int 0)
%value FLOAT ("0.0")
%value STRING ("")
%value CHAR ("a")



# The grammar rule section proper starts after this
# next double-percent-sign separator.
#
# Rule names are flush-left, rule definitions follow,
# and rule actions are in parens to the right:
#
# We present the rules in bottom-up order, starting
# with the fiddly little stuff and ending with the
# high-level statements, so if you like a top-down
# presentation, you might want to read it in reverse
# order:


%%



##########################################
#  We start with a section building up   #
#  our type declaration syntax.          #
##########################################


uppercase_path:
      UPPERCASE_PATH                    (   # Handle a string like "foo::bar::ZOT".
                                            # This needs to become a string of typed symbols
                                            # [foo, bar, ZOT], but we don't know what kind
                                            # to make the last symbol yet, so we return
                                            # a closure that will generate the desired list
                                            # once supplied with the proper symbol-making
                                            # function ('kind'):
                                            #
                                            {   convert tokens
                                                where
                                                    uppercase_path ->   RAWSYM( word, string );         # String will be "foo::bar::ZOT" or such.

                                                    tokens = string::tokens
                                                                 (\\ c =  c == ':')             # Break string into tokens at ':' boundaries.
                                                                 string;

                                                    fun convert []
                                                            =>
                                                            {   exception IMPOSSIBLE;
                                                                raise exception IMPOSSIBLE;             # XXX BUGGO FIXME Should use some standard global exception here
                                                            };

                                                        convert [a]
                                                            =>
                                                            (\\ kind =  [kind (RAWSYM(hs::hash_string a, a))]);

                                                         convert (first ! rest)
                                                             =>
                                                             {   rest = convert rest;

                                                                 (\\ kind =  make_package_symbol (RAWSYM(hs::hash_string first, first))
                                                                             !
                                                                             rest kind);
                                                             };
                                                    end;
                                                end;
                                            }
                                        )



mixedcase_path:
      MIXEDCASE_PATH                    (   # Handle a string like "foo::bar::Zot".
                                            # This needs to become a string of typed symbols
                                            # [foo, bar, Zot], but we don't know what kind
                                            # to make the last symbol yet, so we return
                                            # a closure that will generate the desired list
                                            # once supplied with the proper symbol-making
                                            # function ('kind'):
                                            #
                                            {   convert tokens
                                                where
                                                    mixedcase_path ->   RAWSYM( word, string ); # String will be "foo::bar::Zot" or such.

                                                    tokens = string::tokens
                                                                 (\\ c =   c == ':')            # Break string into tokens at ':' boundaries.
                                                                 string;

                                                    fun convert []
                                                            =>
                                                            {   exception IMPOSSIBLE;
                                                                raise exception IMPOSSIBLE;             # XXX BUGGO FIXME Should use some standard global exception here
                                                            };

                                                        convert [a]
                                                            =>
                                                            (\\ kind =  [kind (RAWSYM(hs::hash_string a, a))]);

                                                         convert (first ! rest)
                                                             =>
                                                             {   rest = convert rest;

                                                                 (\\ kind =  make_package_symbol (RAWSYM(hs::hash_string first, first))
                                                                             !
                                                                             rest kind);
                                                             };
                                                    end;
                                                end;
                                            }
                                        )


lowercase_path:
      LOWERCASE_PATH                    (   # Handle a string like "foo::bar::zot".
                                            # This needs to become a list of typed symbols
                                            # [foo, bar, zot], but we don't know what kind
                                            # to make the last symbol yet, so we return
                                            # a closure that will generate the desired list
                                            # once supplied with the proper symbol-making
                                            # function ('kind'):
                                            #
                                            {   convert tokens
                                                where
                                                    lowercase_path ->   RAWSYM( _, path_string );                       # String will be "foo::bar::zot" or such.

                                                    tokens = string::tokens
                                                                 (\\ c =   c == ':')            # Break string into tokens at ':' boundaries.
                                                                 path_string;

                                                    fun convert []
                                                            =>
                                                            {   exception IMPOSSIBLE;
                                                                raise exception IMPOSSIBLE;             # XXX BUGGO FIXME Should use some standard global exception here
                                                            };

                                                        convert [a]
                                                            =>
                                                            (\\ kind =  [kind (RAWSYM(hs::hash_string a, a))]);

                                                         convert (first ! rest)
                                                             =>
                                                             {   rest = convert rest;

                                                                 (\\ kind =  make_package_symbol (RAWSYM(hs::hash_string first, first))
                                                                             !
                                                                             rest kind);
                                                             };
                                                    end;
                                                end;
                                            }
                                        )


operators_path:
      OPERATORS_PATH                    (   # Handle a string like "foo::bar::(++)".
                                            # This needs to become a string of typed symbols
                                            # [foo, bar, ++], but we don't know what kind
                                            # to make the last symbol yet, so we return
                                            # a closure that will generate the desired list
                                            # once supplied with the proper symbol-making
                                            # function ('kind'):
                                            #
                                            {   convert tokens
                                                where
                                                    operators_path ->   RAWSYM( word, string );         # 'string' will be "foo::bar::(++)" or such.

                                                    tokens = explode_path string;                       # Convert "foo::bar::(++)" to ["foo", "bar", "(++)"]

                                                    fun convert []
                                                            =>
                                                            {   exception IMPOSSIBLE;
                                                                raise exception IMPOSSIBLE;             # XXX BUGGO FIXME Should use some standard global exception here
                                                            };

                                                        convert [a]             # 'a' will be `(++)` or such.
                                                            =>
                                                            {   a = substring::from_string  a;          # Convert `(++)` from String to Substring.
                                                                a = substring::drop_first 1 a;          # Drop left  paren.
                                                                a = substring::drop_last  1 a;          # Drop right paren.
                                                                a = substring::to_string    a;          # Convert back to a string.
                                                                #
                                                                (\\ kind =  [kind (RAWSYM(hs::hash_string a, a))]);
                                                            };

                                                         convert (first ! rest)
                                                             =>
                                                             {   rest = convert rest;

                                                                 (\\ kind =  make_package_symbol (RAWSYM(hs::hash_string first, first))
                                                                             !
                                                                             rest kind);
                                                             };
                                                    end;
                                                end;
                                            }
                                        )




# Integer constants and identifiers:

int:  INT                               (int)
    | INT0                              (int0)

nonprefix_value_or_bar:
      UPPERCASE_ID                      (uppercase_id)
    | lowercase_id                      (lowercase_id)
    | bar                               (bar)
    | OPERATORS_ID                      (operators_id)
    | AMPER                             (raw_symbol (amper_hash,    amper_string))
    | ATSIGN                            (raw_symbol (atsign_hash,   atsign_string))
    | BACK                              (raw_symbol (back_hash,     back_string))
    | BANG                              (raw_symbol (bang_hash,     bang_string))
    | BUCK                              (raw_symbol (buck_hash,     buck_string))
    | CARET                             (raw_symbol (caret_hash,    caret_string))
    | DASH                              (raw_symbol (dash_hash,     dash_string))
    | PERCNT                            (raw_symbol (percnt_hash,   percnt_string))
    | PLUS                              (raw_symbol (plus_hash,     plus_string))
    | QMARK                             (raw_symbol (qmark_hash,    qmark_string))
    | SLASH                             (raw_symbol (slash_hash,    slash_string))
    | STAR                              (raw_symbol (star_hash,     star_string))
    | TILDA                             (raw_symbol (tilda_hash,    tilda_string))
    | LANGLE                            (raw_symbol (langle_hash,   langle_string))
    | RANGLE                            (raw_symbol (rangle_hash,   rangle_string))
    | EQEQ_OP                           (raw_symbol (eqeq_hash,     eqeq_string))
    | PLUS_PLUS                         (raw_symbol (plusplus_hash, plusplus_string))
    | DASH_DASH                         (raw_symbol (dashdash_hash, dashdash_string))
    | DOTDOT                            (raw_symbol (dotdot_hash,   dotdot_string))

postfix_op:
      POSTFIX_OP_ID                     (postfix_op_id)
    | POST_AMPER                        (raw_symbol (postamper_hash,  postamper_string))
    | POST_ATSIGN                       (raw_symbol (postatsign_hash, postatsign_string))
    | POST_BACK                         (raw_symbol (postback_hash,   postback_string))
    | POST_BANG                         (raw_symbol (postbang_hash,   postbang_string))
    | POST_BAR                          (raw_symbol (postbar_hash,    postbar_string))
    | POST_BUCK                         (raw_symbol (postbuck_hash,   postbuck_string))
    | POST_CARET                        (raw_symbol (postcaret_hash,  postcaret_string))
    | POST_DASH                         (raw_symbol (postdash_hash,   postdash_string))
    | POST_PERCNT                       (raw_symbol (postpercnt_hash, postpercnt_string))
    | POST_PLUS                         (raw_symbol (postplus_hash,   postplus_string))
    | POST_QMARK                        (raw_symbol (postqmark_hash,  postqmark_string))
    | POST_STAR                         (raw_symbol (poststar_hash,   poststar_string))
    | POST_TILDA                        (raw_symbol (posttilda_hash,  posttilda_string))
    | POST_DASHDASH                     (raw_symbol (post_dashdash_hash,  post_dashdash_string))
    | POST_PLUSPLUS                     (raw_symbol (post_plusplus_hash,  post_plusplus_string))
    | POST_DOTDOT                       (raw_symbol (post_dotdot_hash,  post_dotdot_string))

prefix_op:
      PREFIX_OP_ID                      (prefix_op_id)
    | PRE_AMPER                         (raw_symbol (preamper_hash,  preamper_string))
    | PRE_ATSIGN                        (raw_symbol (preatsign_hash, preatsign_string))
    | PRE_BACK                          (raw_symbol (preback_hash,   preback_string))
    | PRE_BANG                          (raw_symbol (prebang_hash,   prebang_string))
    | PRE_BAR                           (raw_symbol (prebar_hash,    prebar_string))
    | PRE_CARET                         (raw_symbol (precaret_hash,  precaret_string))
    | PRE_DASH                          (raw_symbol (predash_hash,   predash_string))
    | PRE_PLUS                          (raw_symbol (preplus_hash,   preplus_string))
    | PRE_QMARK                         (raw_symbol (preqmark_hash,  preqmark_string))
    | PRE_STAR                          (raw_symbol (prestar_hash,   prestar_string))
    | PRE_TILDA                         (raw_symbol (pretilda_hash,  pretilda_string))

value_or_bar: UPPERCASE_ID              (uppercase_id)
    |     lvalue_or_bar                 (lvalue_or_bar)

value_id: UPPERCASE_ID                  (uppercase_id)
    |     lvalue_id                     (lvalue_id)

lvalue_or_bar:
      lvalue_id                         (lvalue_id)
    | bar                               (bar)

lvalue_id:
      lowercase_id                      (lowercase_id)
    | operators_id                      (operators_id)

# Vanilla lower-case identifiers.
# by listing 'FIELD_T' etc here
# we make them effectively plain
# identifiers so far as application
# programmers are concerned, while
# still allowing the parser to respond
# specially to them in particular
# syntactic contexts such as between
# ';' and 'my'/'fun'/'package'/'api'/...:
#
lowercase_id:
      LOWERCASE_ID                      (lowercase_id)
    | FIELD_T                           (raw_symbol (     field_hash,       field_string))
    | GENERIC_T                         (raw_symbol (   generic_hash,     generic_string))
    | IN_T                              (raw_symbol (        in_hash,          in_string))
    | INCLUDE_T                         (raw_symbol (   include_hash,     include_string))
    | INFIXR_T                          (raw_symbol (    infixr_hash,      infixr_string))
    | INFIX_T                           (raw_symbol (     infix_hash,       infix_string))
    | MESSAGE_T                         (raw_symbol (   message_hash,     message_string))
    | METHOD_T                          (raw_symbol (    method_hash,      method_string))
    | NONFIX_T                          (raw_symbol (    nonfix_hash,      nonfix_string))
    | OVERLOADED_T                      (raw_symbol (overloaded_hash,  overloaded_string))
    | RAISE_T                           (raw_symbol (     raise_hash,       raise_string))
    | RECURSIVE_T                       (raw_symbol ( recursive_hash,   recursive_string))

operators_id:
      OPERATORS_ID                      (operators_id)
    | AMPER                             (raw_symbol (amper_hash,    amper_string))
    | ATSIGN                            (raw_symbol (atsign_hash,   atsign_string))
    | BACK                              (raw_symbol (back_hash,     back_string))
    | BANG                              (raw_symbol (bang_hash,     bang_string))
    | BUCK                              (raw_symbol (buck_hash,     buck_string))
    | CARET                             (raw_symbol (caret_hash,    caret_string))
    | DASH                              (raw_symbol (dash_hash,     dash_string))
    | PERCNT                            (raw_symbol (percnt_hash,   percnt_string))
    | PLUS                              (raw_symbol (plus_hash,     plus_string))
    | QMARK                             (raw_symbol (qmark_hash,    qmark_string))
    | SLASH                             (raw_symbol (slash_hash,    slash_string))
    | STAR                              (raw_symbol (star_hash,     star_string))
    | TILDA                             (raw_symbol (tilda_hash,    tilda_string))

    | LANGLE                            (raw_symbol (langle_hash,   langle_string))
    | RANGLE                            (raw_symbol (rangle_hash,   rangle_string))

    | EQEQ_OP                           (raw_symbol (eqeq_hash,     eqeq_string))

    | DASH_DASH                         (raw_symbol (dashdash_hash,  dashdash_string))
    | PLUS_PLUS                         (raw_symbol (plusplus_hash,  plusplus_string))
    | DOTDOT                            (raw_symbol (dotdot_hash,    dotdot_string))

    | PRE_AMPER                         (raw_symbol (preamper_hash,  preamper_string))
    | PRE_ATSIGN                        (raw_symbol (preatsign_hash, preatsign_string))
    | PRE_BACK                          (raw_symbol (preback_hash,   preback_string))
    | PRE_BANG                          (raw_symbol (prebang_hash,   prebang_string))
    | PRE_BUCK                          (raw_symbol (prebuck_hash,   prebuck_string))
    | PRE_CARET                         (raw_symbol (precaret_hash,  precaret_string))
    | PRE_DASH                          (raw_symbol (predash_hash,   predash_string))
    | PRE_PERCNT                        (raw_symbol (prepercnt_hash, prepercnt_string))
    | PRE_PLUS                          (raw_symbol (preplus_hash,   preplus_string))
    | PRE_QMARK                         (raw_symbol (preqmark_hash,  preqmark_string))
    | PRE_STAR                          (raw_symbol (prestar_hash,   prestar_string))
    | PRE_TILDA                         (raw_symbol (pretilda_hash,  pretilda_string))



bar:  BAR                               (raw_symbol (bar_hash,     bar_string))





# Paths (qualified identifiers like "a::b::c")
# name a package or part of a package.
# The identifiers before a "::" must
# name a package, and package names must
# be lowercase, hence all but the last
# part of a qualified identifier must
# be lowercase.  Paths are recognized
# in the lexer, and arrive here as single
# tokens.  (If we didn't do this, parsing
# would fail to be LALR(1) due to insufficient
# lookahead -- a::Type and a::some_value
# would be indistinguishable until too late.)

# Handle "foo" or "his::foo":
#
lowercase:
      lowercase_path                    (\\ kind =  lowercase_path kind)
    | lowercase_id                      (\\ kind =  [kind lowercase_id])

# Handle "Foo" or "his::Foo":
#
mixedcase:
      mixedcase_path                    (\\ kind =  mixedcase_path kind)
    | MIXEDCASE_ID                      (\\ kind =  [kind mixedcase_id])

# Handle "FOO" or "his::FOO":
uppercase:
      uppercase_path                    (\\ kind =  uppercase_path kind)
    | UPPERCASE_ID                      (\\ kind =  [kind uppercase_id])


# Same as above, but with different rule actions,
# for use in type syntax: 


type:
      mixedcase                         (mixedcase make_type_symbol)



# Record selectors like and.name
# tuple  selectors like #1

selector:
      lowercase_id                      (make_label_symbol lowercase_id)
    | INT                               (symbol::make_label_symbol (multiword_int::to_string int))



# Typed selectors like "length: Int",
# for use in record type declarations like
#    ... {   name: String,   length: int,   dumb: Bool } ...

typed_selector:
      selector COLON anytype                    (selector, anytype )
    | anytype selector                          (selector, anytype )


# ... and comma-separated sequences of them:

typed_selectors:
      typed_selector COMMA typed_selectors      (typed_selector ! typed_selectors)
    | typed_selector                            ([typed_selector])



# With the above details out of the way,
# we are now in a position to give rules
# for the core type declaration syntax,
# including record, tuple and function types:

anytype':
      LBRACE RBRACE                     (RECORD_TYPE [])

    | LPAREN anytype RPAREN             (anytype)

    | TYVAR                             (   SOURCE_CODE_REGION_FOR_TYPE (
                                                TYPEVAR_TYPE   (TYPEVAR (make_typevar_symbol tyvar)),
                                                (tyvarleft, tyvarright)
                                        )   )

    | LBRACE typed_selectors RBRACE     (    SOURCE_CODE_REGION_FOR_TYPE (
                                                 RECORD_TYPE typed_selectors,
                                                 (lbraceleft, rbraceright)
                                        )    )

    | type
      LPAREN
          ty0_pc
      RPAREN
                                        (    SOURCE_CODE_REGION_FOR_TYPE (
                                                 TYPE_TYPE (type, ty0_pc),
                                                 (typeleft, typeright)
                                        )    )

    | type anytype'                     (    SOURCE_CODE_REGION_FOR_TYPE (
                                                TYPE_TYPE (type, [anytype']),
                                                (typeleft, typeright)
                                        )    )

    | type                              (    SOURCE_CODE_REGION_FOR_TYPE (
                                                TYPE_TYPE (type, []),
                                                (typeleft, typeright)
                                        )    )



tuple_ty:
      anytype COMMA tuple_ty            (anytype ! tuple_ty)
    | anytype COMMA anytype             ( [ anytype1, anytype2 ] )




anytype:
      LPAREN tuple_ty RPAREN            (TUPLE_TYPE tuple_ty)
    | anytype ARROW anytype             (TYPE_TYPE ( [arrow_type], [anytype1, anytype2]))
    | anytype'                          (anytype')
        


ty0_pc:
      anytype COMMA anytype                     ( [anytype1, anytype2] )
    | anytype COMMA ty0_pc                      (  anytype ! ty0_pc    )



# This is for single-rule '\\' or 'except' clauses:
eq_rule:
      pattern
      EQUAL_OP
      expression                        (   CASE_RULE {
                                                pattern, 
                                                expression => mark_expression (   expression,
                                                                                  expressionleft,
                                                                                  expressionright
                                                                              )
                                            }
                                        )

# This is for multi-rule '\\' or 'except' clauses
# and all 'case' statements:
darrow_rule:
      pattern
      DARROW
      expression
      SEMI                              (   CASE_RULE {
                                                pattern, 
                                                expression => mark_expression (   expression,
                                                                                  expressionleft,
                                                                                  expressionright
                                                                              )
                                            }
                                        )

darrow_rules:
      darrow_rule                       ( [darrow_rule] )
    | darrow_rule darrow_rules          (darrow_rule ! darrow_rules)





#########################################
#  In the second section we build up    #
#  our core expression syntax:          #
#########################################





# "label=expression" pairs for record expressions.
#
# The first two rules here were originally the single
# rule "selector EQUAL_OP expression" but I had to
# expand 'selector' in-place to avoid a shift-reduce error:
#
record_element:
      INT          DARROW   expression  ((symbol::make_label_symbol (multiword_int::to_string int)), expression)
    | lowercase_id DARROW   expression  ((make_label_symbol lowercase_id), expression)
    | selector                          (selector, VARIABLE_IN_EXPRESSION [ symbol::make_value_symbol (symbol::name selector) ])



# Comma-separated sequences of them: 
#
record_elements:
      record_element COMMA record_elements      (record_element ! record_elements)
    | record_element                            ([record_element])


expression:
      expressionb                       (expressionb)

    | expression COLON anytype          (TYPE_CONSTRAINT_EXPRESSION { expression, constraint => anytype } )

    | expression OR_T expression        (OR_EXPRESSION (
                                            mark_expression (expression1, expression1left, expression1right),
                                            mark_expression (expression2, expression2left, expression2right)
                                        ) )

    | expression AND_T expression       (AND_EXPRESSION (
                                            mark_expression (expression1, expression1left, expression1right),
                                            mark_expression (expression2, expression2left, expression2right)
                                        ) )

    | expression EXCEPT_T eq_rule       (EXCEPT_EXPRESSION { expression, rules =>[eq_rule]})
    | expression EXCEPT_T
      darrow_rules END_T                (EXCEPT_EXPRESSION { expression, rules => darrow_rules })

    | prefix_exp
      WHAT_COLON
      expression                        (   {   IF_EXPRESSION
                                                    { test_case => PRE_FIXITY_EXPRESSION prefix_exp,
                                                      then_case => mark_expression (expression, expressionleft, expressionright),
                                                      else_case => void_expression
                                                    };
                                            }
                                        )


    | expression
      COLON_WHAT
      prefix_exp                        (   {   IF_EXPRESSION
                                                    { test_case => PRE_FIXITY_EXPRESSION prefix_exp,
                                                      then_case => mark_expression (expression, expressionleft, expressionright),
                                                      else_case => void_expression
                                                    };
                                            }
                                        )




    | FN_T eq_rule                      (mark_expression (FN_EXPRESSION [eq_rule], fn_tleft, eq_ruleright))


    | app_exp
      WHERE_T
          block_declarations_and_expressions
      END_T                             (   # Convert the 'where' expression to a block,
                                            # and thence to a LET_EXPRESSION:
                                            {
                                                app_exp_as_expression
                                                    =
                                                    PRE_FIXITY_EXPRESSION ( app_exp );

                                                expression_as_declaration
                                                    =
                                                    mark_declaration (
                                                        VALUE_DECLARATIONS (
                                                            [   NAMED_VALUE {
                                                                    expression => app_exp_as_expression,
                                                                    pattern    => WILDCARD_PATTERN,
                                                                    is_lazy    => FALSE
                                                                }
                                                            ],
                                                            NIL
                                                        ),
                                                        app_expleft,
                                                        end_tright
                                                    );

                                                declaration_list
                                                    = 
                                                    expression_as_declaration 
                                                    !
                                                    block_declarations_and_expressions;

                                                raw_syntax_junk::block_to_let  declaration_list;        # NB: List is in reverse order.
                                            }
                                        )


    # This is the old 'while' loop, now
    # using the 'for' keyword because I
    # don't want to waste a perfectly good
    # identifier like 'while' on it:
    #
    | FOR_T
      LPAREN expression RPAREN
      expression                        (WHILE_EXPRESSION
                                            {   test       => mark_expression (expression1, expression1left, expression1right),
                                                expression => mark_expression (expression2, expression2left, expression2right)
                                            }
                                        )

    # Allow infinite loops to be written
    #    
    #     for () { ... }
    #    
    #
    | FOR_T
      LPAREN RPAREN
      expression                        (WHILE_EXPRESSION
                                            {   test       => VARIABLE_IN_EXPRESSION [ fast_symbol::make_value_symbol' "TRUE" ],
                                                expression => mark_expression (expression, expressionleft, expressionright)
                                            }
                                        )

    # Allow infinite loops to be written
    #    
    #     for (;;) { ... }
    #    
    # per C tradition:
    #
    | FOR_T
      LPAREN SEMI SEMI RPAREN
      expression                        (WHILE_EXPRESSION
                                            {   test       => VARIABLE_IN_EXPRESSION [ fast_symbol::make_value_symbol' "TRUE" ],
                                                expression => mark_expression (expression, expressionleft, expressionright)
                                            }
                                        )

    | FOR_T
      LPAREN
          init_expressions
          SEMI
          expression                    # test_expression
          SEMI
          loop_declarations             # loop_expression
      RPAREN 
      expression                        # body_expression

                                        (make_raw_syntax::for_loop
                                             ( (for_tleft,       for_tright),
                                               init_expressions,
                                               (expression1,     expression1left,  expression1right),
                                               loop_declarations,
                                               (void_expression, semi1right,       rparenleft),
                                               (expression2,     expression2left,  expression2right)
                                        )    )

    | FOR_T
      LPAREN
          init_expressions
          SEMI
          expression                    # test_expression
          SEMI
          loop_declarations             # loop_expression
          SEMI
          expression                    # done_expression
      RPAREN 
      expression                        # body_expression

                                        (make_raw_syntax::for_loop
                                             ( (for_tleft,       for_tright),
                                               init_expressions,
                                               (expression1,     expression1left,  expression1right),
                                               loop_declarations,
                                               (expression2,     expression2left,  expression2right),
                                               (expression3,     expression3left,  expression3right)
                                        )    )

    | RAISE_T EXCEPTION_T expression    (mark_expression (
                                            mark_expression (RAISE_EXPRESSION expression, expressionleft, expressionright),
                                            raise_tleft, expressionright
                                        ) )

    | expression
      TILDA_TILDA
      SLASH
      regular_expressions
      SLASH                             (    regex_to_raw_syntax (
                                                 expression,
                                                 regular_expressions,
                                                 expressionleft,
                                                 expressionright,
                                                 regular_expressionsright
                                             )
                                        )


# Init expressions for 'for' loops:
#
init_expressions:

      lowercase_id EQUAL_OP expression
      COMMA
      init_expressions                          (  ( (lowercase_id, lowercase_idleft, lowercase_idright),
                                                     (expression,   expressionleft,   expressionright)
                                                   )
                                                   !
                                                   init_expressions
                                                )

    | lowercase_id EQUAL_OP expression          ( [ ( (lowercase_id, lowercase_idleft, lowercase_idright),
                                                      (expression,   expressionleft,   expressionright)
                                                    )
                                                  ]
                                                )


# Loop declarations (e.g., ++x, y+=10) for 'for' loops:
#
loop_declarations:
                                                ([])
    | declaration                               ( [ (declaration, declarationleft, declarationright) ] )
    | declaration COMMA loop_declarations       (   (declaration, declarationleft, declarationright)
                                                    !
                                                    loop_declarations
                                                )




expressionb:
      expressionc                       (expressionc)

    | expressionc
      WHAT_WHAT
      expressionc
      COLON_COLON
      expressionc
                                         (  {   IF_EXPRESSION
                                                    { test_case => expressionc1,
                                                      then_case => mark_expression (expressionc2, expressionc2left, expressionc2right),
                                                      else_case => mark_expression (expressionc3, expressionc3left, expressionc3right)
                                                    };
                                            }
                                        )

expressionc:
      app_exp                           (PRE_FIXITY_EXPRESSION app_exp)



# Mythryl apply expressions like "f x"
# -- and also infix expressions like 'a+b'.
#
# These are the components that fill out the
# above control structures.
#
# If they look mysteriously formless here,
# it is because at this point we just
# collect stuff like "a+b*c-d" as an
# unstructured list:  Actually turning
# this list into a tree structure according
# to the proper precedence rules is done
# much later in a post-pass -- see
#
#    src/lib/compiler/front/typer/main/resolve-operator-precedence.pkg
#
# (We need to defer operator precedence
# handling to a post-pass because of
# the "infix" and "infixr" declarations
# which change the desired parse in ways
# the the parser has no way of knowing about.)
                                                                                # printf_format_string_to_raw_syntax    is from   src/lib/compiler/front/parser/raw-syntax/printf-format-string-to-raw-syntax.pkg
app_exp:

      postfix_exp                       (postfix_exp)

    | postfix_exp app_exp               (postfix_exp @ app_exp)


# Here we implement "x!" and "x*" etc,
# which we want to bind tighter than "f x"
# yet looser than "!x":
#
postfix_exp:

      prefix_exp                        (prefix_exp)

    # *a !a -a +a \a &a @a ^a %a ?a ~a
    #
    | prefix_exp postfix_op             (   {   my (v, f)
                                                   =
                                                   make_value_and_fixity_symbols  postfix_op;

                                               postfix_op_item
                                                   =
                                                   { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], postfix_opleft, postfix_opright),
                                                     source_code_region => (postfix_opleft, postfix_opright),
                                                     fixity             => THE f
                                                   };

                                               expression
                                                   =
                                                   PRE_FIXITY_EXPRESSION ( postfix_op_item ! prefix_exp );

                                                [   { item               => mark_expression (expression, prefix_expleft, postfix_opright),
                                                      source_code_region => (prefix_expleft, postfix_opright),
                                                      fixity             => NULL
                                                    }
                                                ];
                                           }
                                       )
    # /a/
    | PRE_SLASH prefix_exp POST_SLASH  (   {   my (v, f)
                                                   =
                                                   make_value_and_fixity_symbols  (make_raw_symbol "/_/");

                                               slashens_op_item
                                                   =
                                                   { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], pre_slashleft, post_slashright),
                                                     source_code_region => (pre_slashleft, post_slashright),
                                                     fixity              => THE f
                                                   };

                                               expression
                                                   =
                                                   PRE_FIXITY_EXPRESSION ( slashens_op_item ! prefix_exp );

                                                [   { item               => mark_expression (expression, pre_slashleft, post_slashright),
                                                      source_code_region => (pre_slashleft, post_slashright),
                                                      fixity             => NULL
                                                    }
                                                ];
                                           }
                                       )
    # |a|
    | PRE_BAR prefix_exp POST_BAR      (   {   my (v, f)
                                                   =
                                                   make_value_and_fixity_symbols  (make_raw_symbol "|_|");

                                               barens_op_item
                                                   =
                                                   { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], pre_barleft, post_barright),
                                                     source_code_region => (pre_barleft, post_barright),
                                                     fixity             => THE f
                                                   };

                                               expression
                                                   =
                                                   PRE_FIXITY_EXPRESSION ( barens_op_item ! prefix_exp );

                                                [   { item               => mark_expression (expression, pre_barleft, post_barright),
                                                      source_code_region => (pre_barleft, post_barright),
                                                      fixity             => NULL
                                                    }
                                                ];
                                           }
                                       )

    # <a>
    #
    | PRE_LANGLE prefix_exp POST_RANGLE  (   {   my (v, f)
                                                   =
                                                   make_value_and_fixity_symbols  (make_raw_symbol "<_>");

                                               anglens_op_item
                                                   =
                                                   { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], pre_langleleft, post_rangleright),
                                                     source_code_region => (pre_langleleft, post_rangleright),
                                                     fixity             => THE f
                                                   };

                                               expression
                                                   =
                                                   PRE_FIXITY_EXPRESSION ( anglens_op_item ! prefix_exp );

                                                [   { item               => mark_expression (expression, pre_langleleft, post_rangleright),
                                                      source_code_region => (pre_langleleft, post_rangleright),
                                                      fixity             => NULL
                                                    }
                                                ];
                                           }
                                       )

    # <a|
    #
    | PRE_LANGLE prefix_exp POST_BAR   (   {   my (v, f)
                                                   =
                                                   make_value_and_fixity_symbols  (make_raw_symbol "<_|");

                                               angbar_op_item
                                                   =
                                                   { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], pre_langleleft, post_barright),
                                                     source_code_region => (pre_langleleft, post_barright),
                                                     fixity             => THE f
                                                   };

                                               expression
                                                   =
                                                   PRE_FIXITY_EXPRESSION ( angbar_op_item ! prefix_exp );

                                                [   { item               => mark_expression (expression, pre_langleleft, post_barright),
                                                      source_code_region => (pre_langleleft, post_barright),
                                                      fixity             => NULL
                                                    }
                                                ];
                                           }
                                       )

    # |a>
    #
    | PRE_BAR prefix_exp POST_RANGLE   (   {   my (v, f)
                                                   =
                                                   make_value_and_fixity_symbols  (make_raw_symbol "|_>");

                                               barang_op_item
                                                   =
                                                   { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], pre_barleft, post_rangleright),
                                                     source_code_region => (pre_barleft, post_rangleright),
                                                     fixity             => THE f
                                                   };

                                               expression
                                                   =
                                                   PRE_FIXITY_EXPRESSION ( barang_op_item ! prefix_exp );

                                                [   { item               => mark_expression (expression, pre_barleft, post_rangleright),
                                                      source_code_region => (pre_barleft, post_rangleright),
                                                      fixity             => NULL
                                                    }
                                                ];
                                           }
                                       )

    # {a}
    #
    | PRE_LBRACE prefix_exp POST_RBRACE (   {   my (v, f)
                                                   =
                                                   make_value_and_fixity_symbols  (make_raw_symbol "{_}");

                                               bracens_op_item
                                                   =
                                                   { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], pre_lbraceleft, post_rbraceright),
                                                     source_code_region => (pre_lbraceleft, post_rbraceright),
                                                     fixity             => THE f
                                                   };

                                               expression
                                                   =
                                                   PRE_FIXITY_EXPRESSION ( bracens_op_item ! prefix_exp );

                                                [   { item               => mark_expression (expression, pre_lbraceleft, post_rbraceright),
                                                      source_code_region => (pre_lbraceleft, post_rbraceright),
                                                      fixity             => NULL
                                                    }
                                                ];
                                           }
                                       )
    # a[b]
    #
    | prefix_exp
      POST_LBRACKET
      app_exp
      RBRACKET                         (   {   my (v, f)
                                                   =
                                                   make_value_and_fixity_symbols  (make_raw_symbol "_[]");

                                               expressions
                                                   =
                                                   [ PRE_FIXITY_EXPRESSION  prefix_exp,
                                                     PRE_FIXITY_EXPRESSION  app_exp
                                                   ];

                                               atomic_exp
                                                   =
                                                   TUPLE_EXPRESSION  expressions;

                                               dot_exp
                                                   =
                                                   [   {   item               =>  mark_expression (atomic_exp, prefix_expleft, rbracketright),
                                                           source_code_region =>  (prefix_expleft, rbracketright),
                                                           fixity             =>  NULL
                                                       }
                                                   ];

                                               sub_op_item
                                                   =
                                                   { item               =>  mark_expression (VARIABLE_IN_EXPRESSION [v], post_lbracketleft, rbracketright),
                                                     source_code_region =>  (post_lbracketleft, rbracketright),
                                                     fixity             =>  THE f
                                                   };

                                               expression
                                                   =
                                                   PRE_FIXITY_EXPRESSION ( sub_op_item ! dot_exp );

                                                [   { item               =>  mark_expression (expression, prefix_expleft, rbracketright),
                                                      source_code_region =>  (prefix_expleft, rbracketright),
                                                      fixity             =>  NULL
                                                    }
                                                ];
                                           }
                                       )

    # a[b,c]
    #
    | prefix_exp
      POST_LBRACKET
      expressions_2_n
      RBRACKET                         (   {   my (v, f)
                                                   =
                                                   make_value_and_fixity_symbols  (make_raw_symbol "_[]");

                                               indices
                                                   =
                                                   [   {   item               =>  mark_expression ((TUPLE_EXPRESSION expressions_2_n), post_lbracketleft, rbracketright),
                                                           source_code_region =>  (post_lbracketleft, rbracketright),
                                                           fixity             =>  NULL
                                                       }
                                                   ];

                                               expressions
                                                   =
                                                   [ PRE_FIXITY_EXPRESSION  prefix_exp,
                                                     PRE_FIXITY_EXPRESSION  indices
                                                   ];

                                               atomic_exp
                                                   =
                                                   TUPLE_EXPRESSION  expressions;

                                               dot_exp
                                                   =
                                                   [   {   item               =>  mark_expression (atomic_exp, prefix_expleft, rbracketright),
                                                           source_code_region =>  (prefix_expleft, rbracketright),
                                                           fixity             =>  NULL
                                                       }
                                                   ];

                                               sub_op_item
                                                   =
                                                   { item               =>  mark_expression (VARIABLE_IN_EXPRESSION [v], post_lbracketleft, rbracketright),
                                                     source_code_region =>  (post_lbracketleft, rbracketright),
                                                     fixity             =>  THE f
                                                   };

                                               expression
                                                   =
                                                   PRE_FIXITY_EXPRESSION ( sub_op_item ! dot_exp );

                                                [   { item               =>  mark_expression (expression, prefix_expleft, rbracketright),
                                                      source_code_region =>  (prefix_expleft, rbracketright),
                                                      fixity             =>  NULL
                                                    }
                                                ];
                                           }
                                       )

# Here we implement "!x" and "*x" etc,
# which we want to bind tighter than "f x"
# yet looser than "a.b":
#
prefix_exp:
      dot_exp                           (dot_exp)

    | PRINTF_T STRING                   (printf_format_string_to_raw_syntax::make_anonymous_curried_function
                                            ( NULL,             # Only fprintf has an fd arg.
                                              string,           # "%d %6.2f %-15s\n" or such.
                                              error,
                                              printf_tleft,
                                              stringleft,
                                              stringright,
                                              printf_format_string_to_raw_syntax::PRINTF
                                            )
                                        )


    | SPRINTF_T STRING                  (printf_format_string_to_raw_syntax::make_anonymous_curried_function
                                            ( NULL,             # Only fprintf has an fd arg.
                                              string,           # "%d %6.2f %-15s\n" or such.
                                              error,
                                              sprintf_tleft,
                                              stringleft,
                                              stringright,
                                              printf_format_string_to_raw_syntax::SPRINTF
                                            )
                                        )

    | FPRINTF_T dot_exp STRING          (printf_format_string_to_raw_syntax::make_anonymous_curried_function
                                            ( THE dot_exp,      # Only fprintf has an fd arg.
                                              string,           # "%d %6.2f %-15s\n" or such.
                                              error,
                                              fprintf_tleft,
                                              stringleft,
                                              stringright,
                                              printf_format_string_to_raw_syntax::FPRINTF
                                            )
                                        )

    | prefix_op dot_exp                 (   {   my (v, f)
                                                   =
                                                   make_value_and_fixity_symbols  prefix_op;

                                               prefix_op_item
                                                   =
                                                   { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], prefix_opleft, prefix_opright),
                                                     source_code_region => (prefix_opleft, prefix_opright),
                                                     fixity             => THE f
                                                   };

                                               expression
                                                   =
                                                   PRE_FIXITY_EXPRESSION ( prefix_op_item ! dot_exp );

                                                [   { item               => mark_expression (expression, prefix_opleft, dot_expright),
                                                      source_code_region => (prefix_opleft, dot_expright),
                                                      fixity             => NULL
                                                    }
                                                ];
                                           }
                                       )


# Here we implement 'dot' expressions 'a.b'
# which select field b from record a.
# We have them bind tighter than functional application,
# so we can write f a.b:
#
dot_exp:

      nonprefix_value_or_bar            (   [   {   my (v, f)
                                                        =
                                                        make_value_and_fixity_symbols  nonprefix_value_or_bar;

                                                    {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], nonprefix_value_or_barleft, nonprefix_value_or_barright),
                                                        source_code_region => (nonprefix_value_or_barleft, nonprefix_value_or_barright),
                                                        fixity             => THE f
                                                    };
                                                }
                                            ]
                                        )

    | IMPLICIT_THUNK_PARAMETER          (   [   {   my (v, f)
                                                        =
                                                        make_value_and_fixity_symbols  implicit_thunk_parameter;

                                                    {   item               => mark_expression (IMPLICIT_THUNK_PARAMETER [v], implicit_thunk_parameterleft, implicit_thunk_parameterright),
                                                        source_code_region => (implicit_thunk_parameterleft, implicit_thunk_parameterright),
                                                        fixity             => THE f
                                                    };
                                                }
                                            ]
                                        )


    | PASSIVEOP_ID                      (   [   {   {   item               => mark_expression (VARIABLE_IN_EXPRESSION [make_value_symbol passiveop_id], passiveop_idleft, passiveop_idright),
                                                        source_code_region => (passiveop_idleft, passiveop_idright),
                                                        fixity             => NULL
                                                    };
                                                }
                                            ]
                                        )

    | atomic_exp                        (   [   {   item               => mark_expression (atomic_exp, atomic_expleft, atomic_expright),
                                                    source_code_region => (atomic_expleft, atomic_expright),
                                                    fixity             => NULL
                                                }
                                            ]
                                        )


    | dot_exp DOT selector              (  # We want 'a.b' to be exactly the same as '.b a'
                                           # so here we just build the value that the latter
                                           # would have produced:

                                           {    selector_exp
                                                    =
                                                    (mark_expression (RECORD_SELECTOR_EXPRESSION selector, selectorleft, selectorright));

                                                selector_exp'
                                                    = 
                                                    [   {   item               => selector_exp,
                                                            source_code_region => (selectorleft, selectorright),
                                                            fixity             => NULL
                                                        }
                                                    ];

                                                app_exp
                                                   =
                                                   selector_exp' @ dot_exp;

                                                expression
                                                   =   
                                                   PRE_FIXITY_EXPRESSION app_exp;

                                                [   {   item               => mark_expression (expression, dot_expleft, selectorright),
                                                        source_code_region => (dot_expleft, selectorright),
                                                        fixity             => NULL
                                                    }
                                                ];
                                            }
                                        )


    | dot_exp POSTFIX_ARROW selector    (  # We defer until  src/lib/compiler/front/typer/main/oop-rewrite-declaration.pkg
                                           # the expansion of this oop code into vanilla code:
                                           #
                                           {   expression
                                                   =
                                                    OBJECT_FIELD_EXPRESSION
                                                     { object =>  PRE_FIXITY_EXPRESSION dot_exp,
                                                       field  =>  selector
                                                     };

                                                [   {   item               => mark_expression (expression, dot_expleft, selectorright),
                                                        source_code_region => (dot_expleft, selectorright),
                                                        fixity             => NULL
                                                    }
                                                ];
                                           }
                                        )


# List comprehension syntax looks like
#
#    [ i*i for i in (1..100) where isprime i ]
#
list_comprehension:
      list_comprehension_result_clause
      list_comprehension_for_clause
      list_comprehension_clauses        ( elc::expand_list_comprehension_syntax
                                            (
                                              ( list_comprehension_for_clause
                                              ! list_comprehension_clauses
                                              )
                                              @
                                              [ list_comprehension_result_clause ]
                                            )
                                        )
#
list_comprehension_result_clause:
      expressionb                       ( elc::LIST_COMPREHENSION_RESULT_CLAUSE (SOURCE_CODE_REGION_FOR_EXPRESSION (expressionb, (expressionbleft, expressionbright )) ))

#
list_comprehension_for_clause:
      FOR_T
      apat
      IN_T
      expressionb                       (   {   my { item => apat, ... } =   apat;
                                                
                                                elc::LIST_COMPREHENSION_FOR_CLAUSE 
                                                  { pattern    => SOURCE_CODE_REGION_FOR_PATTERN    (apat, (apatleft, apatright)),
                                                    expression => SOURCE_CODE_REGION_FOR_EXPRESSION (expressionb, (expressionbleft, expressionbright))
                                                  };
                                            }
                                        )

#
list_comprehension_where_clause:
      WHERE_T
      expressionb                       (   elc::LIST_COMPREHENSION_WHERE_CLAUSE  (SOURCE_CODE_REGION_FOR_EXPRESSION (expressionb, (expressionbleft, expressionbright)) ))

#
list_comprehension_clauses:
      /* empty */                       (  [] )

    | list_comprehension_where_clause
      list_comprehension_clauses        ( list_comprehension_where_clause ! list_comprehension_clauses )
      
    | list_comprehension_for_clause
      list_comprehension_clauses        ( list_comprehension_for_clause   ! list_comprehension_clauses )
      


# 'atomic' expressions:
#
atomic_exp:
      PASSIVEOP_ID                      (VARIABLE_IN_EXPRESSION [make_value_symbol passiveop_id])
    | uppercase_path                    (VARIABLE_IN_EXPRESSION (uppercase_path make_value_symbol))
    | lowercase_path                    (VARIABLE_IN_EXPRESSION (lowercase_path make_value_symbol))
    | operators_path                    (VARIABLE_IN_EXPRESSION (operators_path make_value_symbol))

    | int                               (INT_CONSTANT_IN_EXPRESSION int)
    | UNT                               (UNT_CONSTANT_IN_EXPRESSION unt)
    | FLOAT                             (FLOAT_CONSTANT_IN_EXPRESSION float)
    | STRING                            (STRING_CONSTANT_IN_EXPRESSION string)
    | CHAR                              (CHAR_CONSTANT_IN_EXPRESSION char)
    | PRE_DOT selector                  (mark_expression (RECORD_SELECTOR_EXPRESSION selector, pre_dotleft,  selectorright))
    | HASH INT                          (mark_expression (RECORD_SELECTOR_EXPRESSION (symbol::make_label_symbol (multiword_int::to_string int)), hashleft, intright))
    | LBRACE record_elements RBRACE     (mark_expression (RECORD_IN_EXPRESSION record_elements, lbraceleft, rbraceright))
    | LBRACE RBRACE                     (RECORD_IN_EXPRESSION NIL)
    | LPAREN RPAREN                     (void_expression)
    | LPAREN expression      RPAREN     (expression)
    | LBRACE block_contents RBRACE      (block_contents)
    | LPAREN   expressions_2_n RPAREN   (TUPLE_EXPRESSION    expressions_2_n)
    | LBRACKET expressions_1_n RBRACKET (LIST_EXPRESSION     expressions_1_n)
    | LBRACKET RBRACKET                 (LIST_EXPRESSION     NIL)
    | LBRACKET
      list_comprehension
      RBRACKET                          (list_comprehension)
    | VECTORSTART
      expressions_1_n
      RBRACKET                          (VECTOR_IN_EXPRESSION   expressions_1_n)          
    | VECTORSTART          RBRACKET     (VECTOR_IN_EXPRESSION   NIL) 
    | ANTIQUOTE_ID                      (VARIABLE_IN_EXPRESSION ( [ make_value_symbol antiquote_id ] ) )
    | quote                             (LIST_EXPRESSION quote)

    | FN_T darrow_rules END_T           (mark_expression (FN_EXPRESSION  darrow_rules,  fn_tleft, end_tright))


    | CASE_T
      prefix_exp
      darrow_rules
      ESAC_T                            (    {   expression =  PRE_FIXITY_EXPRESSION prefix_exp;
 
                                                 mark_expression (
                                                    CASE_EXPRESSION { expression, rules => darrow_rules },
                                                    case_tleft, esac_tright
                                                 );
                                             }
                                        )   

    | IF_T
      prefix_exp
      block_contents
      elifs                             (   {   IF_EXPRESSION
                                                    { test_case => PRE_FIXITY_EXPRESSION prefix_exp,
                                                      then_case => mark_expression (block_contents1, block_contents1left, block_contents1right),
                                                      else_case => mark_expression (elifs,           elifsleft,           elifsright          )
                                                    };
                                            }
                                        )

    | BACKTICKS                         (    {
                                                 my (v, f)
                                                     =
                                                     make_value_and_fixity_symbols  (make_raw_symbol "backticks__op");

                                                 fun_item
                                                     =
                                                     { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], backticksleft, backticksright),
                                                       source_code_region => (backticksleft, backticksright),
                                                       fixity             => THE f
                                                     };

                                                 string_item
                                                     =
                                                     { item               => mark_expression (STRING_CONSTANT_IN_EXPRESSION backticks, backticksleft, backticksright),
                                                       source_code_region => (backticksleft, backticksright),
                                                       fixity             => THE f
                                                     };

                                                 PRE_FIXITY_EXPRESSION [ fun_item, string_item ];
                                             }
                                        ) 

    | DOT_BACKTICKS                     (    {
                                                 my (v, f)
                                                     =
                                                     make_value_and_fixity_symbols  (make_raw_symbol "dotbackticks__op");

                                                 fun_item
                                                     =
                                                     { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], dot_backticksleft, dot_backticksright),
                                                       source_code_region => (dot_backticksleft, dot_backticksright),
                                                       fixity             => THE f
                                                     };

                                                 string_item
                                                     =
                                                     { item               => mark_expression (STRING_CONSTANT_IN_EXPRESSION dot_backticks, dot_backticksleft, dot_backticksright),
                                                       source_code_region => (dot_backticksleft, dot_backticksright),
                                                       fixity             => THE f
                                                     };

                                                 PRE_FIXITY_EXPRESSION [ fun_item, string_item ];
                                             }
                                        ) 

    | DOT_QQUOTES                       (    {
                                                 my (v, f)
                                                     =
                                                     make_value_and_fixity_symbols  (make_raw_symbol "dotqquotes__op");

                                                 fun_item
                                                     =
                                                     { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], dot_qquotesleft, dot_qquotesright),
                                                       source_code_region => (dot_qquotesleft, dot_qquotesright),
                                                       fixity             => THE f
                                                     };

                                                 string_item
                                                     =
                                                     { item               => mark_expression (STRING_CONSTANT_IN_EXPRESSION dot_qquotes, dot_qquotesleft, dot_qquotesright),
                                                       source_code_region => (dot_qquotesleft, dot_qquotesright),
                                                       fixity             => THE f
                                                     };

                                                 PRE_FIXITY_EXPRESSION [ fun_item, string_item ];
                                             }
                                        ) 

    | DOT_QUOTES                        (    {
                                                 my (v, f)
                                                     =
                                                     make_value_and_fixity_symbols  (make_raw_symbol "dotquotes__op");

                                                 fun_item
                                                     =
                                                     { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], dot_quotesleft, dot_quotesright),
                                                       source_code_region => (dot_quotesleft, dot_quotesright),
                                                       fixity             => THE f
                                                     };

                                                 string_item
                                                     =
                                                     { item               => mark_expression (STRING_CONSTANT_IN_EXPRESSION dot_quotes, dot_quotesleft, dot_quotesright),
                                                       source_code_region => (dot_quotesleft, dot_quotesright),
                                                       fixity             => THE f
                                                     };

                                                 PRE_FIXITY_EXPRESSION [ fun_item, string_item ];
                                             }
                                        ) 

    | DOT_BROKETS                       (    {
                                                 my (v, f)
                                                     =
                                                     make_value_and_fixity_symbols  (make_raw_symbol "dotbrokets__op");

                                                 fun_item
                                                     =
                                                     { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], dot_broketsleft, dot_broketsright),
                                                       source_code_region => (dot_broketsleft, dot_broketsright),
                                                       fixity             => THE f
                                                     };

                                                 string_item
                                                     =
                                                     { item               => mark_expression (STRING_CONSTANT_IN_EXPRESSION dot_brokets, dot_broketsleft, dot_broketsright),
                                                       source_code_region => (dot_broketsleft, dot_broketsright),
                                                       fixity             => THE f
                                                     };

                                                 PRE_FIXITY_EXPRESSION [ fun_item, string_item ];
                                             }
                                        ) 

    | DOT_BARETS                        (    {
                                                 my (v, f)
                                                     =
                                                     make_value_and_fixity_symbols  (make_raw_symbol "dotbarets__op");

                                                 fun_item
                                                     =
                                                     { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], dot_baretsleft, dot_baretsright),
                                                       source_code_region => (dot_baretsleft, dot_baretsright),
                                                       fixity             => THE f
                                                     };

                                                 string_item
                                                     =
                                                     { item               => mark_expression (STRING_CONSTANT_IN_EXPRESSION dot_barets, dot_baretsleft, dot_baretsright),
                                                       source_code_region => (dot_baretsleft, dot_baretsright),
                                                       fixity             => THE f
                                                     };

                                                 PRE_FIXITY_EXPRESSION [ fun_item, string_item ];
                                             }
                                        ) 

    | DOT_SLASHETS                      (    {
                                                 my (v, f)
                                                     =
                                                     make_value_and_fixity_symbols  (make_raw_symbol "dotslashets__op");

                                                 fun_item
                                                     =
                                                     { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], dot_slashetsleft, dot_slashetsright),
                                                       source_code_region => (dot_slashetsleft, dot_slashetsright),
                                                       fixity             => THE f
                                                     };

                                                 string_item
                                                     =
                                                     { item               => mark_expression (STRING_CONSTANT_IN_EXPRESSION dot_slashets, dot_slashetsleft, dot_slashetsright),
                                                       source_code_region => (dot_slashetsleft, dot_slashetsright),
                                                       fixity             => THE f
                                                     };

                                                 PRE_FIXITY_EXPRESSION [ fun_item, string_item ];
                                             }
                                        ) 

    | DOT_HASHETS                       (    {
                                                 my (v, f)
                                                     =
                                                     make_value_and_fixity_symbols  (make_raw_symbol "dothashets__op");

                                                 fun_item
                                                     =
                                                     { item               => mark_expression (VARIABLE_IN_EXPRESSION [v], dot_hashetsleft, dot_hashetsright),
                                                       source_code_region => (dot_hashetsleft, dot_hashetsright),
                                                       fixity             => THE f
                                                     };

                                                 string_item
                                                     =
                                                     { item               => mark_expression (STRING_CONSTANT_IN_EXPRESSION dot_hashets, dot_hashetsleft, dot_hashetsright),
                                                       source_code_region => (dot_hashetsleft, dot_hashetsright),
                                                       fixity             => THE f
                                                     };

                                                 PRE_FIXITY_EXPRESSION [ fun_item, string_item ];
                                             }
                                        ) 

    | LBRACE_DOT block_contents RBRACE  (make_raw_syntax::thunk
                                             ( lbrace_dotleft,
                                               lbrace_dotright,
                                               block_contents,
                                               block_contentsleft,
                                               block_contentsright,
                                               rbraceright
                                        )     )


elifs:
      FI_T                              (void_expression)

    | ELSE_T
      block_contents
      FI_T                              (block_contents)

    | ELIF_T
      prefix_exp
      block_contents
      elifs                             (   {
                                                IF_EXPRESSION
                                                    { test_case => PRE_FIXITY_EXPRESSION prefix_exp,
                                                      then_case => mark_expression (block_contents, block_contentsleft, block_contentsright),
                                                      else_case => mark_expression (elifs,          elifsleft,          elifsright         )
                                                    };
                                            }
                                        )


block_contents:

      block_declarations_and_expressions        (raw_syntax_junk::block_to_let  block_declarations_and_expressions)     # NB: List is in reverse order


block_declarations_and_expressions:
      declaration_or_expression SEMI   ([ declaration_or_expression ])

    | declaration_or_expression SEMI
      block_declarations_and_expressions         (block_declarations_and_expressions @ [declaration_or_expression])


regular_expressions:
    modified_regular_expression                         ( [ modified_regular_expression ] )
  | modified_regular_expression regular_expressions     (modified_regular_expression ! regular_expressions)

modified_regular_expression:
    regular_expression                  (regular_expression)
  | regular_expression STAR             (REGEX_STAR regular_expression)
  | regular_expression PRE_STAR         (REGEX_STAR regular_expression)


regular_expression:
      STRING                            (REGEX_STRING string)
    | PRE_DOT                           (REGEX_DOT)
    | DOT                               (REGEX_DOT)



declaration_or_expression:

      declaration                                       (declaration)

    # Allow bare expressions
    # too -- fake up a
    #     my _ = ...
    # by hand to make it look like
    # a declaration to later logic:

    | expression                                (expression_to_declaration( expression, expressionleft, expressionright ))


    | STIPULATE_T
      maybe_declarations
      HEREIN_T
      maybe_declarations
      END_T                             (   mark_declaration (
                                                LOCAL_DECLARATIONS (
                                                    mark_declaration (maybe_declarations1, maybe_declarations1left, maybe_declarations1right),
                                                    mark_declaration (maybe_declarations2, maybe_declarations2left, maybe_declarations2right)
                                                ),
                                                stipulate_tleft,
                                                end_tright
                                            )
                                        )









quote:
      BEGINQ ENDQ                       ( [ quote_expression endq ] )
    | BEGINQ ot_list ENDQ               (ot_list @ [ quote_expression endq ] )



ot_list:
      CHUNKL atomic_exp                 ( [ quote_expression chunkl,   antiquote_expression  atomic_exp ] )
    | CHUNKL atomic_exp ot_list         (   quote_expression chunkl ! antiquote_expression atomic_exp ! ot_list)



# The difference between the next two is that
#   expressions_2_n   must have at least two comma-separated elements, whereas
#   expressions_1_n   is allowed to have a single element.

expressions_2_n:
      expression COMMA expressions_2_n  (expression ! expressions_2_n)
    | expression COMMA expression       ( [ expression1, expression2 ] )



expressions_1_n:
      expression                        ( [ expression ] )
    | expression COMMA expressions_1_n  (expression ! expressions_1_n)



pattern:
      pattern AS_T pattern              (layered   (pattern1,   pattern2,   error (pattern1left, pattern2right)))
    | pattern COLON anytype             (TYPE_CONSTRAINT_PATTERN {   pattern,  type_constraint => anytype } )
    | apats                             (PRE_FIXITY_PATTERN apats)



# Atomic pattern sequences:
#
apats:
      postfix_pat                       ( [ postfix_pat ] )
    | postfix_pat apats                 (   postfix_pat ! apats) 



# 2008-01-14 CrT: Does this rule do anything useful? 
#                 I put it in before I realized that
#                 'fun' has its own copy of the 'apats' rule.
postfix_pat:
      apat                              (apat)  

    | apat postfix_op                   (   {   p_op = {   item               => VARIABLE_IN_PATTERN [make_value_symbol postfix_op], 
                                                           source_code_region => (postfix_opleft, postfix_opright),
                                                           fixity             => NULL
                                                       };

                                                pattern = PRE_FIXITY_PATTERN [ p_op, apat ];

                                                {   item               =>  pattern,
                                                    source_code_region =>  (apatleft, postfix_opright),
                                                    fixity             =>  NULL
                                                };
                                            }
                                        )

apat: 

      apat'                             (   {   item               => apat',
                                                source_code_region => (apat'left, apat'right),
                                                fixity             => NULL
                                             }
                                        )

    | LPAREN pattern RPAREN             (   {   item               => pattern,
                                                source_code_region => (lparenleft, rparenright),
                                                fixity             => NULL
                                            }
                                        )

    | value_id                          (   {   my (v, f)
                                                    =
                                                    make_value_and_fixity_symbols value_id;

                                                {   item               => VARIABLE_IN_PATTERN [v], 
                                                    source_code_region => (value_idleft, value_idright),
                                                    fixity             => THE f
                                                };
                                            }
                                        )


    | PASSIVEOP_ID                      (   {   {   item               => VARIABLE_IN_PATTERN [make_value_symbol passiveop_id], 
                                                    source_code_region => (passiveop_idleft, passiveop_idright),
                                                    fixity             => NULL
                                                };
                                            }
                                        )


    | prefix_op                         (   {   {   item               => VARIABLE_IN_PATTERN [make_value_symbol prefix_op], 
                                                    source_code_region => (prefix_opleft, prefix_opright),
                                                    fixity             => NULL
                                                };
                                            }
                                        )


    | LPAREN RPAREN                     (   {   item               => void_pattern,
                                                source_code_region => (lparenleft, rparenright),
                                                fixity             => NULL
                                            }
                                        )

    | LPAREN
          pattern COMMA
          pat_list
      RPAREN                            (   {   item               => TUPLE_PATTERN ( pattern ! pat_list),
                                                source_code_region => (lparenleft, rparenright),
                                                fixity             => NULL
                                            }
                                        )

    | LPAREN
          pattern BAR
          or_pat_list
      RPAREN                            (   {   item               => OR_PATTERN (pattern ! or_pat_list),
                                                source_code_region => (lparenleft, rparenright),
                                                fixity             => NULL
                                            }
                                        )



apat':
      uppercase_path                    (VARIABLE_IN_PATTERN (uppercase_path make_value_symbol))
    | lowercase_path                    (VARIABLE_IN_PATTERN (lowercase_path make_value_symbol))
    | operators_path                    (VARIABLE_IN_PATTERN (operators_path make_value_symbol))

    | int                               (INT_CONSTANT_IN_PATTERN       int)
    | UNT                               (UNT_CONSTANT_IN_PATTERN       unt)
    | STRING                            (STRING_CONSTANT_IN_PATTERN string)
    | CHAR                              (CHAR_CONSTANT_IN_PATTERN     char)
    | WILD                              (WILDCARD_PATTERN)
    | LBRACKET RBRACKET                 (LIST_PATTERN   NIL)
    | LBRACKET pat_list RBRACKET        (LIST_PATTERN   pat_list)
    | VECTORSTART RBRACKET              (VECTOR_PATTERN NIL)
    | VECTORSTART pat_list RBRACKET     (VECTOR_PATTERN pat_list)
    | LBRACE RBRACE                     (void_pattern)
    | LBRACE plabels RBRACE             (   {   my (definition, is_incomplete) = plabels;

                                                SOURCE_CODE_REGION_FOR_PATTERN (
                                                    RECORD_PATTERN {
                                                        definition,
                                                        is_incomplete
                                                    },
                                                    (lbraceleft, rbraceright)
                                                );
                                            }
                                        )



plabel:
      selector DARROW pattern           (   {
                                                (selector, pattern);
                                            }
                                        )
    | lowercase_id                      (make_label_symbol lowercase_id,   VARIABLE_IN_PATTERN [ make_value_symbol lowercase_id ] )

    | lowercase_id AS_T pattern         (   make_label_symbol lowercase_id, 
                                            AS_PATTERN {
                                                variable_pattern   => VARIABLE_IN_PATTERN [make_value_symbol lowercase_id], 
                                                expression_pattern => pattern
                                            }
                                        )
    | lowercase_id COLON anytype        (   make_label_symbol lowercase_id,
                                            TYPE_CONSTRAINT_PATTERN {
                                                pattern        => VARIABLE_IN_PATTERN [ make_value_symbol lowercase_id ],
                                                type_constraint => anytype
                                            }
                                        )

    | anytype lowercase_id              (   make_label_symbol lowercase_id,
                                            TYPE_CONSTRAINT_PATTERN {
                                                pattern        => VARIABLE_IN_PATTERN [ make_value_symbol lowercase_id ],
                                                type_constraint => anytype
                                            }
                                        )

    | lowercase_id
      COLON
      anytype
      AS_T
      pattern                           (   make_label_symbol lowercase_id,
                                            AS_PATTERN {
                                                variable_pattern => TYPE_CONSTRAINT_PATTERN {
                                                                      pattern        => VARIABLE_IN_PATTERN [ make_value_symbol lowercase_id ],
                                                                      type_constraint => anytype
                                                                   },
                                                expression_pattern => pattern
                                            }
                                        )




# Pattern labels:
#
plabels:

      plabel                            ([plabel], FALSE)
    | DOTDOTDOT                         (NIL, TRUE)

    | plabel COMMA plabels              (   { my (a, (b, is_incomplete))   =   (plabel, plabels);

                                                 (a ! b, is_incomplete);
                                            }
                                        )



pat_list:
      pattern                           ( [ pattern ] )
    | pattern COMMA pat_list            (   pattern ! pat_list)



or_pat_list:
      pattern                           ( [ pattern ] )
    | pattern BAR or_pat_list           (   pattern ! or_pat_list)



# Named values:
#
vb:   vb ALSO_T vb                              (vb1 @ vb2)

    | LAZY_T
      pattern EQUAL_OP expression       (   [   SOURCE_CODE_REGION_FOR_NAMED_VALUE (
                                                    NAMED_VALUE {
                                                        expression,
                                                        pattern,
                                                        is_lazy    => TRUE
                                                    },
                                                    (patternleft, expressionright)
                                                )
                                            ]
                                        )
    | pattern EQUAL_OP expression       (   [   SOURCE_CODE_REGION_FOR_NAMED_VALUE (
                                                    NAMED_VALUE {
                                                        expression,
                                                        pattern,
                                                        is_lazy    => FALSE
                                                    },
                                                    (patternleft, expressionright)
                                                )
                                            ]
                                        )


# OOP named fields.     Syntactically we pattern these on
# named values (above), but for now we don't allow
# initializers or LAZY_T qualifiers, so they reduce
# to just one typed symbol per declaration:
#
fields:
      fields ALSO_T fields              (fields1 @ fields2)

    | anytype lowercase_id              (   [   SOURCE_CODE_REGION_FOR_NAMED_FIELD (
                                                    NAMED_FIELD
                                                      { name => make_label_symbol lowercase_id,
                                                        type => anytype,
                                                        init => NULL
                                                      },
                                                    (lowercase_idleft, anytyperight)
                                                )
                                            ]
                                        )

    | anytype
      lowercase_id
      EQUAL_OP
      expression                        (   [   SOURCE_CODE_REGION_FOR_NAMED_FIELD (
                                                    NAMED_FIELD
                                                      { name => make_label_symbol lowercase_id,
                                                        type => anytype,
                                                        init => THE expression
                                                      },
                                                    (lowercase_idleft, anytyperight)
                                                )
                                            ]
                                        )



constraint:
                                        (NULL)
    | COLON anytype                     (THE anytype)



# Recursive named values:
#
rvb:  rvb ALSO_T rvb                    (rvb1 @ rvb2)

    | lvalue_or_bar
      constraint
      EQUAL_OP
      expression                        (   {   my (variable_symbol, fixity) = make_value_and_fixity_symbols lvalue_or_bar;

                                                [   SOURCE_CODE_REGION_FOR_RECURSIVELY_NAMED_VALUE (
                                                        NAMED_RECURSIVE_VALUE {
                                                            variable_symbol,
                                                            fixity          => THE (fixity, (lvalue_or_barleft, lvalue_or_barright)),
                                                            null_or_type    => constraint,
                                                            expression,
                                                            is_lazy         => FALSE
                                                        },
                                                        (lvalue_or_barleft, expressionright)
                                                    )
                                                ];
                                            }
                                        )

    | PASSIVEOP_ID
      constraint
      EQUAL_OP
      expression                        (   {   [   SOURCE_CODE_REGION_FOR_RECURSIVELY_NAMED_VALUE (
                                                        NAMED_RECURSIVE_VALUE {
                                                            variable_symbol => make_value_symbol passiveop_id,
                                                            fixity          => NULL,
                                                            null_or_type    => constraint,
                                                            expression,
                                                            is_lazy         => FALSE
                                                        },
                                                        (passiveop_idleft, expressionright)
                                                    )
                                                ];
                                            }
                                        )

    | LAZY_T lvalue_or_bar constraint
          EQUAL_OP expression           (   {   (make_value_and_fixity_symbols lvalue_or_bar)
                                                    ->
                                                    (variable_symbol, fixity);

                                                [   SOURCE_CODE_REGION_FOR_RECURSIVELY_NAMED_VALUE (
                                                        NAMED_RECURSIVE_VALUE {
                                                            variable_symbol,
                                                            fixity          => THE (fixity, (lvalue_or_barleft, lvalue_or_barright)),
                                                            null_or_type    => constraint,
                                                            expression,
                                                            is_lazy         => TRUE
                                                        },
                                                        (lvalue_or_barleft, expressionright)
                                                    )
                                                ];
                                            }
                                        )

    | LAZY_T PASSIVEOP_ID constraint
          EQUAL_OP expression           (   {   [   SOURCE_CODE_REGION_FOR_RECURSIVELY_NAMED_VALUE (
                                                        NAMED_RECURSIVE_VALUE {
                                                            variable_symbol => make_value_symbol passiveop_id,
                                                            fixity          => NULL,
                                                            null_or_type    => constraint,
                                                            expression,
                                                            is_lazy         => TRUE
                                                        },
                                                        (passiveop_idleft, expressionright)
                                                    )
                                                ];
                                            }
                                        )



# Named functions:
#
fun_clauses:
      eq_clause                                 ([eq_clause])
    | darrow_clause SEMI darrow_clauses END_T   (darrow_clause ! darrow_clauses)

darrow_clauses:
      darrow_clause SEMI                        ([darrow_clause])
    | darrow_clause SEMI darrow_clauses         (darrow_clause ! darrow_clauses)



maybe_lazy:                                     (FALSE)
    | LAZY_T                                    (TRUE)

# The next three rulesets are virtually identical, but
# we need the duplication to remember what value to
# assign to 'kind': PLAIN_FUN, MESSAGE_FUN or METHOD_FUN:
#
fun_decls:
      maybe_lazy         fun_clauses                                      ( [ SOURCE_CODE_REGION_FOR_NAMED_FUNCTION (NAMED_FUNCTION { pattern_clauses => fun_clauses, is_lazy => maybe_lazy, kind =>   PLAIN_FUN, null_or_type => NULL        }, (fun_clausesleft, fun_clausesright)) ]              )
    | maybe_lazy         fun_clauses ALSO_T           FUN_T     fun_decls (   SOURCE_CODE_REGION_FOR_NAMED_FUNCTION (NAMED_FUNCTION { pattern_clauses => fun_clauses, is_lazy => maybe_lazy, kind =>   PLAIN_FUN, null_or_type => NULL        }, (fun_clausesleft, fun_clausesright)) !     fun_decls)
    | maybe_lazy         fun_clauses ALSO_T METHOD_T  FUN_T  method_decls (   SOURCE_CODE_REGION_FOR_NAMED_FUNCTION (NAMED_FUNCTION { pattern_clauses => fun_clauses, is_lazy => maybe_lazy, kind =>   PLAIN_FUN, null_or_type => NULL        }, (fun_clausesleft, fun_clausesright)) !  method_decls)
    | maybe_lazy         fun_clauses ALSO_T MESSAGE_T FUN_T message_decls (   SOURCE_CODE_REGION_FOR_NAMED_FUNCTION (NAMED_FUNCTION { pattern_clauses => fun_clauses, is_lazy => maybe_lazy, kind =>   PLAIN_FUN, null_or_type => NULL        }, (fun_clausesleft, fun_clausesright)) ! message_decls)


method_decls:
      maybe_lazy         fun_clauses                                      ( [ SOURCE_CODE_REGION_FOR_NAMED_FUNCTION (NAMED_FUNCTION { pattern_clauses => fun_clauses, is_lazy => maybe_lazy, kind =>  METHOD_FUN, null_or_type => NULL        }, (fun_clausesleft, fun_clausesright)) ]              )
    | maybe_lazy         fun_clauses ALSO_T           FUN_T     fun_decls (   SOURCE_CODE_REGION_FOR_NAMED_FUNCTION (NAMED_FUNCTION { pattern_clauses => fun_clauses, is_lazy => maybe_lazy, kind =>  METHOD_FUN, null_or_type => NULL        }, (fun_clausesleft, fun_clausesright)) !     fun_decls)
    | maybe_lazy         fun_clauses ALSO_T METHOD_T  FUN_T  method_decls (   SOURCE_CODE_REGION_FOR_NAMED_FUNCTION (NAMED_FUNCTION { pattern_clauses => fun_clauses, is_lazy => maybe_lazy, kind =>  METHOD_FUN, null_or_type => NULL        }, (fun_clausesleft, fun_clausesright)) !  method_decls)
    | maybe_lazy         fun_clauses ALSO_T MESSAGE_T FUN_T message_decls (   SOURCE_CODE_REGION_FOR_NAMED_FUNCTION (NAMED_FUNCTION { pattern_clauses => fun_clauses, is_lazy => maybe_lazy, kind =>  METHOD_FUN, null_or_type => NULL        }, (fun_clausesleft, fun_clausesright)) ! message_decls)


message_decls:
      maybe_lazy anytype fun_clauses                                      ( [ SOURCE_CODE_REGION_FOR_NAMED_FUNCTION (NAMED_FUNCTION { pattern_clauses => fun_clauses, is_lazy => maybe_lazy, kind => MESSAGE_FUN, null_or_type => THE anytype }, (fun_clausesleft, fun_clausesright)) ]              )
    | maybe_lazy anytype fun_clauses ALSO_T           FUN_T     fun_decls (   SOURCE_CODE_REGION_FOR_NAMED_FUNCTION (NAMED_FUNCTION { pattern_clauses => fun_clauses, is_lazy => maybe_lazy, kind => MESSAGE_FUN, null_or_type => THE anytype }, (fun_clausesleft, fun_clausesright)) !     fun_decls)
    | maybe_lazy anytype fun_clauses ALSO_T METHOD_T  FUN_T  method_decls (   SOURCE_CODE_REGION_FOR_NAMED_FUNCTION (NAMED_FUNCTION { pattern_clauses => fun_clauses, is_lazy => maybe_lazy, kind => MESSAGE_FUN, null_or_type => THE anytype }, (fun_clausesleft, fun_clausesright)) !  method_decls)
    | maybe_lazy anytype fun_clauses ALSO_T MESSAGE_T FUN_T message_decls (   SOURCE_CODE_REGION_FOR_NAMED_FUNCTION (NAMED_FUNCTION { pattern_clauses => fun_clauses, is_lazy => maybe_lazy, kind => MESSAGE_FUN, null_or_type => THE anytype }, (fun_clausesleft, fun_clausesright)) ! message_decls)


# Fun def clauses:
#
eq_clause:                              # Used only in fun defs, never \\/case/except
      fun_apats constraint
          EQUAL_OP expression           (   PATTERN_CLAUSE {
                                                patterns    => fun_apats,
                                                result_type => constraint,
                                                expression  => mark_expression (expression, expressionleft, expressionright)
                                            }
                                        )

darrow_clause:                          # Used only in fun defs, never \\/case/except
      fun_apats constraint
          DARROW expression             (   PATTERN_CLAUSE {
                                                patterns    => fun_apats,
                                                result_type => constraint,
                                                expression  => mark_expression (expression, expressionleft, expressionright)
                                            }
                                        )


# Toplevel function definition atomic pattern sequences.
# The only difference between this and the vanilla "apats"
# rule is that we allow '|' (bar) in the sequence:
#
fun_apats:
      fun_apat                          ( [ fun_apat ] )
    | fun_apat fun_apats                (   fun_apat ! fun_apats) 

    | fun_apats postfix_op              (   {   p_op = {   item               => VARIABLE_IN_PATTERN [make_value_symbol postfix_op], 
                                                           source_code_region => (postfix_opleft, postfix_opright),
                                                           fixity             => NULL
                                                       };

                                                p_op ! fun_apats;
                                            }
                                        )

    # |a|
    #
    | PRE_BAR fun_apats POST_BAR        (   {   p_op = {   item               => VARIABLE_IN_PATTERN [ make_value_symbol' "|_|" ], 
                                                           source_code_region => (pre_barleft, post_barright),
                                                           fixity             => NULL
                                                       };

                                                p_op ! fun_apats;
                                            }
                                        )
    # /a/
    #
    | PRE_SLASH fun_apats POST_SLASH    (   {   p_op = {   item               => VARIABLE_IN_PATTERN [ make_value_symbol' "/_/" ], 
                                                           source_code_region => (pre_slashleft, post_slashright),
                                                           fixity             => NULL
                                                       };

                                                p_op ! fun_apats;
                                            }
                                        )

    # <a>
    #
    | PRE_LANGLE fun_apats POST_RANGLE  (   {   p_op = {   item               => VARIABLE_IN_PATTERN [ make_value_symbol' "<_>" ], 
                                                           source_code_region => (pre_langleleft, post_rangleright),
                                                           fixity             => NULL
                                                       };

                                                p_op ! fun_apats;
                                            }
                                        )

    # <a|
    #
    | PRE_LANGLE fun_apats POST_BAR     (   {   p_op = {   item               => VARIABLE_IN_PATTERN [ make_value_symbol' "< |" ], 
                                                           source_code_region => (pre_langleleft, post_barright),
                                                           fixity             => NULL
                                                       };

                                                p_op ! fun_apats;
                                            }
                                        )

    # |a>
    #
    | PRE_BAR fun_apats POST_RANGLE     (   {   p_op = {   item               => VARIABLE_IN_PATTERN [ make_value_symbol' "| >" ], 
                                                           source_code_region => (pre_barleft, post_rangleright),
                                                           fixity             => NULL
                                                       };

                                                p_op ! fun_apats;
                                            }
                                        )

    # {a}
    #
    | PRE_LBRACE fun_apats POST_RBRACE  (   {   p_op = {   item               => VARIABLE_IN_PATTERN [ make_value_symbol' "{_}" ], 
                                                           source_code_region => (pre_lbraceleft, post_rbraceright),
                                                           fixity             => NULL
                                                       };

                                                p_op ! fun_apats;
                                            }
                                        )

    # a[b]
    #
    | apat
      POST_LBRACKET
      pattern
      RBRACKET                         (   {   p_op = {   item                => VARIABLE_IN_PATTERN [ make_value_symbol' "_[]" ], 
                                                           source_code_region => (apatleft, rbracketright),
                                                           fixity             => NULL
                                                       };


                                                tuple = {   item               => TUPLE_PATTERN [ PRE_FIXITY_PATTERN [ apat ], pattern ],
                                                            source_code_region => (apatleft, rbracketright),
                                                            fixity             => NULL
                                                        };

                                                [ p_op, tuple ];
                                            }
                                        )




    # a[b,c]
    #
    | apat
      POST_LBRACKET
          pattern COMMA
          pat_list
      RBRACKET                         (   {   p_op = {   item                => VARIABLE_IN_PATTERN [ make_value_symbol' "_[]" ], 
                                                           source_code_region => (apatleft, rbracketright),
                                                           fixity             => NULL
                                                       };

                                                pat   = TUPLE_PATTERN ( pattern ! pat_list);

                                                tuple = {   item               => TUPLE_PATTERN [ PRE_FIXITY_PATTERN [ apat ], pat ],
                                                            source_code_region => (apatleft, rbracketright),
                                                            fixity             => NULL
                                                        };

                                                [ p_op, tuple ];
                                            }
                                        )




fun_apat:
      apat                              (apat)

    | bar                               (   {   my (v, f)
                                                    =
                                                    make_value_and_fixity_symbols bar;

                                                {   item               => VARIABLE_IN_PATTERN [v], 
                                                    source_code_region => (barleft, barright),
                                                    fixity             => THE f
                                                };
                                            }
                                        )




named_types:
      named_types
      ALSO_T
      named_types                       (named_types1 @ named_types2)

    | MIXEDCASE_ID typevars
      EQUAL_OP anytype                  (  [   SOURCE_CODE_REGION_FOR_NAMED_TYPE (
                                                    NAMED_TYPE {
                                                        typevars,
                                                        name_symbol => make_type_symbol mixedcase_id,
                                                        definition  => anytype
                                                    },
                                                    (anytypeleft, anytyperight)
                                                )
                                            ]
                                        )

# NB: Apparently union types can be mutually recursive
#     but not other (e.g. record) types.
# For example  
#     This = THIS { this: This, that: That } also
#     That = THAT { this: This, that: That };
# is allowed, but
#     This =      { this: This, that: That } also
#     That =      { this: This, that: That };
# is verboten (except after 'withtype', and even
# there they are not mutually recursive).
# I presume there are solid core semantic
# reasons for this...? -- 2010-09-29 CrT



typevars:
      LPAREN tyvar_pc RPAREN            (tyvar_pc)
    |                                   (NIL)

    | TYVAR                             (   [   SOURCE_CODE_REGION_FOR_TYPEVAR (
                                                    TYPEVAR (make_typevar_symbol tyvar),
                                                    (tyvarleft, tyvarright)
                                                )
                                            ]
                                        )



# Parenthesized, comma-separated
# type variable sequences:
#
tyvar_pc:
      TYVAR                             (   [   SOURCE_CODE_REGION_FOR_TYPEVAR (
                                                    TYPEVAR (make_typevar_symbol tyvar),
                                                    (tyvarleft, tyvarright)
                                                )
                                            ]
                                        )

    | TYVAR COMMA tyvar_pc              (   SOURCE_CODE_REGION_FOR_TYPEVAR (
                                                TYPEVAR (make_typevar_symbol tyvar),
                                                (tyvarleft, tyvarright)
                                            )
                                            ! tyvar_pc
                                        )



# Named enums:
#
sumtypes:
      sumtypes
      ALSO_T
      sumtypes                          (sumtypes1 @ sumtypes2)

    | MIXEDCASE_ID typevars
          EQUAL_OP constructors         (   [   raw::SUM_TYPE {
                                                    name_symbol      => make_type_symbol mixedcase_id,
                                                    typevars,
                                                    right_hand_side  => (VALCONS constructors),
                                                    is_lazy          => FALSE
                                                }
                                            ]
                                        )

    | MIXEDCASE_ID typevars
          EQEQ_OP type                  (   [   raw::SUM_TYPE {
                                                    name_symbol      => make_type_symbol mixedcase_id,
                                                    typevars,
                                                    right_hand_side  => (REPLICAS type),
                                                    is_lazy          => FALSE
                                                }
                                            ]
                                        )

    | LAZY_T MIXEDCASE_ID typevars
          EQUAL_OP constructors         (   [   raw::SUM_TYPE {
                                                    name_symbol      => make_type_symbol mixedcase_id,
                                                    typevars,
                                                    right_hand_side  => (VALCONS constructors),
                                                    is_lazy          => TRUE
                                                }
                                            ]
                                        )


    | LAZY_T MIXEDCASE_ID typevars
          EQEQ_OP type                  (   [   raw::SUM_TYPE {
                                                    name_symbol      => make_type_symbol mixedcase_id,
                                                    typevars,
                                                    right_hand_side  => (REPLICAS type),
                                                    is_lazy          => TRUE
                                                }
                                            ]
                                        )


# Union type constructors:
#
constructors:
      constructor                       ([constructor])
    | constructor BAR constructors      (constructor ! constructors)



constructor:
      UPPERCASE_ID                      (make_value_symbol uppercase_id,   NULL   )
    | UPPERCASE_ID      anytype         (make_value_symbol uppercase_id,   THE anytype)


# Named exceptions: 
#
eb:   eb ALSO_T eb                              (eb1 @ eb2)

    | UPPERCASE_ID                      (   [   NAMED_EXCEPTION {
                                                    exception_symbol => (make_value_symbol uppercase_id),
                                                    exception_type   => NULL
                                                }
                                            ]
                                        )

    | UPPERCASE_ID      anytype (   [   NAMED_EXCEPTION {
                                                    exception_symbol => (make_value_symbol uppercase_id),
                                                    exception_type   => THE anytype
                                                }
                                            ]
                                        )

    | UPPERCASE_ID
      EQUAL_OP
      uppercase                         (   [   DUPLICATE_NAMED_EXCEPTION {
                                                    exception_symbol => make_value_symbol uppercase_id,
                                                    equal_to         => uppercase make_value_symbol
                                                }
                                            ]
                                        )


# Qualified identifier sequences
# in 'include' statements:
#
package_in_import:
      lowercase                                 ( [ lowercase make_package_symbol ] )
#    | lowercase package_in_import              (   lowercase make_package_symbol ! package_in_import)


fixity:
      INFIX_T  MY_T                     (infixleft 0)
    | INFIX_T  MY_T int                 (infixleft  (check_fixity (multiword_int::to_int int, error (intleft, intright))))
    | INFIXR_T MY_T                     (infixright 0)
    | INFIXR_T MY_T int                 (infixright (check_fixity (multiword_int::to_int int, error (intleft, intright))))
    | NONFIX_T MY_T                     (NONFIX)



# 'stipulate' declarations:
#
declaration:
      MY_T vb                           (VALUE_DECLARATIONS (vb, NIL))

    # "Reverse assignment", e.g.
    #
    #  foo -> (a, b);
    #
    | dot_exp
      ARROW
      pattern                           (VALUE_DECLARATIONS
                                            ( [   SOURCE_CODE_REGION_FOR_NAMED_VALUE (
                                                      NAMED_VALUE {
                                                          expression => (PRE_FIXITY_EXPRESSION (dot_exp)),
                                                          pattern,
                                                          is_lazy    => FALSE
                                                      },
                                                      (dot_expleft, patternright)
                                                  )
                                              ],
                                              NIL 
                                            )
                                        )
                                        #
                                        # I'd love to change 'dot_exp' to 'app_exp' above, so as to be able to write
                                        #     f x -> { this, that };
                                        # in place of
                                        #     (f x) -> { this, that };
                                        # Unfortunately none of the obvious tries work.
                                        # I suspect the parser is being forced to make an early decision as to whether to
                                        # reduce an initial lower-case identifier as an expression component or as a pattern
                                        # component. Rewriting the grammar to keep them as vanilla lower-case identifiers
                                        # until more context has been seen might do the trick, but doesn't look easy, or perhaps even possible.
                                        #                  -- 2011-01-10 CrT


    # OOP support.  Syntactically we treat
    # 'field' declarations much like local
    # variable declarations, except without
    # initializers:
    #
    | FIELD_T MY_T      fields          (FIELD_DECLARATIONS (fields, NIL))

    | RECURSIVE_T  MY_T   rvb           (RECURSIVE_VALUE_DECLARATIONS (rvb, NIL))

    # At this syntactic level, a method/message
    # declaration is identical to a function except
    # for being flagged with a   'method'/'message'
    # modifier before the 'fun':
    #
    |           FUN_T     fun_decls     (FUNCTION_DECLARATIONS (    fun_decls, NIL))
    |  METHOD_T FUN_T  method_decls     (FUNCTION_DECLARATIONS ( method_decls, NIL))
    | MESSAGE_T FUN_T message_decls     (FUNCTION_DECLARATIONS (message_decls, NIL))

    | named_types                       (TYPE_DECLARATIONS     named_types)
    | sumtypes                          (SUMTYPE_DECLARATIONS { sumtypes,
                                                                with_types => []
                                                              }
                                        )

    | sumtypes
      WITHTYPE_T
      named_types                       (SUMTYPE_DECLARATIONS { sumtypes,
                                                                   with_types => named_types
                                                                 }
                                        )

    | EXCEPTION_T eb                    (EXCEPTION_DECLARATIONS eb)

    | INCLUDE_T
      PACKAGE_T
      package_in_import                 (INCLUDE_DECLARATIONS package_in_import)

    | fixity ops                        (FIXITY_DECLARATIONS { fixity, ops } )

    | OVERLOADED_T
      MY_T
      lvalue_or_bar
      COLON
      anytype
      EQUAL_OP
      LPAREN
      overloaded_expressions
      RPAREN                            (OVERLOADED_VARIABLE_DECLARATION (make_value_symbol lvalue_or_bar, anytype, overloaded_expressions, FALSE))

    | OVERLOADED_T
      MY_T
      lvalue_or_bar
      COLON
      anytype
      PLUS_EQ                           # This is only difference from previous rule.
      LPAREN
      overloaded_expressions
      RPAREN                            (OVERLOADED_VARIABLE_DECLARATION (make_value_symbol lvalue_or_bar, anytype, overloaded_expressions, TRUE))

    | OVERLOADED_T
      MY_T
      PASSIVEOP_ID
      COLON
      anytype
      EQUAL_OP
      LPAREN
      overloaded_expressions
      RPAREN                            (OVERLOADED_VARIABLE_DECLARATION (make_value_symbol passiveop_id, anytype, overloaded_expressions, FALSE))

    | OVERLOADED_T
      MY_T
      PASSIVEOP_ID
      COLON
      anytype
      PLUS_EQ                           # This is only difference from previous rule.
      LPAREN
      overloaded_expressions
      RPAREN                            (OVERLOADED_VARIABLE_DECLARATION (make_value_symbol passiveop_id, anytype, overloaded_expressions, TRUE))

# Don't require leading 'my' on simple variable patterns:

    | lvalue_or_bar EQUAL_OP expression (   mark_declaration (
                                                VALUE_DECLARATIONS (
                                                    [   NAMED_VALUE {
                                                            expression,
                                                            pattern    => VARIABLE_IN_PATTERN [make_value_symbol lvalue_or_bar],
                                                            is_lazy    => FALSE
                                                        }
                                                    ],
                                                    NIL
                                                ),
                                                lvalue_or_barleft,
                                                expressionright
                                            )
                                        )

    | PASSIVEOP_ID EQUAL_OP expression  (   mark_declaration (
                                                VALUE_DECLARATIONS (
                                                    [   NAMED_VALUE {
                                                            expression,
                                                            pattern    => VARIABLE_IN_PATTERN [make_value_symbol passiveop_id],
                                                            is_lazy    => FALSE
                                                        }
                                                    ],
                                                    NIL
                                                ),
                                                passiveop_idleft,
                                                expressionright
                                            )
                                        )

    | PRE_PLUSPLUS  lowercase_id        (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                plus       =  raw_symbol (plus_hash,    plus_string);

                                                plus_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  plus;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], pre_plusplusleft, pre_plusplusright),
                                                                          source_code_region => (pre_plusplusleft, pre_plusplusright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                one        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (INT_CONSTANT_IN_EXPRESSION 1, lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                expression =  PRE_FIXITY_EXPRESSION [ var, plus_op, one ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    pre_plusplusleft,
                                                    lowercase_idright
                                                );
                                            }
                                        )


    | PRE_DASHDASH  lowercase_id        (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                dash       =  raw_symbol (dash_hash,    dash_string);

                                                dash_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  dash;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], pre_dashdashleft, pre_dashdashright),
                                                                          source_code_region => (pre_dashdashleft, pre_dashdashright),
                                                                          fixity             => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity             => THE f
                                                                      };
                                                                  };

                                                one        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (INT_CONSTANT_IN_EXPRESSION 1, lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity             => THE f
                                                                      };
                                                                  };

                                                expression =  PRE_FIXITY_EXPRESSION [ var, dash_op, one ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    pre_dashdashleft,
                                                    lowercase_idright
                                                );
                                            }
                                        )


    # It would be nice to factor the common stuff
    # in the following into a function, but all the
    # left/right stuff would make it ugly :(
    #
    | lowercase_id  PLUS_EQ  expression (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                plus       =  raw_symbol (plus_hash,    plus_string);

                                                plus_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  plus;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], plus_eqleft, plus_eqright),
                                                                          source_code_region => (plus_eqleft, plus_eqright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                atomic_exp =      {   item               => mark_expression (expression, expressionleft, expressionright),
                                                                      source_code_region => (expressionleft, expressionright),
                                                                      fixity             => NULL
                                                                  };



                                                expression =  PRE_FIXITY_EXPRESSION [ var, plus_op, atomic_exp ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    lowercase_idleft,
                                                    expressionright
                                                );
                                            }
                                        )


    | lowercase_id  STAR_EQ  expression (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                star       =  raw_symbol (star_hash,    star_string);

                                                star_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  star;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], star_eqleft, star_eqright),
                                                                          source_code_region => (star_eqleft, star_eqright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                atomic_exp =      {   item               => mark_expression (expression, expressionleft, expressionright),
                                                                      source_code_region => (expressionleft, expressionright),
                                                                      fixity             => NULL
                                                                  };



                                                expression =  PRE_FIXITY_EXPRESSION [ var, star_op, atomic_exp ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    lowercase_idleft,
                                                    expressionright
                                                );
                                            }
                                        )

    | lowercase_id
      DASH_EQ
      expression                        (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                dash       =  raw_symbol (dash_hash,    dash_string);

                                                dash_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  dash;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], dash_eqleft, dash_eqright),
                                                                          source_code_region => (dash_eqleft, dash_eqright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                atomic_exp =      {   item               => mark_expression (expression, expressionleft, expressionright),
                                                                      source_code_region => (expressionleft, expressionright),
                                                                      fixity             => NULL
                                                                  };



                                                expression =  PRE_FIXITY_EXPRESSION [ var, dash_op, atomic_exp ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    lowercase_idleft,
                                                    expressionright
                                                );
                                            }
                                        )


    | lowercase_id
      SLASH_EQ
      expression                        (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                slash       =  raw_symbol (slash_hash,    slash_string);

                                                slash_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  slash;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], slash_eqleft, slash_eqright),
                                                                          source_code_region => (slash_eqleft, slash_eqright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                atomic_exp =      {   item               => mark_expression (expression, expressionleft, expressionright),
                                                                      source_code_region => (expressionleft, expressionright),
                                                                      fixity             => NULL
                                                                  };



                                                expression =  PRE_FIXITY_EXPRESSION [ var, slash_op, atomic_exp ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    lowercase_idleft,
                                                    expressionright
                                                );
                                            }
                                        )



    | lowercase_id
      PERCNT_EQ
      expression                        (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                percnt       =  raw_symbol (percnt_hash,    percnt_string);

                                                percnt_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  percnt;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], percnt_eqleft, percnt_eqright),
                                                                          source_code_region => (percnt_eqleft, percnt_eqright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                atomic_exp =      {   item               => mark_expression (expression, expressionleft, expressionright),
                                                                      source_code_region => (expressionleft, expressionright),
                                                                      fixity             => NULL
                                                                  };



                                                expression =  PRE_FIXITY_EXPRESSION [ var, percnt_op, atomic_exp ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    lowercase_idleft,
                                                    expressionright
                                                );
                                            }
                                        )


    | lowercase_id
      BUCK_EQ
      expression                        (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                buck       =  raw_symbol (buck_hash,    buck_string);

                                                buck_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  buck;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], buck_eqleft, buck_eqright),
                                                                          source_code_region => (buck_eqleft, buck_eqright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                atomic_exp =      {   item               => mark_expression (expression, expressionleft, expressionright),
                                                                      source_code_region => (expressionleft, expressionright),
                                                                      fixity             => NULL
                                                                  };



                                                expression =  PRE_FIXITY_EXPRESSION [ var, buck_op, atomic_exp ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    lowercase_idleft,
                                                    expressionright
                                                );
                                            }
                                        )



    | lowercase_id
      BANG_EQ
      expression                        (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                bang       =  raw_symbol (bang_hash,    bang_string);

                                                bang_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  bang;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], bang_eqleft, bang_eqright),
                                                                          source_code_region => (bang_eqleft, bang_eqright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                atomic_exp =      {   item               => mark_expression (expression, expressionleft, expressionright),
                                                                      source_code_region => (expressionleft, expressionright),
                                                                      fixity             => NULL
                                                                  };



                                                expression =  PRE_FIXITY_EXPRESSION [ var, bang_op, atomic_exp ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    lowercase_idleft,
                                                    expressionright
                                                );
                                            }
                                        )



    | lowercase_id
      BACK_EQ
      expression                        (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                back       =  raw_symbol (back_hash,    back_string);

                                                back_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  back;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], back_eqleft, back_eqright),
                                                                          source_code_region => (back_eqleft, back_eqright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                atomic_exp =      {   item               => mark_expression (expression, expressionleft, expressionright),
                                                                      source_code_region => (expressionleft, expressionright),
                                                                      fixity             => NULL
                                                                  };



                                                expression =  PRE_FIXITY_EXPRESSION [ var, back_op, atomic_exp ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    lowercase_idleft,
                                                    expressionright
                                                );
                                            }
                                        )


    | lowercase_id
      AMPER_EQ
      expression                        (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                amper       =  raw_symbol (amper_hash,    amper_string);

                                                amper_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  amper;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], amper_eqleft, amper_eqright),
                                                                          source_code_region => (amper_eqleft, amper_eqright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                atomic_exp =      {   item               => mark_expression (expression, expressionleft, expressionright),
                                                                      source_code_region => (expressionleft, expressionright),
                                                                      fixity             => NULL
                                                                  };



                                                expression =  PRE_FIXITY_EXPRESSION [ var, amper_op, atomic_exp ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    lowercase_idleft,
                                                    expressionright
                                                );
                                            }
                                        )



    | lowercase_id
      ATSIGN_EQ
      expression                        (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                atsign       =  raw_symbol (atsign_hash,    atsign_string);

                                                atsign_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  atsign;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], atsign_eqleft, atsign_eqright),
                                                                          source_code_region => (atsign_eqleft, atsign_eqright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                atomic_exp =      {   item               => mark_expression (expression, expressionleft, expressionright),
                                                                      source_code_region => (expressionleft, expressionright),
                                                                      fixity             => NULL
                                                                  };



                                                expression =  PRE_FIXITY_EXPRESSION [ var, atsign_op, atomic_exp ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    lowercase_idleft,
                                                    expressionright
                                                );
                                            }
                                        )


    | lowercase_id
      QMARK_EQ
      expression                        (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                qmark       =  raw_symbol (qmark_hash,    qmark_string);

                                                qmark_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  qmark;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], qmark_eqleft, qmark_eqright),
                                                                          source_code_region => (qmark_eqleft, qmark_eqright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                atomic_exp =      {   item               => mark_expression (expression, expressionleft, expressionright),
                                                                      source_code_region => (expressionleft, expressionright),
                                                                      fixity             => NULL
                                                                  };



                                                expression =  PRE_FIXITY_EXPRESSION [ var, qmark_op, atomic_exp ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    lowercase_idleft,
                                                    expressionright
                                                );
                                            }
                                        )


    | lowercase_id
      TILDA_EQ
      expression                        (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                tilda       =  raw_symbol (tilda_hash,    tilda_string);

                                                tilda_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  tilda;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], tilda_eqleft, tilda_eqright),
                                                                          source_code_region => (tilda_eqleft, tilda_eqright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                atomic_exp =      {   item               => mark_expression (expression, expressionleft, expressionright),
                                                                      source_code_region => (expressionleft, expressionright),
                                                                      fixity             => NULL
                                                                  };



                                                expression =  PRE_FIXITY_EXPRESSION [ var, tilda_op, atomic_exp ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    lowercase_idleft,
                                                    expressionright
                                                );
                                            }
                                        )




    | lowercase_id
      DOT_EQ
      expression                        (   {   pattern    =  VARIABLE_IN_PATTERN [make_value_symbol lowercase_id];

                                                dot        =  raw_symbol (weakdot_hash,    weakdot_string);

                                                dot_op    =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  dot;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], dot_eqleft, dot_eqright),
                                                                          source_code_region => (dot_eqleft, dot_eqright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                var        =      {   my (v, f)
                                                                          =
                                                                          make_value_and_fixity_symbols  lowercase_id;

                                                                      {   item               => mark_expression (VARIABLE_IN_EXPRESSION [v], lowercase_idleft, lowercase_idright),
                                                                          source_code_region => (lowercase_idleft, lowercase_idright),
                                                                          fixity                   => THE f
                                                                      };
                                                                  };

                                                atomic_exp =      {   item               => mark_expression (expression, expressionleft, expressionright),
                                                                      source_code_region => (expressionleft, expressionright),
                                                                      fixity             => NULL
                                                                  };



                                                expression =  PRE_FIXITY_EXPRESSION [ atomic_exp, dot_op, var ];

                                                mark_declaration (
                                                    VALUE_DECLARATIONS (
                                                        [   NAMED_VALUE { pattern, expression, is_lazy => FALSE } ],
                                                        NIL
                                                    ),
                                                    lowercase_idleft,
                                                    expressionright
                                                );
                                            }
                                        )



# These rules commented out 2009-04-04 CrT.  Apparently only use of this syntax in the codebase
# was in src/lib/src/note.pkg
#    fun X new (to_string)
#    fun X new' { create, to_string, get=>get' }
# The compiler seems to run fine after simply eliding the above two X
# declarations; I'm inclined to believe these rules are not a cost-effective
# use of syntactic resources:
#
#    | FIELD_T tyvarseq fields          (FIELD_DECLARATIONS (fields, tyvarseq))
#    | MY_T tyvarseq vb                 (VALUE_DECLARATIONS (vb, tyvarseq))
#    | RECURSIVE_T MY_T tyvarseq rvb    (RECURSIVE_VALUE_DECLARATIONS (rvb, tyvarseq))
#
#    | FUN_T tyvarseq fun_decls         (   {
#                                                FUNCTION_DECLARATIONS (fun_decls, tyvarseq);
#                                           }
#                                       )
#    | METHOD_T tyvarseq method_decls   (   {
#                                                FUNCTION_DECLARATIONS (method_decls, tyvarseq);
#                                            }
#                                        )
# # Type variable sequences:
# tyvarseq:
#       LPAREN tyvar_pc RPAREN          (tyvar_pc)

#     | TYVAR                           (   [   SOURCE_CODE_REGION_FOR_TYPEVAR (
#                                                   TYPEVAR (make_typevar_symbol tyvar),
#                                                   (tyvarleft, tyvarright)
#                                               )
#                                           ]
#                                       )




# Expression sequences for
# above 'overloaded val' statements:
#
overloaded_expressions:

      overloaded_expression             ( [ overloaded_expression ] )

    | overloaded_expression
      COMMA
      overloaded_expressions            (   overloaded_expression ! overloaded_expressions)

overloaded_expression:

      lowercase_path                    (mark_expression (VARIABLE_IN_EXPRESSION (lowercase_path make_value_symbol), lowercase_pathright, lowercase_pathleft))
    | operators_path                    (mark_expression (VARIABLE_IN_EXPRESSION (operators_path make_value_symbol), operators_pathright, operators_pathleft))
    | PASSIVEOP_ID                      (mark_expression (VARIABLE_IN_EXPRESSION [make_value_symbol passiveop_id],   passiveop_idright,   passiveop_idleft  ))
    | lvalue_id                         (mark_expression (VARIABLE_IN_EXPRESSION [make_value_symbol lvalue_id],      lvalue_idright,      lvalue_idleft     ))
      

# 'local' declarations:
maybe_declarations:
                                        (SEQUENTIAL_DECLARATIONS NIL)
    | declarations                              (declarations)



declarations:

      declaration_or_local
      SEMI                              (declaration_or_local)

    | declaration_or_local
      SEMI
      declarations                      (make_declaration_sequence   (mark_declaration   (declaration_or_local, declaration_or_localleft, declaration_or_localright),   declarations))


declaration_or_local:

      declaration                       (declaration)

    | STIPULATE_T
      maybe_declarations
      HEREIN_T
      maybe_declarations
      END_T                               (   mark_declaration (
                                                LOCAL_DECLARATIONS (
                                                    mark_declaration (maybe_declarations1, maybe_declarations1left, maybe_declarations1right),
                                                    mark_declaration (maybe_declarations2, maybe_declarations2left, maybe_declarations2right)
                                                ),
                                                stipulate_tleft,
                                                end_tright
                                            )
                                        )



ops:  value_or_bar                      ( [ make_fixity_symbol value_or_bar ] )
    | PASSIVEOP_ID                      ( [ make_fixity_symbol passiveop_id ] )
    | value_or_bar ops                  (   make_fixity_symbol value_or_bar  !  ops)
    | PASSIVEOP_ID ops                  (   make_fixity_symbol passiveop_id  !  ops)





#########################################
# In the third section we build up      #
# our api syntax.                       #
#                                       #
# In "Definition of Standard ML"        #
# terminology anything appearing in     #
# an api is a 'specification', which    #
# we here abbreviate to 'spec':         #
#########################################



# Much of the time we treat 'class' and
# 'package' as synonyms:
package:
        PACKAGE_T                       (())
    |   CLASS_T                         (())
    |   CLASS2_T                        (())


# Spec sequences:
maybe_api_elements:
                                        ( [] )
    | api_elements                      (api_elements) 

api_elements:

      api_element       SEMI            (api_element)

    | api_element
      SEMI
      api_elements                      (api_element @ api_elements)



api_element:

      package package_in_api            ( [ PACKAGES_IN_API package_in_api ] )

    | GENERIC_T PACKAGE_T
      generic_in_api                    ( [ GENERICS_IN_API generic_in_api ] )

    |                sumtypes   ( [ VALCONS_IN_API { sumtypes, with_types => NIL } ] )

    |                sumtypes
      WITHTYPE_T     named_types        ( [ VALCONS_IN_API { sumtypes, with_types => named_types  } ] )

    |               type_in_api         ( [ TYPES_IN_API (type_in_api, FALSE) ] )
    | EQTYPE_T      type_in_api         ( [ TYPES_IN_API (type_in_api, TRUE ) ] )
    | MY_T value_in_api                 ( [ VALUES_IN_API value_in_api ] )
    |      value_in_api                 ( [ VALUES_IN_API value_in_api ] )
    | EXCEPTION_T exception_in_api      ( [ EXCEPTIONS_IN_API exception_in_api ] )

    | INCLUDE_T API_T an_api            ( [ IMPORT_IN_API an_api ] )
    | INCLUDE_T API_T MIXEDCASE_ID      ( [ IMPORT_IN_API (API_BY_NAME (fast_symbol::make_api_symbol mixedcase_id)) ] )

    | SHARING_T sharespec               (sharespec)




# Package specifications:
#
package_in_api:

      package_in_api
      ALSO_T
      package_in_api                    (package_in_api1 @ package_in_api2)

    | lowercase_id COLON an_api         ( [ (make_package_symbol lowercase_id, an_api, NULL) ] )
    | lowercase_id COLON an_api
          EQUAL_OP lowercase            ( [ (make_package_symbol lowercase_id, an_api, THE (lowercase make_package_symbol)) ] )



# Generic package specifications:
#
generic_in_api:

      generic_in_api
      ALSO_T
      generic_in_api                    (generic_in_api1 @ generic_in_api2)

    | lowercase_id fsig                 ( [ (make_generic_symbol lowercase_id, fsig) ] )



# Type specifications:
#
type_in_api:
      type_in_api ALSO_T type_in_api    (type_in_api1 @ type_in_api2)
    | MIXEDCASE_ID typevars     ( [ (make_type_symbol mixedcase_id, typevars, NULL   ) ] )
    | MIXEDCASE_ID typevars
      EQUAL_OP anytype                  ( [ (make_type_symbol mixedcase_id, typevars, THE anytype) ] )


# Value specifications:
#
value_in_api:
      value_in_api ALSO_T value_in_api  (value_in_api1 @ value_in_api2)
    | lowercase_id COLON anytype        ( [ (make_value_symbol lowercase_id, anytype) ] )
    | OPERATORS_ID COLON anytype        ( [ (make_value_symbol operators_id, anytype) ] )
    | PASSIVEOP_ID COLON anytype        ( [ (make_value_symbol passiveop_id, anytype) ] )

    | AMPER        COLON anytype        ( [ (make_value_symbol (raw_symbol (amper_hash,    amper_string )), anytype) ] )
    | ATSIGN       COLON anytype        ( [ (make_value_symbol (raw_symbol (atsign_hash,   atsign_string)), anytype) ] )
    | BACK         COLON anytype        ( [ (make_value_symbol (raw_symbol (back_hash,     back_string  )), anytype) ] )
    | BAR          COLON anytype        ( [ (make_value_symbol (raw_symbol (bar_hash,      bar_string   )), anytype) ] )
    | BANG         COLON anytype        ( [ (make_value_symbol (raw_symbol (bang_hash,     bang_string  )), anytype) ] )
    | BUCK         COLON anytype        ( [ (make_value_symbol (raw_symbol (buck_hash,     buck_string  )), anytype) ] )
    | CARET        COLON anytype        ( [ (make_value_symbol (raw_symbol (caret_hash,    caret_string )), anytype) ] )
    | DASH         COLON anytype        ( [ (make_value_symbol (raw_symbol (dash_hash,     dash_string  )), anytype) ] )
    | PERCNT       COLON anytype        ( [ (make_value_symbol (raw_symbol (percnt_hash,   percnt_string)), anytype) ] )
    | PLUS         COLON anytype        ( [ (make_value_symbol (raw_symbol (plus_hash,     plus_string  )), anytype) ] )
    | QMARK        COLON anytype        ( [ (make_value_symbol (raw_symbol (qmark_hash,    qmark_string )), anytype) ] )
    | SLASH        COLON anytype        ( [ (make_value_symbol (raw_symbol (slash_hash,    slash_string )), anytype) ] )
    | STAR         COLON anytype        ( [ (make_value_symbol (raw_symbol (star_hash,     star_string  )), anytype) ] )
    | TILDA        COLON anytype        ( [ (make_value_symbol (raw_symbol (tilda_hash,    tilda_string )), anytype) ] )

    | DASH_DASH    COLON anytype        ( [ (make_value_symbol (raw_symbol (dashdash_hash,  dashdash_string )), anytype) ] )
    | PLUS_PLUS    COLON anytype        ( [ (make_value_symbol (raw_symbol (plusplus_hash,  plusplus_string )), anytype) ] )
    | DOTDOT       COLON anytype        ( [ (make_value_symbol (raw_symbol (dotdot_hash,    dotdot_string   )), anytype) ] )

    | LANGLE       COLON anytype        ( [ (make_value_symbol (raw_symbol (langle_hash,    langle_string)), anytype) ] )
    | RANGLE       COLON anytype        ( [ (make_value_symbol (raw_symbol (rangle_hash,    rangle_string)), anytype) ] )

    | EQEQ_OP      COLON anytype        ( [ (make_value_symbol (raw_symbol (eqeq_hash,      eqeq_string)), anytype) ] )

    | PRE_AMPER    COLON anytype        ( [ (make_value_symbol (raw_symbol (preamper_hash,  preamper_string )), anytype) ] )
    | PRE_ATSIGN   COLON anytype        ( [ (make_value_symbol (raw_symbol (preatsign_hash, preatsign_string)), anytype) ] )
    | PRE_BACK     COLON anytype        ( [ (make_value_symbol (raw_symbol (preback_hash,   preback_string  )), anytype) ] )
    | PRE_BANG     COLON anytype        ( [ (make_value_symbol (raw_symbol (prebang_hash,   prebang_string  )), anytype) ] )
    | PRE_BUCK     COLON anytype        ( [ (make_value_symbol (raw_symbol (prebuck_hash,   prebuck_string  )), anytype) ] )
    | PRE_CARET    COLON anytype        ( [ (make_value_symbol (raw_symbol (precaret_hash,  precaret_string )), anytype) ] )
    | PRE_DASH     COLON anytype        ( [ (make_value_symbol (raw_symbol (predash_hash,   predash_string  )), anytype) ] )
    | PRE_PERCNT   COLON anytype        ( [ (make_value_symbol (raw_symbol (prepercnt_hash, prepercnt_string)), anytype) ] )
    | PRE_PLUS     COLON anytype        ( [ (make_value_symbol (raw_symbol (preplus_hash,   preplus_string  )), anytype) ] )
    | PRE_STAR     COLON anytype        ( [ (make_value_symbol (raw_symbol (prestar_hash,   prestar_string  )), anytype) ] )
    | PRE_TILDA    COLON anytype        ( [ (make_value_symbol (raw_symbol (pretilda_hash,  pretilda_string )), anytype) ] )

    # NB: Had to expand the above possibilities in-place to resolve
    # a nasty shift-reduce confusion as to whether a lowercase id
    # at the start of a generic package argument list represented
    # a package or value name.

# Exception specifications:
#
exception_in_api:

      exception_in_api
      ALSO_T
      exception_in_api                  (exception_in_api1 @ exception_in_api2)

    | UPPERCASE_ID                      ( [ (make_value_symbol uppercase_id, NULL       ) ] )
    | UPPERCASE_ID      anytype         ( [ (make_value_symbol uppercase_id, THE anytype) ] )


# Type and package sharing
# specifications:
#
sharespec:
      sharespec ALSO_T sharespec                (sharespec1 @ sharespec2)

    | typepatheqn                       (   [   SOURCE_CODE_REGION_FOR_API_ELEMENT (
                                                    TYPE_SHARING_IN_API (typepatheqn make_type_symbol),
                                                    (typepatheqnleft, typepatheqnright)
                                                )
                                            ]
                                        )

    | patheqn                           (   [   SOURCE_CODE_REGION_FOR_API_ELEMENT (
                                                    PACKAGE_SHARING_IN_API (patheqn make_package_symbol),
                                                    (patheqnleft, patheqnright)
                                                )
                                            ]
                                        )
        


typepatheqn:
      mixedcase           EQEQ_OP mixedcase             (\\ kind =  [mixedcase1 kind, mixedcase2 kind])
    | mixedcase           EQEQ_OP typepatheqn           (\\ kind =   mixedcase kind ! typepatheqn kind)

patheqn:
      lowercase           EQEQ_OP lowercase             (\\ kind =  [lowercase1 kind, lowercase2 kind])
    | lowercase           EQEQ_OP patheqn               (\\ kind =   lowercase  kind ! patheqn kind)


# 'where' specifications:
where_spec:
      where_spec ALSO_T where_spec              (where_spec1 @ where_spec2)

    | lowercase  EQEQ_OP lowercase              ( [ WHERE_PACKAGE (lowercase1 make_package_symbol, lowercase2 make_package_symbol) ] )

    | mixedcase
      typevars
      EQEQ_OP
      anytype                                   ( [ WHERE_TYPE      (mixedcase make_type_symbol, typevars, anytype) ] )





an_api:
      MIXEDCASE_ID                      (   SOURCE_CODE_REGION_FOR_API (
                                                API_BY_NAME (make_api_symbol mixedcase_id),
                                                (mixedcase_idleft, mixedcase_idright)
                                        )   )

    | API_T
      LBRACE
      maybe_api_elements
      RBRACE                            (   SOURCE_CODE_REGION_FOR_API (
                                                API_DEFINITION (maybe_api_elements),
                                                (maybe_api_elementsleft, maybe_api_elementsright)
                                        )   )

    | an_api WHERE_T where_spec         (   SOURCE_CODE_REGION_FOR_API (
                                                API_WITH_WHERE_SPECS (an_api, where_spec),
                                                (an_apileft, where_specright)
                                        )   )





########################################
# In the fourth and final section we   #
# build up our generic syntax:         #
########################################



# Api constraints:
#
maybe_api_constraint_op:
                                        (     NO_PACKAGE_CAST         )
    |    WEAK_PACKAGE_CAST   an_api     (   WEAK_PACKAGE_CAST (an_api))
    | PARTIAL_PACKAGE_CAST   an_api     (PARTIAL_PACKAGE_CAST (an_api))
    | COLON                  an_api     ( STRONG_PACKAGE_CAST (an_api))





# Generic package api constraints:
#
maybe_generic_api_constraint_op:
                                        (     NO_PACKAGE_CAST)
    |    WEAK_PACKAGE_CAST MIXEDCASE_ID (   WEAK_PACKAGE_CAST (GENERIC_API_BY_NAME (make_generic_api_symbol mixedcase_id)))
    | PARTIAL_PACKAGE_CAST MIXEDCASE_ID (PARTIAL_PACKAGE_CAST (GENERIC_API_BY_NAME (make_generic_api_symbol mixedcase_id)))
    | COLON                MIXEDCASE_ID ( STRONG_PACKAGE_CAST (GENERIC_API_BY_NAME (make_generic_api_symbol mixedcase_id)))




api_naming:

      api_naming
      ALSO_T
      api_naming                        (api_naming1 @ api_naming2)

    | MIXEDCASE_ID EQUAL_OP an_api      (   [   NAMED_API {
                                                    name_symbol => make_api_symbol mixedcase_id,
                                                    definition  => an_api
                                                }
                                            ]
                                        )



generic_api_naming:

      generic_api_naming
      ALSO_T
      generic_api_naming                (generic_api_naming1 @ generic_api_naming2)

    | MIXEDCASE_ID
      generic_parameter_list
      EQUAL_OP
      an_api                            (   [   NAMED_GENERIC_API {
                                                    name_symbol => make_generic_api_symbol mixedcase_id,
                                                    definition  => GENERIC_API_DEFINITION {
                                                                     parameter => generic_parameter_list,
                                                                     result    => an_api
                                                                 }
                                                }
                                            ]
                                        )



# generic APIs:
fsig: COLON MIXEDCASE_ID                (GENERIC_API_BY_NAME (make_generic_api_symbol mixedcase_id))

    | generic_parameter_list
      COLON
      an_api                            (   GENERIC_API_DEFINITION {
                                                parameter => generic_parameter_list,
                                                result    => an_api
                                            }
                                        )



a_package:
      lowercase                         (   (   SOURCE_CODE_REGION_FOR_PACKAGE (
                                                    PACKAGE_BY_NAME (lowercase make_package_symbol),
                                                    (lowercaseleft, lowercaseright)
                                        )   )   )

    | PACKAGE_T
      LBRACE
      maybe_pkg_elements
      RBRACE                            (PACKAGE_DEFINITION maybe_pkg_elements)


    | lowercase generic_arg             (   SOURCE_CODE_REGION_FOR_PACKAGE (
                                                CALL_OF_GENERIC (lowercase make_generic_symbol, generic_arg),
                                                (lowercaseleft, generic_argright)
                                        )   )

    | STIPULATE_T
      maybe_pkg_elements
      HEREIN_T
      a_package
      END_T                             (   SOURCE_CODE_REGION_FOR_PACKAGE (
                                                LET_IN_PACKAGE (maybe_pkg_elements, a_package),
                                                (stipulate_tleft, end_tright)
                                        )   )

    | a_package
      WEAK_PACKAGE_CAST
      an_api                            (   SOURCE_CODE_REGION_FOR_PACKAGE (
                                                PACKAGE_CAST (a_package, WEAK_PACKAGE_CAST an_api),
                                                (a_packageleft, an_apiright)
                                        )   )

    | a_package
      PARTIAL_PACKAGE_CAST
      an_api                            (   SOURCE_CODE_REGION_FOR_PACKAGE (
                                                PACKAGE_CAST (a_package, PARTIAL_PACKAGE_CAST an_api),
                                                (a_packageleft, an_apiright)
                                        )   )

    | a_package COLON   an_api          (   SOURCE_CODE_REGION_FOR_PACKAGE (
                                                PACKAGE_CAST (a_package, STRONG_PACKAGE_CAST an_api),
                                                (a_packageleft, an_apiright)
                                        )   )



generic_arg:

      LPAREN
      a_package
      RPAREN                            ( [ (a_package, TRUE) ] )

      # We need the following case because if someone writes
      #     package gamma = beta_g(alpha);
      # instead of
      #     package gamma = beta_g( alpha );
      # then the lexer will collapse the "(alpha)" into a PASSIVEOP_ID:
      # -- death by a thousand hacks! :-)       (Problem reported by Hue White. 2011-06-04)
      #
    | PASSIVEOP_ID                      ( [ ( SOURCE_CODE_REGION_FOR_PACKAGE
                                                (
                                                  PACKAGE_BY_NAME [make_package_symbol passiveop_id],
                                                  (passiveop_idleft, passiveop_idright)
                                                ),
                                              TRUE
                                            )
                                          ]
                                        )

    | LPAREN
      maybe_pkg_elements
      RPAREN                            (   [   (   SOURCE_CODE_REGION_FOR_PACKAGE (
                                                        PACKAGE_DEFINITION maybe_pkg_elements,
                                                        (maybe_pkg_elementsleft, maybe_pkg_elementsright)
                                                    ),
                                                    FALSE
                                                )
                                            ]
                                        )


    | LPAREN
      a_package
      RPAREN
      generic_arg                       ( (a_package, TRUE) ! generic_arg)

    | LPAREN
      maybe_pkg_elements
      RPAREN
      generic_arg                       (   (   SOURCE_CODE_REGION_FOR_PACKAGE (
                                                    PACKAGE_DEFINITION maybe_pkg_elements,
                                                    (maybe_pkg_elementsleft, maybe_pkg_elementsright)
                                                ),
                                                FALSE
                                            )
                                            ! generic_arg
                                        )

maybe_pkg_elements:
      pkg_elements                      (pkg_elements)
    |                                   (SEQUENTIAL_DECLARATIONS [])



pkg_elements:
      pkg_element       SEMI            (pkg_element)

    | pkg_element
      SEMI
      pkg_elements                      (   make_declaration_sequence (
                                                mark_declaration (pkg_element, pkg_elementleft, pkg_elementright),
                                                pkg_elements
                                        )   )



pkg_element:
      PACKAGE_T
      named_packages                    (PACKAGE_DECLARATIONS named_packages)

    | CLASS_T
      named_classes                     (PACKAGE_DECLARATIONS named_classes)

    | CLASS2_T
      named_class2es                    (PACKAGE_DECLARATIONS named_class2es)

    | GENERIC_T PACKAGE_T
      generic_naming                    (GENERIC_DECLARATIONS   generic_naming  )

    | declaration                       (mark_declaration (declaration, declarationleft, declarationright))

    | STIPULATE_T
      maybe_pkg_elements
      HEREIN_T
      maybe_pkg_elements
      END_T                             (   LOCAL_DECLARATIONS (
                                                mark_declaration (maybe_pkg_elements1, maybe_pkg_elements1left, maybe_pkg_elements1right),
                                                mark_declaration (maybe_pkg_elements2, maybe_pkg_elements2left, maybe_pkg_elements2right)
                                        )   )



named_packages:
      named_packages
      ALSO_T
      named_packages                    (named_packages1 @ named_packages2)

    | lowercase_id
      maybe_api_constraint_op
      EQUAL_OP
      a_package                         (   [   SOURCE_CODE_REGION_FOR_NAMED_PACKAGE (
                                                    NAMED_PACKAGE {
                                                        name_symbol => make_package_symbol lowercase_id,
                                                        definition  => a_package, 
                                                        constraint  => maybe_api_constraint_op,
                                                        kind        => PLAIN_PACKAGE
                                                    },
                                                    (lowercase_idleft, a_packageright)
                                                )
                                            ]
                                        )

    | lowercase_id
      maybe_api_constraint_op
      LBRACE
      maybe_pkg_elements
      RBRACE                            (   {
                                                [   SOURCE_CODE_REGION_FOR_NAMED_PACKAGE (
                                                        NAMED_PACKAGE {
                                                            name_symbol => make_package_symbol lowercase_id,
                                                            definition  => PACKAGE_DEFINITION maybe_pkg_elements,
                                                            constraint  => maybe_api_constraint_op,
                                                            kind        => PLAIN_PACKAGE
                                                        },
                                                        (lowercase_idleft, rbraceright)
                                                    )
                                                ];
                                            }
                                        )



# This is identical to named_packages (above)
# except that we set kind to CLASS_PACKAGE:
#
named_classes:
      named_classes
      ALSO_T
      named_classes                     (named_classes1 @ named_classes2)

    | lowercase_id
      maybe_api_constraint_op
      EQUAL_OP
      a_package                         (   [   SOURCE_CODE_REGION_FOR_NAMED_PACKAGE (
                                                    NAMED_PACKAGE {
                                                        name_symbol => make_package_symbol lowercase_id,
                                                        definition  => a_package,
                                                        constraint  => maybe_api_constraint_op,
                                                        kind        => CLASS_PACKAGE
                                                    },
                                                    (lowercase_idleft, a_packageright)
                                                )
                                            ]
                                        )

                                                                                # oop_syntax_parser_transform   is from   src/lib/compiler/front/parser/raw-syntax/oop-syntax-parser-transform.pkg
    | lowercase_id
      maybe_api_constraint_op
      LBRACE
      maybe_pkg_elements
      RBRACE                            (   {
                                                [   SOURCE_CODE_REGION_FOR_NAMED_PACKAGE (
                                                        NAMED_PACKAGE {
                                                            name_symbol => make_package_symbol lowercase_id,
                                                            definition  => PACKAGE_DEFINITION (oop_syntax_parser_transform::prepend_dummy_package_references_to_declaration  maybe_pkg_elements),
                                                            constraint  => maybe_api_constraint_op,
                                                            kind        => CLASS_PACKAGE
                                                        },
                                                        (lowercase_idleft, rbraceright)
                                                    )
                                                ];
                                            }
                                        )


# This is identical to above case
# except that we set kind to CLASS2_PACKAGE:
#
named_class2es:
      named_class2es
      ALSO_T
      named_class2es                    (named_class2es1 @ named_class2es2)

    | lowercase_id
      maybe_api_constraint_op
      EQUAL_OP
      a_package                         (   [   SOURCE_CODE_REGION_FOR_NAMED_PACKAGE (
                                                    NAMED_PACKAGE {
                                                        name_symbol => make_package_symbol lowercase_id,
                                                        definition  => a_package,
                                                        constraint  => maybe_api_constraint_op,
                                                        kind        => CLASS2_PACKAGE
                                                    },
                                                    (lowercase_idleft, a_packageright)
                                                )
                                            ]
                                        )

                                                                                # oop_syntax_parser_transform   is from   src/lib/compiler/front/parser/raw-syntax/oop-syntax-parser-transform.pkg
    | lowercase_id
      maybe_api_constraint_op
      LBRACE
      maybe_pkg_elements
      RBRACE                            (   {
                                                [   SOURCE_CODE_REGION_FOR_NAMED_PACKAGE (
                                                        NAMED_PACKAGE {
                                                            name_symbol => make_package_symbol lowercase_id,
                                                            definition  => PACKAGE_DEFINITION (oop_syntax_parser_transform::prepend_dummy_package_references_to_declaration  maybe_pkg_elements),
                                                            constraint  => maybe_api_constraint_op,
                                                            kind        => CLASS2_PACKAGE
                                                        },
                                                        (lowercase_idleft, rbraceright)
                                                    )
                                                ];
                                            }
                                        )



# Generic parameters:
generic_parameter:

      lowercase_id COLON an_api         (   (   THE (make_package_symbol lowercase_id), an_api) )

    | maybe_api_elements                (   (   NULL,
                                                SOURCE_CODE_REGION_FOR_API (
                                                    API_DEFINITION maybe_api_elements,
                                                    (maybe_api_elementsleft, maybe_api_elementsright)
                                        )   )   )



generic_parameter_list:

      LPAREN
      generic_parameter
      RPAREN                            ( [ generic_parameter ] )

    | LPAREN
      generic_parameter
      RPAREN
      generic_parameter_list    (   generic_parameter ! generic_parameter_list)



generic_naming:

     lowercase_id
     generic_parameter_list
     maybe_api_constraint_op
     EQUAL_OP
     a_package                          (   [   SOURCE_CODE_REGION_FOR_NAMED_GENERIC (
                                                    NAMED_GENERIC {
                                                        name_symbol => make_generic_symbol lowercase_id,
                                                        definition  => GENERIC_DEFINITION {
                                                                         parameters => generic_parameter_list,
                                                                         body       => a_package,       
                                                                         constraint => maybe_api_constraint_op
                                                                     }
                                                    },
                                                    (lowercase_idleft, a_packageright)
                                                )
                                            ]
                                        )


    | lowercase_id
      generic_parameter_list
      maybe_api_constraint_op
      LBRACE
      maybe_pkg_elements
      RBRACE                            (   [   SOURCE_CODE_REGION_FOR_NAMED_GENERIC (
                                                    NAMED_GENERIC {
                                                        name_symbol => make_generic_symbol lowercase_id,
                                                        definition  => GENERIC_DEFINITION {
                                                                         parameters => generic_parameter_list,
                                                                         body       => PACKAGE_DEFINITION maybe_pkg_elements,
                                                                         constraint => maybe_api_constraint_op
                                                                     }
                                                    },
                                                    (lowercase_idleft, rbraceright)
                                                )
                                            ]
                                        )

    | lowercase_id
      maybe_generic_api_constraint_op
      EQUAL_OP
      generic_expression                (   [   SOURCE_CODE_REGION_FOR_NAMED_GENERIC (
                                                    NAMED_GENERIC {
                                                        name_symbol => make_generic_symbol lowercase_id,
                                                        definition  => generic_expression (maybe_generic_api_constraint_op)
                                                    },
                                                    (lowercase_idleft, generic_expressionright)
                                                )
                                            ]
                                        )

    | generic_naming
      ALSO_T
      generic_naming                    (generic_naming1 @ generic_naming2)



generic_expression:

      lowercase                         (\\ constraint =  GENERIC_BY_NAME (lowercase make_generic_symbol, constraint))

    | lowercase generic_arg             (\\ constraint =  SOURCE_CODE_REGION_FOR_GENERIC (
                                                              CONSTRAINED_CALL_OF_GENERIC (lowercase make_generic_symbol, generic_arg, constraint),
                                                              (lowercaseleft, generic_argright)
                                        )                 )

    | STIPULATE_T
      maybe_pkg_elements
      HEREIN_T
      generic_expression
      END_T                             (\\ constraint =  SOURCE_CODE_REGION_FOR_GENERIC (
                                                              LET_IN_GENERIC (maybe_pkg_elements, generic_expression constraint),
                                                              (stipulate_tleft, end_tright)
                                        )                 )



maybe_toplevel_declarations:
                                        (SEQUENTIAL_DECLARATIONS [])
    | toplevel_declarations             (toplevel_declarations)



toplevel_declaration:

      PACKAGE_T named_packages          (PACKAGE_DECLARATIONS           named_packages    )
    | CLASS_T   named_classes           (PACKAGE_DECLARATIONS           named_classes     )
    | CLASS2_T  named_class2es          (PACKAGE_DECLARATIONS           named_class2es    )

    | API_T api_naming                  (API_DECLARATIONS               api_naming        )

    | API_T 
      MIXEDCASE_ID
      LBRACE
      maybe_api_elements
      RBRACE                            (   {   an_api =
                                                    SOURCE_CODE_REGION_FOR_API (
                                                        API_DEFINITION (maybe_api_elements),
                                                        (maybe_api_elementsleft, maybe_api_elementsright)
                                                    );

                                                API_DECLARATIONS
                                                    [   NAMED_API {
                                                            name_symbol => make_api_symbol mixedcase_id,
                                                            definition  => an_api
                                                        }
                                                    ];
                                            }
                                        )
    | GENERIC_T API_T
      generic_api_naming                (GENERIC_API_DECLARATIONS generic_api_naming)

    | GENERIC_T PACKAGE_T
      generic_naming                    (GENERIC_DECLARATIONS     generic_naming          )

    | declaration                       (mark_declaration (declaration, declarationleft, declarationright))

    | STIPULATE_T
      maybe_toplevel_declarations
      HEREIN_T
      maybe_toplevel_declarations
      END_T                             (   LOCAL_DECLARATIONS (
                                                mark_declaration (maybe_toplevel_declarations1, maybe_toplevel_declarations1left, maybe_toplevel_declarations1right),
                                                mark_declaration (maybe_toplevel_declarations2, maybe_toplevel_declarations2left, maybe_toplevel_declarations2right)
                                        )   )

    | PRE_COMPILE_CODE                  (   PRE_COMPILE_CODE pre_compile_code )                                 # Note that first PRE_COMPILE_CODE is a lexer token, second PRE_COMPILE_CODE is a raw::Declaration constructor.

    | expression                        (   mark_declaration (
                                                VALUE_DECLARATIONS (
                                                    [   NAMED_VALUE {
                                                            pattern    =>  VARIABLE_IN_PATTERN it_symbol,
                                                            expression,
                                                            is_lazy    =>  FALSE
                                                        }
                                                    ],
                                                    NIL
                                                ),
                                                expressionleft,
                                                expressionright
                                        )   )

toplevel_declarations:

      toplevel_declaration SEMI         (mark_declaration (toplevel_declaration, toplevel_declarationleft, semiright))

    | toplevel_declaration SEMI
      toplevel_declarations             (   mark_declaration (
                                                make_declaration_sequence (
                                                    mark_declaration (toplevel_declaration, toplevel_declarationleft, toplevel_declarationright),
                                                    toplevel_declarations
                                                ),
                                                toplevel_declarationleft,
                                                toplevel_declarationsright
                                            )
                                        )


toplevel:

        toplevel_declarations           (toplevel_declarations)










##########################################################################
#   The following is support for outline-minor-mode in emacs.            #
#  ^C @ ^T hides all Text. (Leaves all headings.)                        #
#  ^C @ ^A shows All of file.                                            #
#  ^C @ ^Q Quickfolds entire file. (Leaves only top-level headings.)     #
#  ^C @ ^I shows Immediate children of node.                             #
#  ^C @ ^S Shows all of a node.                                          #
#  ^C @ ^D hiDes all of a node.                                          #
#  ^HFoutline-mode gives more details.                                   #
#  (Or do ^HI and read emacs:outline mode.)                              #
#                                                                        #
# Local variables:                                                       #
# mode: outline-minor                                                    #
# outline-regexp: "[a-z]"                                                #
# End:                                                                   #
##########################################################################


## Copyright 1989, 1992 by AT&T Bell Laboratories
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUp