# SI413 Unit 2 Languages, Fall 2026 language_name: Mercury notes_from_prof: | Language designed by Chris Taylor and reviewed by Kenzie Koszegi. This is a classic stack-based language with a magick/alchemy theme. That means that when the program is running, it maintains a stack of values (each can be either a bool or a string), and then different commands either add or remove things from the stack. It ends up being a postfix language (where the operations come after the operands) because you have to push things onto the stack first, before you can perform some kind of operations on them. example_program: | ;;;; Mercury block comment :D ;;;; ; Mercury single line comment :P receive ; read a line, push to stack summon order ; pop and store line in "order" variable banish ~ salad~ ; arg 2 banish order ; arg 1 chop ; call chop scry ; pop, reverse value, push it back summon label banish gold ; push true summon rushhour banish lead ; push false summon manager ; weird = not (label + "sandwich" < "mustard") or manager or lead banish ~mustard~ banish ~sandwich~ banish label conjoin ; label + "sandwich" weigh ; (label + "sandwich") < "mustard" reflect banish manager ether banish lead ether summon weird ; print("eat up: [" + label + "]") banish ~]~ banish label banish ~eat up: [~ conjoin conjoin invoke ; print("hot: " + bool2str(not rushhour or weird)) banish ~hot: ~ banish rushhour reflect banish weird ether assay transmute ; put "hot: " at top of stack conjoin invoke example_input_1: | fruit salad example_output_1: | eat up: [tiurf] hot: yes example_input_2: | pork example_output_2: | eat up: [krop] hot: no tokens: | ignore: ;;;;[\s\S]*?;;;; ignore: ;[^\n]* ignore: \s STRING: ~([^\\~]|\\.)*~ BANISH: banish INVOKE: invoke RECEIVE: receive SUMMON: summon TRANSMUTE: transmute SCRY: scry REFLECT: reflect CONJOIN: conjoin CHOP: chop WEIGH: weigh ETHER: ether ASSAY: assay GOLD: gold LEAD: lead VAR: [A-Za-z_][A-Za-z0-9_]* grammar: | parser grammar MercuryParser; tokens { STRING, BANISH, INVOKE, RECEIVE, SUMMON, TRANSMUTE, SCRY, REFLECT, CONJOIN, CHOP, WEIGH, ETHER, ASSAY, GOLD, LEAD, VAR } program : stmt program | EOF ; stmt : BANISH value | SUMMON VAR | RECEIVE | INVOKE | TRANSMUTE | SCRY | REFLECT | CONJOIN | CHOP | WEIGH | ETHER | ASSAY ; value : STRING | GOLD | LEAD | VAR ; semantics: | Mercury runs from top to bottom, left to right. Mercury has a LIFO stack that can hold booleans and strings. Variables are global and store a single string or boolean value. Variables are mutable and can be overwritten with new values of either type. Strings in Mercury are defined between two tildas, for example, ~Abracadabra~. Inline tildas are ignored by a prefixing backslash, for example, ~random tilda here\~ but not here~. Booleans are gold for true and lead for false. Booleans cannot be printed directly, so use the "assay" command to convert them to a string before printing. Mercury takes inspiration from the x86 calling convention where the first argument to a function is the at the top of the stack, the seond argument just below it, and so on. These arguements will be popped and the result will be pushed. Strings, Booleans, and Variables: - banish ~~ - push specified string to stack - banish gold - push boolean true value - banish lead - push boolean false value - banish - push value of variable - summon - pop value into variable I/O: - receive - read one line of text from user (w/o newline) and push to stack as string - invoke - pop a string and print it w/ newline Helpers: transmute - swap top two values on stack conjoin - push arg1 + arg2 (concatenate strings) scry - pop string, reverse it, push it chop - push arg1 chopped by arg2 (string chop) weigh - push gold if arg1 < arg2 lexicographically, else push lead Boolean Operations: ether - push arg1 OR arg2 reflect - pop arg1, push NOT arg1 assay - pops a boolean, push string ~yes~ if true and ~no~ if false