# Parse and Process the Key-Language Input

Let's parse and process Key-Language! Given the input of a sequence of keyboard keypresses and/or special keys, write a program, function, etc. that outputs the product when all the actions are processed based on the following keyboard:

+-------------------------------------------------------+
| ~ | ! | @ | # | $| % | ^ | & | * | ( | ) | - | + | | |  | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | _ | = |Del| +-------------------------------------------------------+ |TAB| q | w | e | r | t | y | u | i | o | p | [ | ] | \ | | | Q | W | E | R | T | Y | U | I | O | P | { | } | | | +-------------------------------------------------------+ |CAPS | a | s | d | f | g | h | j | k | l | ; | ' | RET | | | A | S | D | F | G | H | J | K | L | : | " | | +-------------------------------------------------------+ | SHIFT | z | x | c | v | b | n | m | , | . | / | SHIFT | | | Z | X | C | V | B | N | M | < | > | ? | | +-------------------------------------------------------+ | | | SPACEBAR | +-------------------------------------------------------+  The keys that output actual characters not consisting of whitespace and are able to be modified by other keys will be known as "character keys", and those that modify the output of other keys or output whitespace will be known as "special keys". The alphabet character keys, which will be shown in the input with uppercase letters, can be modified with either Shift or Caps Lock to produce uppercase letters, and the rest of the character keys can only be modified with Shift to produce their alternate characters. Therefore A in the input corresponds to the a A character key, whose normal output is a and whose modified output, obtainable with either the Shift or Caps Lock key, is A. On the other hand, /, which corresponds to the / ? character key, has a normal output of / and a modified output of ? obtainable with only with Shift this time. # Rules • The input will always be a string consisting of a sequence of the character keys and special keys. The full special key to string mapping for the input (i.e. the format they are guaranteed to be in the input) and their corresponding actions/outputs are as follows: • <DEL> -> Delete the previous character (including whitespace). If called when string is empty, nothing happens. If called 2 or more times in a row, 2 consecutive deletes happen. For instance, "RE<DEL><DEL>" should return an empty string ("") and also "R<RET><DEL><DEL>E" should return just "E". • <CAPS> -> Enable Caps Lock until <CAPS> appears again, upon which it is disabled, although it is not guaranteed to be disabled by the end of the input. Enabling this only modifies the upcoming alphabet keys resulting in them outputting only uppercase letters. For instance, "<CAPS>RE<CAPS>" results in the output "RE", but <CAPS>.<CAPS> would still result in a ".". • <RET> -> Add a new line. • <SPC> -> Add a single blank space. • <TAB> -> Add 4 spaces. • <SHFT> -> Shift is held down resulting in the alternate character of the upcoming keypress to be output, after which the key is released. For instance, "<SHFT>A" results in the output "A", "<SHFT>1" results in the output "!", and "<SHFT>1234" results in the output "!234" as only the first upcoming keypress is modified and nothing else. It is guaranteed that a character key will succeed a <SHFT>. Therefore, <SHFT><SPC> is not a possible input. • An empty string is also possible as input, for which the output should be nothing. • The use of any built-in that solves this problem directly is disallowed. • The use of standard loopholes is disallowed. # Test Cases Presented in the format Actual String Input -> Actual String Output followed by an explanation for a few. 1. 1<SHFT>2<TAB><CAPS>R.KAP.<SPC><SHFT>123 -> 1@ R.KAP. !23 Output 1 as the 1 key is pressed without a toggle, then Shift is held down and the 2 key is pressed resulting in the @ output. Then the Shift key is released and Tab is pressed, resulting in a 4 spaced indentation. Following up, the Caps Lock key is pressed, after which the R,.,K,A,P, and . keys are pressed, resulting in the output R.KAP.. Finally, a single space is output followed by shift resulting in !23 being output when the 1,2, and 3 keys are pressed at the end. 2. <SHFT>ABCDEFG<SHFT>HIJK<SHFT>1<SHFT>2<SHFT>3<SHFT>4567890 -> AbcdefgHijk!@#$567890

The Shift key is held down followed by the A key, resulting in the output A followed by the output bcdefg when the B-G keys are pressed. Then, the Shift key is held down again succeeded by the H key, after which the output is H, followed by ijk when the I-K keys are pressed. Finally, the 1-4 keys are all modified as shift is held down before each keypress resulting in the output !@#$ finished off by 567890 when the 5-0 keys re pressed. 3. <CAPS>THIS<SPC>IS<SPC>IN<SPC>ALL<SPC>CAPS<CAPS><SPC>NOW<SPC>THIS<SPC>IS<SPC>IN<SPC>ALL<SPC>LOWERCASE -> THIS IS IN ALL CAPS now this is in all lowercase 4. <TAB><SPC><TAB><SHFT>1 -> ! 5. <CAPS>WWW<CAPS>.CODEGOLF.STACKEXCHANGE<SHFT>.COM -> WWW.codegolf.stackexchange>com 6. PROGRAMMING<CAPS><SPC>IS<SPC><CAPS>AWESOME -> programming IS awesome 7. <DEL><RET><DEL><RET><DEL> -> "" (Empty String) The delete key is pressed in the beginning after which nothing happens. Then, the Return key is pressed resulting in a new line, which is deleted after the backspace key is pressed again. Finally, the same sequence (new line followed by backspace) is repeated. After all this, the output is an empty string. 8. <SHFT>HI<SPC>HOW<SPC>ARE<SPC>YOU<SHFT>/<RET><SHFT>I<SPC><SHFT>AM<SPC>O<DEL><SHFT>GOOD<SHFT>1 -> Hi how are you?\nI Am Good! 9. <SHFT>,<CAPS>RET<CAPS><SHFT>. -> <RET> The string <RET> should be the actual string output. Thus, this should not output a new line. 10. <CAPS>67890,.;'[]<CAPS> -> 67890,.;'[] 11. <CAPS><SHFT>A -> A 12. RE<DEL><DEL> -> "" (Empty String) 13. U<RET><DEL><DEL>I -> i 14. <DEL><DEL><DEL>5<DEL> -> "" (Empty string) 15. "" (Empty String) -> "" (Empty String) This is so the shortest code in bytes wins! • That's a weird Delete key you have there... – Dennis Jul 2 '16 at 2:35 • @Dennis Well, I'm describing keys based on my MacBook Pro's keyboard, where the delete key deletes the previous character. I still agree with you though. It's a pretty weird layout. – R. Kap Jul 2 '16 at 2:36 • Ah, that explains it. It's called Backspace on literally every keyboard I've ever owned. mumbles something about normal keyboard keypresses – Dennis Jul 2 '16 at 2:40 • In test #2, should the output be AbcdefgHijk!@#$567890? Also, in test #8, <SHFT> is at the end of the string, but the rules state: "It is guaranteed that a character key will succeed a <SHFT>." – atlasologist Jul 2 '16 at 5:13
• @atlasologist Yes, you are right, and nice catch! I forgot to update those. – R. Kap Jul 2 '16 at 6:25

# 16-bit x86 machine code, 140 139 bytes

Saved 1 byte by replacing DL with DX in the second-to-last opcode. Also corrected jump offsets in disassembly to match hex dump.

Since the nature of the task requires some pre-initialized data, and the answer is not a full program but a function, I assume that there's a data section in the program and the linker promptly updates the address of the data. The address placeholder is denoted by '????'.

This is a hex representation of the code. The parameters are pointer to input string in SI and pointer to the output buffer in DI. Strings are assumed to be NULL-terminated.

8D1E????89F931D231C0FCAC84C07419D0EA72173C3C74263C41720A3C5A770684F675020C20AAEBE2AAC33C41720B3C5A76F324170402D7EBEC2C27EBF94646AC46240F74154848741748741948741A4848741A39F973B34FEBB04680F601EBAAB020AAAAAAB020EBBCB00AEBB84642EB99


Content of the mapping table (25 bytes):

"   =<_>?)!@#$%^&*( :{}|  The byte count accounts for both code and data. ## Disassembly: 8d 1e ?? ?? lea bx,ds:???? ;Load address of mapping table to BX 89 f9 mov cx,di ;Save pointer to output buffer in CX 31 d2 xor dx,dx ;DX is the status register, bit 0 - shift status 31 c0 xor ax,ax ;bit 8 - caps lock status fc cld ;Clear DF _loop: ac lodsb ;Fetch next char 84 c0 test al,al ;If end of string found 74 19 je _end ;break d0 ea shr dl,1 ;Copy shift flag to CF and clear it 72 17 jc _shift ;Branch to input procssing with shift set 3c 3c cmp al,0x3c ;If AL == '<' 74 26 je _special ;branch to special character processing 3c 41 cmp al,0x41 ;At this point anything 72 0a jb _out ;not in 'A'..'Z' range 3c 5a cmp al,0x5a ;should be printed unmodified 77 06 ja _out 84 f6 test dh,dh ;If caps lock status flag is set 75 02 jne _out ;go to printing right away 0c 20 or al,0x20 ;otherwise convert to lower case _out: aa stosb ;Store AL into output buffer eb e2 jmp _loop ;Continue _end: aa stosb ;NULL-terminate the output string c3 ret ;and return _shift: 3c 41 cmp al,0x41 ;AL in the range [0x27..0x3b] with 72 0b jb _xlat0 ;a couple of holes in it 3c 5a cmp al,0x5a ;AL in the range 'A'..'Z' 76 f3 jbe _out ;Since shift is active, go print it 24 17 and al,0x17 ;AL is 0x5b, 0x5c, 0x5d or 0x7e, 04 02 add al,0x2 ;convert to the [0x15..0x18] range _xlat: d7 xlatb ;Lookup mapping table (AL=[BX+AL]) eb ec jmp _out _xlat0: 2c 27 sub al,0x27 ;Convert AL to be a zero-based index eb f9 jmp _xlat ;Reuse lookup code _special: ;The next 4 or 5 chars are special character opcode 46 inc si ;Since correct input format is guaranteed 46 inc si ;don't bother reading & checking all of them, ac lodsb ;just load the third one and skip the rest 46 inc si ;The lower 4 bits of the 3rd char 24 0f and al,0xf ;allow to differentiate opcodes 74 15 jz _sc_caps ;0x0 48 dec ax 48 dec ax 74 17 jz _sc_tab ;0x2 48 dec ax 74 19 jz _sc_spc ;0x3 48 dec ax 74 1a jz _sc_ret ;0x4 48 dec ax 48 dec ax 74 1a jz _sc_shft ;0x6 _sc_del: ;0xC, <DEL> opcode 39 f9 cmp cx,di ;Check the length of the current output 73 b3 jae _loop ;DI <= CX ==> NOOP 4f dec di ;Remove the last char eb b0 jmp _loop _sc_caps: ;<CAPS> opcode 46 inc si ;Consume leftover '>' from the input 80 f6 01 xor dh,0x1 ;Flip caps lock status bit eb aa jmp _loop _sc_tab: ;<TAB> opcode b0 20 mov al,0x20 ;Space char aa stosb ;Print it three times aa stosb ;and let the <SPC> handler aa stosb ;do the last one _sc_spc: ;<SPC> opcode b0 20 mov al,0x20 ;Space char eb bc jmp _out ;Go print it _sc_ret: ;<RET> opcode b0 0a mov al,0xa ;Newline char eb b8 jmp _out ;Go print it _sc_shft: ;<SHFT> opcode 46 inc si ;Consume leftover '>' from the input 42 inc dx ;Set shift status bit (DL is guaranteed to be zero) eb 99 jmp _loop  For 32-bit instruction set the code is absolutely the same except for the first instruction which is 2 bytes longer due to 32-bit addressing (8d1d???????? lea ebx,ds:????????) • Nice work! :) If it's not too much trouble, can you please check if your program returns and output of i for the test caseU<RET><DEL><DEL>I and an empty string for the input RE<DEL><DEL>? I clarified the rules a little bit regarding the delete key, so if those 2 test cases don't work, could you please also update your code so that it produces the correct output for those test cases? Thank you! – R. Kap Jul 5 '16 at 7:44 • All test cases succeeded. Why would <DEL> work incorrectly? It's just a register decrement with boundary check – meden Jul 5 '16 at 9:06 • All right. I just wanted to make sure that your program worked as it should. Great answer. – R. Kap Jul 5 '16 at 9:09 • We need more special cases. It'd be more interesting if <DEL> could not delete the <RET>. I can implement it in just 3 bytes. – meden Jul 5 '16 at 16:25 • When typing in a shell's command line that perfectly makes sense. But, mind you, I'm not asking for the rule change. Thanks for the challenge. – meden Jul 6 '16 at 13:55 # Retina, 136 bytes Probably can be golfed further. <SHFT> § <SPC> <TAB> <CAPS> ¶ <RET> þ <DEL> ÷ TLl(?<=^(.*¶.*¶)*).+ T-=;'[]/\\,.w\_+:"{}?|<>_)!@#$%^&*(lL§.
§|¶

i(þ
¶
[^§]?÷



Verify all testcases. (Slightly modified to run all testcases at once.)

• Caps + Shift + A = a on my keyboard. – Neil Jul 2 '16 at 18:40
• @Neil Well, for the purposes of this challenge (and according to my Macbook Pro's keyboard) Caps+Shift+A = A. Man my keyboard is weird... – R. Kap Jul 2 '16 at 18:47
• CAPS + SHIFT + A = A. Why on earth would caps invert shift?? – cat Jul 2 '16 at 21:30
• @cat in millions on Windows system CAPS invert shift, no matter how many question marks you write. Because it's convenient and users are used to it – edc65 Jul 2 '16 at 22:00
• Aaaand, two 110 byte solutions: retina.tryitonline.net/…, retina.tryitonline.net/… ... I think I'm done for now. ;) – Martin Ender Jul 5 '16 at 7:27

# JavaScript (ES6), 207

Updated to fix the bug with repeated deletes, even some bytes shorter.

s=>s.replace(/<\w+>|./g,x=>(k=x[3])=='L'?o=o.slice(0,-1):k=='P'?l=!l:k=='F'?s=0:o+=k?k<'C'?'    ':k<'D'?' ':
:s?l?x.toLowerCase():x:s=")!@#$%^&*("[x]||'_={}|:"<>?'["-+[]\\;',./".indexOf(x)]||x,l=s,o='')&&o  less golfed s=>s.replace( /<\w+>|./g, x => (k=x[3]) == 'L' ? o = o.slice(0,-1) : k == 'P' ? l = !l : k == 'F' ? s = 0 : o+= k ? k < 'C' ? ' ' : k < 'D' ? ' ' : '\n' : s ? l ? x.toLowerCase() : x : s = ")!@#$%^&*("[x] || '_={}|:"<>?' ["-+[]\\;',./".indexOf(x)] || x,
l = s, o = ''
) && o


Test

F=
s=>s.replace(/<\w+>|./g,x=>(k=x[3])=='L'?o=o.slice(0,-1):k=='P'?l=!l:k=='F'?s=0:o+=k?k<'C'?'    ':k<'D'?' ':
:s?l?x.toLowerCase():x:s=")!@#$%^&*("[x]||'_={}|:"<>?'["-+[]\\;',./".indexOf(x)]||x,l=s,o='')&&o console.log=(...x)=>O.textContent+=x.join +'\n' ;[["1<SHFT>2<TAB><CAPS>R.KAP.<SPC><SHFT>123", "1@ R.KAP. !23"] ,["<SHFT>ABCDEFG<SHFT>HIJK<SHFT>1<SHFT>2<SHFT>3<SHFT>4567890", "AbcdefgHijk!@#$567890"]
,["<CAPS>THIS<SPC>IS<SPC>IN<SPC>ALL<SPC>CAPS<CAPS><SPC>NOW<SPC>THIS<SPC>IS<SPC>IN<SPC>ALL<SPC>LOWERCASE", "THIS IS IN ALL CAPS now this is in all lowercase"]
,["<TAB><SPC><TAB><SHFT>1", "         !"]
,["<CAPS>WWW<CAPS>.CODEGOLF.STACKEXCHANGE<SHFT>.COM", "WWW.codegolf.stackexchange>com"]
,["PROGRAMMING<CAPS><SPC>IS<SPC><CAPS>AWESOME", "programming IS awesome"]
,["<DEL><RET><DEL><RET><DEL>", ""]
,["<SHFT>HI<SPC>HOW<SPC>ARE<SPC>YOU<SHFT>/<RET><SHFT>I<SPC><SHFT>AM<SPC>O<DEL><SHFT>GOOD<SHFT>1", "Hi how are you?\nI Am Good!"]
,["<SHFT>,<CAPS>RET<CAPS><SHFT>.", "<RET>"]
,["<CAPS>67890,.;'[]<CAPS>", "67890,.;'[]"]
,["<CAPS><SHFT>A", "A"]
,["U<RET><DEL><DEL>I", "i"]
,["RE<DEL><DEL>", ""]
,["", ""]].forEach(t=>{
var i=t[0],k=t[1],r=F(i)
console.log(
k==r?'OK':'KO',i,'\n->',r,k==r?'\n':'(should be ->'+k+')\n'
)
})
<pre id=O></pre>

• Nice job! :) If it's not too much trouble, can you please check if your program returns and output of I for the test case U<RET><DEL><DEL>I and an empty string for the input RE<DEL><DEL>? I clarified the rules a little bit regarding the delete key, so if those 2 test cases don't work, could you please also update your code so that it produces the correct output for those test cases? Thank you! – R. Kap Jul 5 '16 at 7:09
• Wrong for these test cases. I have to take another approach. Meanwhile, i presume U<RET><DEL>I should give i not I` – edc65 Jul 5 '16 at 7:34
• Yes, you are correct about that. Updated. – R. Kap Jul 5 '16 at 7:41