## 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.pkginclude package raw_syntax; # raw_syntax is from
src/lib/compiler/front/parser/raw-syntax/raw-syntax.pkginclude package make_raw_syntax; # make_raw_syntax is from
src/lib/compiler/front/parser/raw-syntax/make-raw-syntax.pkginclude package error_message; # error_message is from
src/lib/compiler/front/basics/errormsg/error-message.pkginclude package symbol; # symbol is from
src/lib/compiler/front/basics/map/symbol.pkginclude package fast_symbol; # fast_symbol is from
src/lib/compiler/front/basics/map/fast-symbol.pkginclude package raw_syntax_junk; # raw_syntax_junk is from
src/lib/compiler/front/parser/raw-syntax/raw-syntax-junk.pkginclude package regex_to_raw_syntax; # regex_to_raw_syntax is from
src/lib/compiler/front/parser/raw-syntax/regex-to-raw-syntax.pkginclude package fixity; # fixity is from
src/lib/compiler/front/basics/map/fixity.pkgpackage elc = expand_list_comprehension_syntax; # expand_list_comprehension_syntax is from
src/lib/compiler/front/parser/raw-syntax/expand-list-comprehension-syntax.pkgpackage hs = hash_string; # hash_string is from
src/lib/src/hash-string.pkginclude 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.pkgRaw_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.pkgapp_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.