Execute CopyPasta Language: Difference between revisions
Added FreeBASIC |
|||
(14 intermediate revisions by 6 users not shown) | |||
Line 16: | Line 16: | ||
|} |
|} |
||
<br> |
<br> |
||
=={{header|11l}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="11l">:start: |
|||
V source = File(:argv[1]).read() |
|||
V lines = source.split("\n") |
|||
V clipboard = ‘’ |
|||
V loc = 0 |
|||
L loc < lines.len |
|||
V command = lines[loc].trim(‘ ’) |
|||
X.try |
|||
I (command == ‘Copy’) |
|||
clipboard ‘’= lines[loc + 1] |
|||
E I (command == ‘CopyFile’) |
|||
I (lines[loc + 1] == ‘TheF*ckingCode’) |
|||
clipboard ‘’= source |
|||
E |
|||
V filetext = File(lines[loc + 1]).read() |
|||
clipboard ‘’= filetext |
|||
E I (command == ‘Duplicate’) |
|||
clipboard ‘’= clipboard * ((Int(lines[loc + 1])) - 1) |
|||
E I (command == ‘Pasta!’) |
|||
print(clipboard) |
|||
L.break |
|||
E |
|||
exit(‘unknown command '’command‘' encountered on line ’(loc + 1)) |
|||
X.catch |
|||
exit(‘error while executing command '’command‘' on line ’(loc + 1)) |
|||
loc += 2</syntaxhighlight> |
|||
=={{header|C++}}== |
=={{header|C++}}== |
||
{{trans|Nanoquery}} |
{{trans|Nanoquery}} |
||
< |
<syntaxhighlight lang="cpp">#include <fstream> |
||
#include <iostream> |
#include <iostream> |
||
#include <sstream> |
#include <sstream> |
||
Line 151: | Line 186: | ||
// return in case we never hit a 'Pasta!' statement |
// return in case we never hit a 'Pasta!' statement |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
The following files were used for testing: |
The following files were used for testing: |
||
Line 213: | Line 248: | ||
usage: ./copypasta [filename.cp] |
usage: ./copypasta [filename.cp] |
||
</pre> |
</pre> |
||
=={{header|FreeBASIC}}== |
|||
Building on Python and Phix solution |
|||
<syntaxhighlight lang="vbnet">' Rosetta Code problem: https://rosettacode.org/wiki/Execute_CopyPasta_Language |
|||
' by Jjuanhdez, 05/2024 |
|||
#define isNumeric(s) Iif(Val(s) = 0 And s <> "0", False, True) |
|||
Const As String prog1_cp = "Copy" & Chr(10) & "Rosetta Code" & Chr(10) & "Duplicate" & Chr(10) & "2" & Chr(10) & "Pasta!" & Chr(10) & "La Vista" |
|||
Const As String prog2_cp = "CopyFile" & Chr(10) & "pasta.txt" & Chr(10) & "Duplicate" & Chr(10) & "1" & Chr(10) & "Pasta!" |
|||
Const As String prog3_cp = "Copy" & Chr(10) & "Invalid" & Chr(10) & " Duplicate" & Chr(10) & "1" & Chr(10) & "Goto" & Chr(10) & "3" & Chr(10) & "Pasta!" |
|||
Const As String prog4_cp = "CopyFile" & Chr(10) & "TheF*ckingCode" & Chr(10) & "Duplicate" & Chr(10) & "2" & Chr(10) & "Pasta!" |
|||
Const As String prog5_cp = "Copy" & Chr(10) & "Rosetta Code" & Chr(10) & "Duplicate" & Chr(10) & "A" & Chr(10) & "Pasta!" |
|||
Const As String doesntexist_cp = "" |
|||
Const As String pasta_txt = "The pasta.txt file." |
|||
Dim Shared As String prog |
|||
Dim Shared As String fake_files(1 To 7) |
|||
Dim Shared As String fake_texts(1 To 7) |
|||
fake_files(1) = "prog1.cp" |
|||
fake_files(2) = "prog2.cp" |
|||
fake_files(3) = "prog3.cp" |
|||
fake_files(4) = "prog4.cp" |
|||
fake_files(5) = "prog5.cp" |
|||
fake_files(6) = "doesntexist.cp" |
|||
fake_files(7) = "pasta.txt" |
|||
fake_texts(1) = prog1_cp |
|||
fake_texts(2) = prog2_cp |
|||
fake_texts(3) = prog3_cp |
|||
fake_texts(4) = prog4_cp |
|||
fake_texts(5) = prog5_cp |
|||
fake_texts(6) = doesntexist_cp |
|||
fake_texts(7) = pasta_txt |
|||
Function GetFileLines(Byval filename As String) As String |
|||
Dim As String lines, source, linea |
|||
Dim As Integer i = 0, k |
|||
For k = Lbound(fake_files) To Ubound(fake_files) |
|||
If filename = fake_files(k) Then |
|||
source = Iif(Command() = "", fake_texts(k), prog) |
|||
lines = "" |
|||
While i <= Len(source) |
|||
linea = "" |
|||
While i <= Len(source) And Mid(source, i, 1) <> Chr(10) |
|||
linea &= Mid(source, i, 1) |
|||
i += 1 |
|||
Wend |
|||
lines &= Trim(linea) & Chr(10) |
|||
i += 1 |
|||
Wend |
|||
Exit For |
|||
End If |
|||
Next |
|||
Return lines |
|||
End Function |
|||
Sub Interpret(Byval filename As String) |
|||
Dim As String linea, tmp, cmd, arg |
|||
Dim As String pgm = GetFileLines(filename) |
|||
Dim As String clipboard = "" |
|||
Dim As Integer pc = 1, l = 0 |
|||
Print "interpret(" & filename & "):" |
|||
Do |
|||
If pc >= Len(pgm) Then |
|||
Print "No Pasta! Sucha mistaka to maka" |
|||
Exit Sub |
|||
End If |
|||
cmd = Trim(Mid(pgm, pc, Instr(pc, pgm, Chr(10)) - pc)) |
|||
arg = Mid(pgm, pc + Len(cmd) + 1, Instr(pc + Len(cmd) + 1, pgm, Chr(10)) - pc - Len(cmd) - 1) |
|||
Select Case cmd |
|||
Case "Copy" |
|||
clipboard &= arg |
|||
l += 4 |
|||
Case "CopyFile" |
|||
Dim As Integer fileNumber = Freefile |
|||
If arg = "TheF*ckingCode" Then |
|||
Open filename For Input As #fileNumber |
|||
Else |
|||
Open arg For Input As #fileNumber |
|||
If Err > 0 Then Print "Error: Could not open file "; arg |
|||
End If |
|||
Do While Not Eof(fileNumber) |
|||
Line Input #fileNumber, linea |
|||
tmp &= linea & Chr(10) |
|||
Loop |
|||
Close #fileNumber |
|||
clipBoard &= tmp |
|||
l += 2 |
|||
Case "Duplicate" |
|||
If Not isNumeric(arg) Then |
|||
Print "Line " & l & ": wrong number of repetitions." |
|||
Exit Do |
|||
End If |
|||
tmp = "" |
|||
For i As Integer = 1 To Val(arg) |
|||
tmp &= clipboard |
|||
Next |
|||
clipboard &= tmp |
|||
l += 2 |
|||
Case "Pasta!" |
|||
Print clipboard |
|||
Exit Sub |
|||
Case "" |
|||
pc -= 1 |
|||
Case Else |
|||
Print "Line " & l & ": unknown command """ & cmd & """" |
|||
Exit Sub |
|||
End Select |
|||
pc += Len(cmd) + Len(arg) + 2 |
|||
Loop |
|||
End Sub |
|||
Sub Main() |
|||
Dim As String cad, cl = Command() |
|||
Dim As Integer ff = Freefile |
|||
If cl <> "" Then |
|||
If Open(cl For Input As #ff) = 0 Then |
|||
While Not Eof(ff) |
|||
Line Input #ff, cad |
|||
prog &= Trim(cad) & Chr(10) |
|||
Wend |
|||
Close #ff |
|||
Else |
|||
Print "Error: Could not open file "; cl |
|||
Exit Sub |
|||
End If |
|||
Interpret(cl) |
|||
Else |
|||
For i As Integer = Lbound(fake_files) To Ubound(fake_files)-1 |
|||
Interpret("prog" & (i) & ".cp") |
|||
Print |
|||
Next |
|||
End If |
|||
End Sub |
|||
Main() |
|||
Sleep</syntaxhighlight> |
|||
{{out}} |
|||
<pre>interpret(prog1.cp): |
|||
Rosetta CodeRosetta CodeRosetta Code |
|||
interpret(prog2.cp): |
|||
I'm the pasta.txt file. |
|||
I'm the pasta.txt file. |
|||
interpret(prog3.cp): |
|||
Line 6: unknown command "Goto" |
|||
interpret(prog4.cp): |
|||
CopyFile |
|||
TheF*ckingCode |
|||
Duplicate |
|||
2 |
|||
Pasta! |
|||
CopyFile |
|||
TheF*ckingCode |
|||
Duplicate |
|||
2 |
|||
Pasta! |
|||
CopyFile |
|||
TheF*ckingCode |
|||
Duplicate |
|||
2 |
|||
Pasta! |
|||
interpret(prog5.cp): |
|||
Line 4: wrong number of repetitions. |
|||
interpret(prog6.cp): |
|||
Error: Could not open file doesntexist.cp</pre> |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
Line 236: | Line 447: | ||
8. When the program is about to end and the contents of the clipboard have (when appropriate) been printed out, the clipboard should be cleared. |
8. When the program is about to end and the contents of the clipboard have (when appropriate) been printed out, the clipboard should be cleared. |
||
< |
<syntaxhighlight lang="go">// copypasta.go |
||
package main |
package main |
||
Line 325: | Line 536: | ||
err = clipboard.WriteAll("") // clear clipboard |
err = clipboard.WriteAll("") // clear clipboard |
||
check(err) |
check(err) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 379: | Line 590: | ||
=={{header|Java}}== |
=={{header|Java}}== |
||
{{trans|Nanoquery}} |
{{trans|Nanoquery}} |
||
< |
<syntaxhighlight lang="java">import java.io.File; |
||
import java.nio.file.Files; |
import java.nio.file.Files; |
||
import java.util.ArrayList; |
import java.util.ArrayList; |
||
Line 463: | Line 674: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
The following files were used for testing: |
The following files were used for testing: |
||
Line 527: | Line 738: | ||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
< |
<syntaxhighlight lang="julia"> |
||
function interpretCopyPasta() |
function interpretCopyPasta() |
||
clipboard = String[] |
clipboard = String[] |
||
Line 566: | Line 777: | ||
interpretCopyPasta() |
interpretCopyPasta() |
||
</ |
</syntaxhighlight>{{out}} |
||
If run on the following CopyPasta "code" file: |
If run on the following CopyPasta "code" file: |
||
<pre> |
<pre> |
||
Line 608: | Line 819: | ||
=={{header|Nanoquery}}== |
=={{header|Nanoquery}}== |
||
< |
<syntaxhighlight lang="nanoquery">// a function to handle fatal errors |
||
def fatal_error(errtext) |
def fatal_error(errtext) |
||
println "%" + errtext |
println "%" + errtext |
||
Line 661: | Line 872: | ||
// increment past the command and the next line |
// increment past the command and the next line |
||
loc += 2 |
loc += 2 |
||
end</ |
end</syntaxhighlight> |
||
The following files were used for testing: |
The following files were used for testing: |
||
Line 722: | Line 933: | ||
%error while trying to read from specified file |
%error while trying to read from specified file |
||
usage: copypasta.nq [filename.cp] |
usage: copypasta.nq [filename.cp] |
||
</pre> |
|||
=={{header|Nim}}== |
|||
<syntaxhighlight lang="nim">import os, strutils |
|||
type CopyPastaError = object of CatchableError |
|||
template raiseError(message: string, linenum = 0) = |
|||
let prefix = if linenum != 0: "Line $1: ".format(linenum) else: "" |
|||
raise newException(CopyPastaError, prefix & message) |
|||
proc copyPasta() = |
|||
## Load and execute a program. |
|||
var clipboard: string |
|||
if paramCount() != 1: |
|||
echo "usage: ", getAppFilename().lastPathPart, " filename.cp" |
|||
quit QuitFailure |
|||
let path = paramStr(1) |
|||
let code = try: path.readFile() |
|||
except IOError: raiseError("Unable to read file “$1”.".format(path)) |
|||
let lines = code.splitLines() |
|||
var linenum = 1 # Starting at index one for line number. |
|||
while linenum <= lines.len: |
|||
let command = lines[linenum - 1].strip() |
|||
case command |
|||
of "Copy": |
|||
if linenum == lines.len: raiseError("missing string to copy.", linenum) |
|||
clipboard.add lines[linenum] |
|||
of "CopyFile": |
|||
if linenum == lines.len: raiseError("missing file to copy from.", linenum) |
|||
let fpath = lines[linenum] |
|||
if fpath == "TheF*ckingCode": |
|||
clipboard.add code |
|||
else: |
|||
let text = try: fpath.readFile() |
|||
except IOError: raiseError("unable to read file “$1”.".format(fpath), linenum) |
|||
clipboard.add text |
|||
of "Duplicate": |
|||
if linenum == lines.len: raiseError("missing number of repetitions.", linenum) |
|||
let n = try: lines[linenum].parseInt() |
|||
except: raiseError("wrong number of repetitions.", linenum + 1) |
|||
clipboard.add repeat(clipboard, n) |
|||
of "Pasta!": |
|||
stdout.write clipboard |
|||
break |
|||
of "": # Empty mine: skip. |
|||
inc linenum |
|||
continue |
|||
else: |
|||
raiseError("unknown command “$1”.".format(command), linenum) |
|||
inc linenum, 2 |
|||
try: |
|||
copyPasta() |
|||
except CopyPastaError: |
|||
quit getCurrentExceptionMsg(), QuitFailure</syntaxhighlight> |
|||
{{out}} |
|||
<strong>File “prog1.cp”:</strong> |
|||
<pre>Copy |
|||
Rosetta Code |
|||
Duplicate |
|||
2 |
|||
Pasta!</pre> |
|||
Result: |
|||
<pre>Rosetta CodeRosetta CodeRosetta Code</pre> |
|||
<strong>File “prog2.cp”:</strong> |
|||
<pre>CopyFile |
|||
pasta.txt |
|||
Duplicate |
|||
1 |
|||
Pasta!</pre> |
|||
Result: |
|||
<pre>I'm the pasta.txt file. |
|||
I'm the pasta.txt file.</pre> |
|||
<strong>File “prog3.cp”:</strong> |
|||
<pre>Copy |
|||
Invalid |
|||
Duplicate |
|||
1 |
|||
Goto |
|||
3 |
|||
Pasta!</pre> |
|||
Result: |
|||
<pre>Line 6: unknown command “Goto”.</pre> |
|||
<strong>File “prog4.cp”:</strong> |
|||
<pre>CopyFile |
|||
TheF*ckingCode |
|||
Pasta!</pre> |
|||
Result: |
|||
<pre>CopyFile |
|||
TheF*ckingCode |
|||
Pasta!</pre> |
|||
<strong>File “prog5.cp”:</strong> |
|||
<pre>Copy |
|||
Rosetta code |
|||
Duplicate |
|||
A |
|||
Pasta!</pre> |
|||
Result: |
|||
<pre>Line 4: wrong number of repetitions.</pre> |
|||
=={{header|Perl}}== |
|||
<syntaxhighlight lang="perl">use strict; |
|||
use warnings; |
|||
use feature 'say'; |
|||
use Path::Tiny; |
|||
sub CopyPasta { |
|||
my($code) = @_; |
|||
my @code = split /\n/, $code =~ s/\s*\n+\s*/\n/gr; |
|||
return "Program never ends!" unless grep { $_ eq 'Pasta!' } @code; |
|||
my @cb; |
|||
my $PC = 0; |
|||
while (1) { |
|||
if ($code[$PC] eq 'Copy') { push @cb, $code[++$PC] } |
|||
elsif ($code[$PC] eq 'CopyFile') { $PC++; push @cb, join ' ', $code[$PC] eq 'TheF*ckingCode' ? @code : path($code[$PC])->slurp } |
|||
elsif ($code[$PC] eq 'Duplicate') { @cb = (@cb) x $code[++$PC] } |
|||
elsif ($code[$PC] eq 'Pasta!') { return @cb } |
|||
else { return "Does not compute: $code[$PC]" } |
|||
$PC++; |
|||
} |
|||
} |
|||
path('pasta.txt')->spew( "I'm the pasta.txt file."); |
|||
for my $prog ( |
|||
"Copy \nRosetta Code\n\tDuplicate\n2\n\nPasta!\nLa Vista", |
|||
"CopyFile\npasta.txt\nDuplicate\n1\nPasta!", |
|||
"Copy\nInvalid\n Duplicate\n1\n\nGoto\n3\nPasta!", |
|||
"CopyFile\nTheF*ckingCode\nDuplicate\n2\nPasta!", |
|||
"Copy\nRosetta Code\nDuplicate\n2\n\nPasta" |
|||
) { |
|||
say for CopyPasta($prog); |
|||
say ''; |
|||
} |
|||
unlink 'pasta.txt';</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Rosetta Code |
|||
Rosetta Code |
|||
I'm the pasta.txt file. |
|||
Does not compute: Goto |
|||
CopyFile TheF*ckingCode Duplicate 2 Pasta! |
|||
CopyFile TheF*ckingCode Duplicate 2 Pasta! |
|||
Program never ends!</pre> |
|||
=={{header|Phix}}== |
|||
Fakes four files so it can be run w/o any fiddly setup, but will handle (differently-named!) real files as well.<br> |
|||
If run without command-line parameters it fakes four runs.<br> |
|||
Assumes if clipboard is "hello ", Duplicate 2 should leave it as "hello hello hello ". |
|||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">prog1_cp</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""" |
|||
Copy |
|||
Rosetta Code |
|||
Duplicate |
|||
2 |
|||
Pasta! |
|||
La Vista |
|||
"""</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">prog2_cp</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""" |
|||
CopyFile |
|||
pasta.txt |
|||
Duplicate |
|||
1 |
|||
Pasta! |
|||
"""</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">prog3_cp</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""" |
|||
Copy |
|||
Invalid |
|||
Duplicate |
|||
1 |
|||
Goto |
|||
3 |
|||
Pasta! |
|||
"""</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">pasta_txt</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""" |
|||
I'm the pasta.txt file. |
|||
"""</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">fake_files</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"prog1.cp"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"prog2.cp"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"prog3.cp"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"pasta.txt"</span><span style="color: #0000FF;">},</span> |
|||
<span style="color: #000000;">fake_texts</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">prog1_cp</span> <span style="color: #0000FF;">,</span> <span style="color: #000000;">prog2_cp</span> <span style="color: #0000FF;">,</span> <span style="color: #000000;">prog3_cp</span> <span style="color: #0000FF;">,</span> <span style="color: #000000;">pasta_txt</span> <span style="color: #0000FF;">}</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">get_file_lines</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">lines</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fake_files</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">lines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fake_texts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span> |
|||
<span style="color: #008080;">or</span> <span style="color: #7060A8;">get_file_type</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)!=</span><span style="color: #004600;">FILETYPE_FILE</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"file not found:%s"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #008080;">else</span> |
|||
<span style="color: #000000;">lines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">get_text</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #004600;">GT_LF_STRIPPED</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">lines</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">interpret</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\ninterpret(%s):\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">pgm</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_file_lines</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)&{</span><span style="color: #008000;">""</span><span style="color: #0000FF;">}</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">clipboard</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">pc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
|||
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">pc</span><span style="color: #0000FF;">>=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pgm</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"No Pasta! Sucha mistaka to maka"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">cmd</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pgm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pc</span><span style="color: #0000FF;">]),</span> <span style="color: #000000;">arg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pgm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pc</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> |
|||
<span style="color: #008080;">switch</span> <span style="color: #000000;">cmd</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #008080;">case</span> <span style="color: #008000;">"Copy"</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">clipboard</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">arg</span><span style="color: #0000FF;">&</span><span style="color: #008000;">"\n"</span> |
|||
<span style="color: #008080;">case</span> <span style="color: #008000;">"CopyFile"</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">clipboard</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">arg</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"TheF*ckingCode"</span><span style="color: #0000FF;">?</span><span style="color: #000000;">pgm</span><span style="color: #0000FF;">:</span><span style="color: #000000;">get_file_lines</span><span style="color: #0000FF;">(</span><span style="color: #000000;">arg</span><span style="color: #0000FF;">)),</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">case</span> <span style="color: #008000;">"Duplicate"</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">clipboard</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">clipboard</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">to_integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">arg</span><span style="color: #0000FF;">)),</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">case</span> <span style="color: #008000;">"Pasta!"</span><span style="color: #0000FF;">:</span> <span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">clipboard</span><span style="color: #0000FF;">);</span> <span style="color: #008080;">return</span> |
|||
<span style="color: #008080;">case</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">pc</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">;</span> <span style="color: #008080;">break</span> <span style="color: #000080;font-style:italic;">-- (skip blank lines [w/o arg])</span> |
|||
<span style="color: #008080;">else</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"unknown command: %s on line %d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">cmd</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pc</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span> |
|||
<span style="color: #000000;">pc</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">2</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">command_line</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #008080;">try</span> |
|||
<span style="color: #000000;">interpret</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"prog%d.cp"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #008080;">catch</span> <span style="color: #000000;">e</span> |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">e</span><span style="color: #0000FF;">[</span><span style="color: #004600;">E_USER</span><span style="color: #0000FF;">]</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">try</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">3</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">interpret</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">])</span> |
|||
<span style="color: #008080;">else</span> |
|||
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"usage: CopyPasta filename"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
|||
<pre> |
|||
interpret(prog1.cp): |
|||
Rosetta Code |
|||
Rosetta Code |
|||
Rosetta Code |
|||
interpret(prog2.cp): |
|||
I'm the pasta.txt file. |
|||
I'm the pasta.txt file. |
|||
interpret(prog3.cp): |
|||
"crash(unknown command: Goto on line 6)" |
|||
interpret(prog4.cp): |
|||
"crash(file not found:prog4.cp)" |
|||
</pre> |
</pre> |
||
=={{header|Python}}== |
=={{header|Python}}== |
||
{{trans|Nanoquery}} |
{{trans|Nanoquery}} |
||
< |
<syntaxhighlight lang="python">import sys |
||
# a function to handle fatal errors |
# a function to handle fatal errors |
||
Line 776: | Line 1,258: | ||
# increment past the command and the next line |
# increment past the command and the next line |
||
loc += 2 |
loc += 2 |
||
</syntaxhighlight> |
|||
</lang> |
|||
The following files were used for testing: |
The following files were used for testing: |
||
Line 837: | Line 1,319: | ||
%error while trying to read from specified file |
%error while trying to read from specified file |
||
usage: copypasta.nq [filename.cp] |
usage: copypasta.nq [filename.cp] |
||
</pre> |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
<syntaxhighlight lang="raku" line>sub CopyPasta ($code) { |
|||
my @code = $code.split("\n")>>.trim.grep: *.so; |
|||
return "Program never ends!" unless grep { $_ eq 'Pasta!' }, @code; |
|||
my @cb; |
|||
my $PC = 0; |
|||
loop { |
|||
given @code[$PC] { |
|||
when 'Copy' { @cb.push: @code[++$PC] } |
|||
when 'CopyFile' { $PC++; @cb.push: @code[$PC] eq 'TheF*ckingCode' ?? @code !! slurp @code[$PC] } |
|||
when 'Duplicate' { @cb = (flat @cb) xx @code[++$PC] } |
|||
when 'Pasta!' { return @cb } |
|||
default { return "Does not compute: @code[$PC]" } |
|||
} |
|||
$PC++; |
|||
} |
|||
} |
|||
spurt 'pasta.txt', "I'm the pasta.txt file."; |
|||
(say $_ for .&CopyPasta; say '') |
|||
for |
|||
"Copy \nRosetta Code\n\tDuplicate\n2\n\nPasta!\nLa Vista", |
|||
"CopyFile\npasta.txt\nDuplicate\n1\nPasta!", |
|||
"Copy\nInvalid\n Duplicate\n1\n\nGoto\n3\nPasta!", |
|||
"CopyFile\nTheF*ckingCode\nDuplicate\n2\nPasta!", |
|||
"Copy\nRosetta Code\nDuplicate\n2\n\nPasta"; |
|||
unlink 'pasta.txt';</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Rosetta Code |
|||
Rosetta Code |
|||
I'm the pasta.txt file. |
|||
Does not compute: Goto |
|||
CopyFile TheF*ckingCode Duplicate 2 Pasta! |
|||
CopyFile TheF*ckingCode Duplicate 2 Pasta! |
|||
Program never ends!</pre> |
|||
=={{header|Wren}}== |
|||
{{trans|Go}} |
|||
<syntaxhighlight lang="wren">import "os" for Platform, Process |
|||
import "io" for File |
|||
var clipboard = "" // don't have access to real thing |
|||
var interpret = Fn.new { |source| |
|||
var source2 = source |
|||
if (Platform.isWindows) source2 = source.replace("\r\n", "\n") |
|||
var lines = source2.split("\n") |
|||
var le = lines.count |
|||
var i = 0 |
|||
while (i < le) { |
|||
lines[i] = lines[i].trim() // ignore leading & trailing whitespace |
|||
if (lines[i] == "Copy") { |
|||
if (i == le - 1) Fiber.abort("There are no lines after the Copy command.") |
|||
i = i + 1 |
|||
clipboard = lines[i] |
|||
} else if (lines[i] == "CopyFile") { |
|||
if (i == le - 1) Fiber.abort("There are no lines after the CopyFile command.") |
|||
i = i + 1 |
|||
if (lines[i] == "TheF*ckingCode") { |
|||
clipboard = source |
|||
} else { |
|||
var s = File.read(lines[i]) |
|||
clipboard = s |
|||
} |
|||
} else if (lines[i] == "Duplicate") { |
|||
if (i == le - 1) Fiber.abort("There are no lines after the Duplicate command.") |
|||
i = i + 1 |
|||
var times = Num.fromString(lines[i]) |
|||
if (times < 0) Fiber.abort("Can't duplicate text a negative number of times.") |
|||
var text = clipboard |
|||
clipboard = text * (times + 1) |
|||
} else if (lines[i] == "Pasta!") { |
|||
var text = clipboard |
|||
System.print(text) |
|||
return |
|||
} else { |
|||
if (lines[i] == "") { |
|||
i = i + 1 |
|||
continue // ignore blank lines |
|||
} |
|||
Fiber.abort("Unknown command, %(lines[i])") |
|||
} |
|||
i = i + 1 |
|||
} |
|||
} |
|||
var args = Process.arguments |
|||
if (args.count != 1) { |
|||
Fiber.abort("There should be exactly one command line argument, the CopyPasta file path.") |
|||
} |
|||
var s = File.read(args[0]) |
|||
interpret.call(s)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Similar to Go entry. |
|||
</pre> |
</pre> |
||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
< |
<syntaxhighlight lang="zkl">var clipBoard=Data(), srcNm=vm.arglist[0]; |
||
pasta:=File(srcNm).read().howza(11); // zkl pastaprog.cp, stripped lines |
pasta:=File(srcNm).read().howza(11); // zkl pastaprog.cp, stripped lines |
||
foreach line in (pasta){ |
foreach line in (pasta){ |
||
Line 871: | Line 1,459: | ||
}catch(TheEnd){ error(w,"Error: End of file: ") } |
}catch(TheEnd){ error(w,"Error: End of file: ") } |
||
catch{ error(w,wantInt and "Not an int: " or "Error: ") } |
catch{ error(w,wantInt and "Not an int: " or "Error: ") } |
||
}</ |
}</syntaxhighlight> |
||
Input programs: |
Input programs: |
||
<pre style="height:15ex"> |
<pre style="height:15ex"> |
Latest revision as of 17:10, 26 May 2024
- Task
Implement a CopyPasta Language interpreter or compiler. These are the commands used by CopyPasta Language:
Command | Description |
---|---|
Copy |
Copy the text of the following line to the clipboard |
CopyFile |
Copy the text of the file cited in the following line to the clipboard or in the case where the next line is TheF*ckingCode copies the code to the clipboard |
Duplicate |
Duplicate the text in the clipboard as many times as the following line specifies |
Pasta! |
Display the clipboard and stop the program |
11l
:start:
V source = File(:argv[1]).read()
V lines = source.split("\n")
V clipboard = ‘’
V loc = 0
L loc < lines.len
V command = lines[loc].trim(‘ ’)
X.try
I (command == ‘Copy’)
clipboard ‘’= lines[loc + 1]
E I (command == ‘CopyFile’)
I (lines[loc + 1] == ‘TheF*ckingCode’)
clipboard ‘’= source
E
V filetext = File(lines[loc + 1]).read()
clipboard ‘’= filetext
E I (command == ‘Duplicate’)
clipboard ‘’= clipboard * ((Int(lines[loc + 1])) - 1)
E I (command == ‘Pasta!’)
print(clipboard)
L.break
E
exit(‘unknown command '’command‘' encountered on line ’(loc + 1))
X.catch
exit(‘error while executing command '’command‘' on line ’(loc + 1))
loc += 2
C++
#include <fstream>
#include <iostream>
#include <sstream>
#include <streambuf>
#include <string>
#include <stdlib.h>
using namespace std;
// a function to handle fatal errors
void fatal_error(string errtext, char *argv[])
{
cout << "%" << errtext << endl;
cout << "usage: " << argv[0] << " [filename.cp]" << endl;
exit(1);
}
// functions to trim strings
// (http://www.martinbroadhurst.com/how-to-trim-a-stdstring.html)
string& ltrim(string& str, const string& chars = "\t\n\v\f\r ")
{
str.erase(0, str.find_first_not_of(chars));
return str;
}
string& rtrim(string& str, const string& chars = "\t\n\v\f\r ")
{
str.erase(str.find_last_not_of(chars) + 1);
return str;
}
string& trim(string& str, const string& chars = "\t\n\v\f\r ")
{
return ltrim(rtrim(str, chars), chars);
}
int main(int argc, char *argv[])
{
// get a filename from the command line and read the file in
string fname = "";
string source = "";
try
{
fname = argv[1];
ifstream t(fname);
t.seekg(0, ios::end);
source.reserve(t.tellg());
t.seekg(0, ios::beg);
source.assign((istreambuf_iterator<char>(t)), istreambuf_iterator<char>());
}
catch(const exception& e)
{
fatal_error("error while trying to read from specified file", argv);
}
// a variable to represent the 'clipboard'
string clipboard = "";
// loop over the lines that were read
int loc = 0;
string remaining = source;
string line = "";
string command = "";
stringstream ss;
while(remaining.find("\n") != string::npos)
{
// check which command is on this line
line = remaining.substr(0, remaining.find("\n"));
command = trim(line);
remaining = remaining.substr(remaining.find("\n") + 1);
try
{
if(line == "Copy")
{
line = remaining.substr(0, remaining.find("\n"));
remaining = remaining.substr(remaining.find("\n") + 1);
clipboard += line;
}
else if(line == "CopyFile")
{
line = remaining.substr(0, remaining.find("\n"));
remaining = remaining.substr(remaining.find("\n") + 1);
if(line == "TheF*ckingCode")
clipboard += source;
else
{
string filetext = "";
ifstream t(line);
t.seekg(0, ios::end);
filetext.reserve(t.tellg());
t.seekg(0, ios::beg);
filetext.assign((istreambuf_iterator<char>(t)), istreambuf_iterator<char>());
clipboard += filetext;
}
}
else if(line == "Duplicate")
{
line = remaining.substr(0, remaining.find("\n"));
remaining = remaining.substr(remaining.find("\n") + 1);
int amount = stoi(line);
string origClipboard = clipboard;
for(int i = 0; i < amount - 1; i++) {
clipboard += origClipboard;
}
}
else if(line == "Pasta!")
{
cout << clipboard << endl;
return 0;
}
else
{
ss << (loc + 1);
fatal_error("unknown command '" + command + "' encounter on line " + ss.str(), argv);
}
}
catch(const exception& e)
{
ss << (loc + 1);
fatal_error("error while executing command '" + command + "' on line " + ss.str(), argv);
}
// increment past the command and the next line
loc += 2;
}
// return in case we never hit a 'Pasta!' statement
return 0;
}
The following files were used for testing:
prog1.cp
Copy Rosetta Code Duplicate 2 Pasta!
prog2.cp
CopyFile pasta.txt Duplicate 1 Pasta!
prog3.cp
Copy Invalid Duplicate 1 Goto 3 Pasta!
prog4.cp
CopyFile TheF*ckingCode Duplicate 2 Pasta!
pasta.txt
I'm the pasta.txt file.
- Output:
$ ./copypasta prog1.cp Rosetta CodeRosetta Code $ ./copypasta prog2.cp I'm the pasta.txt file. $ ./copypasta prog3.cp %unknown command '' encountered on line 5 usage: ./copypasta [filename.cp] $ ./copypasta prog4.cp CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! $ ./copypasta doesntexist.cp %error while trying to read from specified file usage: ./copypasta [filename.cp]
FreeBASIC
Building on Python and Phix solution
' Rosetta Code problem: https://rosettacode.org/wiki/Execute_CopyPasta_Language
' by Jjuanhdez, 05/2024
#define isNumeric(s) Iif(Val(s) = 0 And s <> "0", False, True)
Const As String prog1_cp = "Copy" & Chr(10) & "Rosetta Code" & Chr(10) & "Duplicate" & Chr(10) & "2" & Chr(10) & "Pasta!" & Chr(10) & "La Vista"
Const As String prog2_cp = "CopyFile" & Chr(10) & "pasta.txt" & Chr(10) & "Duplicate" & Chr(10) & "1" & Chr(10) & "Pasta!"
Const As String prog3_cp = "Copy" & Chr(10) & "Invalid" & Chr(10) & " Duplicate" & Chr(10) & "1" & Chr(10) & "Goto" & Chr(10) & "3" & Chr(10) & "Pasta!"
Const As String prog4_cp = "CopyFile" & Chr(10) & "TheF*ckingCode" & Chr(10) & "Duplicate" & Chr(10) & "2" & Chr(10) & "Pasta!"
Const As String prog5_cp = "Copy" & Chr(10) & "Rosetta Code" & Chr(10) & "Duplicate" & Chr(10) & "A" & Chr(10) & "Pasta!"
Const As String doesntexist_cp = ""
Const As String pasta_txt = "The pasta.txt file."
Dim Shared As String prog
Dim Shared As String fake_files(1 To 7)
Dim Shared As String fake_texts(1 To 7)
fake_files(1) = "prog1.cp"
fake_files(2) = "prog2.cp"
fake_files(3) = "prog3.cp"
fake_files(4) = "prog4.cp"
fake_files(5) = "prog5.cp"
fake_files(6) = "doesntexist.cp"
fake_files(7) = "pasta.txt"
fake_texts(1) = prog1_cp
fake_texts(2) = prog2_cp
fake_texts(3) = prog3_cp
fake_texts(4) = prog4_cp
fake_texts(5) = prog5_cp
fake_texts(6) = doesntexist_cp
fake_texts(7) = pasta_txt
Function GetFileLines(Byval filename As String) As String
Dim As String lines, source, linea
Dim As Integer i = 0, k
For k = Lbound(fake_files) To Ubound(fake_files)
If filename = fake_files(k) Then
source = Iif(Command() = "", fake_texts(k), prog)
lines = ""
While i <= Len(source)
linea = ""
While i <= Len(source) And Mid(source, i, 1) <> Chr(10)
linea &= Mid(source, i, 1)
i += 1
Wend
lines &= Trim(linea) & Chr(10)
i += 1
Wend
Exit For
End If
Next
Return lines
End Function
Sub Interpret(Byval filename As String)
Dim As String linea, tmp, cmd, arg
Dim As String pgm = GetFileLines(filename)
Dim As String clipboard = ""
Dim As Integer pc = 1, l = 0
Print "interpret(" & filename & "):"
Do
If pc >= Len(pgm) Then
Print "No Pasta! Sucha mistaka to maka"
Exit Sub
End If
cmd = Trim(Mid(pgm, pc, Instr(pc, pgm, Chr(10)) - pc))
arg = Mid(pgm, pc + Len(cmd) + 1, Instr(pc + Len(cmd) + 1, pgm, Chr(10)) - pc - Len(cmd) - 1)
Select Case cmd
Case "Copy"
clipboard &= arg
l += 4
Case "CopyFile"
Dim As Integer fileNumber = Freefile
If arg = "TheF*ckingCode" Then
Open filename For Input As #fileNumber
Else
Open arg For Input As #fileNumber
If Err > 0 Then Print "Error: Could not open file "; arg
End If
Do While Not Eof(fileNumber)
Line Input #fileNumber, linea
tmp &= linea & Chr(10)
Loop
Close #fileNumber
clipBoard &= tmp
l += 2
Case "Duplicate"
If Not isNumeric(arg) Then
Print "Line " & l & ": wrong number of repetitions."
Exit Do
End If
tmp = ""
For i As Integer = 1 To Val(arg)
tmp &= clipboard
Next
clipboard &= tmp
l += 2
Case "Pasta!"
Print clipboard
Exit Sub
Case ""
pc -= 1
Case Else
Print "Line " & l & ": unknown command """ & cmd & """"
Exit Sub
End Select
pc += Len(cmd) + Len(arg) + 2
Loop
End Sub
Sub Main()
Dim As String cad, cl = Command()
Dim As Integer ff = Freefile
If cl <> "" Then
If Open(cl For Input As #ff) = 0 Then
While Not Eof(ff)
Line Input #ff, cad
prog &= Trim(cad) & Chr(10)
Wend
Close #ff
Else
Print "Error: Could not open file "; cl
Exit Sub
End If
Interpret(cl)
Else
For i As Integer = Lbound(fake_files) To Ubound(fake_files)-1
Interpret("prog" & (i) & ".cp")
Print
Next
End If
End Sub
Main()
Sleep
- Output:
interpret(prog1.cp): Rosetta CodeRosetta CodeRosetta Code interpret(prog2.cp): I'm the pasta.txt file. I'm the pasta.txt file. interpret(prog3.cp): Line 6: unknown command "Goto" interpret(prog4.cp): CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! interpret(prog5.cp): Line 4: wrong number of repetitions. interpret(prog6.cp): Error: Could not open file doesntexist.cp
Go
Here's my tentative attempt at an interpreter for CopyPasta.
I've made the following assumptions:
1. The program to be interpreted is read in from a file whose path is supplied as a command line argument.
2. Writing to the clipboard should always overwrite what (if anything) is already in the clipboard and not append to it.
3. CopyPasta is case sensitive.
4. When writing commands, leading and trailing whitespace should be ignored.
5. Blank commands should be ignored.
6. When a command consumes the following line, that line should not be reprocessed if it is a command itself.
7. The program should terminate with a suitable message if any error is encountered (i.e. no following line, file doesn't exist etc.).
8. When the program is about to end and the contents of the clipboard have (when appropriate) been printed out, the clipboard should be cleared.
// copypasta.go
package main
import (
"fmt"
"github.com/atotto/clipboard"
"io/ioutil"
"log"
"os"
"runtime"
"strconv"
"strings"
)
func check(err error) {
if err != nil {
clipboard.WriteAll("") // clear clipboard
log.Fatal(err)
}
}
func interpret(source string) {
source2 := source
if runtime.GOOS == "windows" {
source2 = strings.ReplaceAll(source, "\r\n", "\n")
}
lines := strings.Split(source2, "\n")
le := len(lines)
for i := 0; i < le; i++ {
lines[i] = strings.TrimSpace(lines[i]) // ignore leading & trailing whitespace
switch lines[i] {
case "Copy":
if i == le-1 {
log.Fatal("There are no lines after the Copy command.")
}
i++
err := clipboard.WriteAll(lines[i])
check(err)
case "CopyFile":
if i == le-1 {
log.Fatal("There are no lines after the CopyFile command.")
}
i++
if lines[i] == "TheF*ckingCode" {
err := clipboard.WriteAll(source)
check(err)
} else {
bytes, err := ioutil.ReadFile(lines[i])
check(err)
err = clipboard.WriteAll(string(bytes))
check(err)
}
case "Duplicate":
if i == le-1 {
log.Fatal("There are no lines after the Duplicate command.")
}
i++
times, err := strconv.Atoi(lines[i])
check(err)
if times < 0 {
log.Fatal("Can't duplicate text a negative number of times.")
}
text, err := clipboard.ReadAll()
check(err)
err = clipboard.WriteAll(strings.Repeat(text, times+1))
check(err)
case "Pasta!":
text, err := clipboard.ReadAll()
check(err)
fmt.Println(text)
return
default:
if lines[i] == "" {
continue // ignore blank lines
}
log.Fatal("Unknown command, " + lines[i])
}
}
}
func main() {
if len(os.Args) != 2 {
log.Fatal("There should be exactly one command line argument, the CopyPasta file path.")
}
bytes, err := ioutil.ReadFile(os.Args[1])
check(err)
interpret(string(bytes))
err = clipboard.WriteAll("") // clear clipboard
check(err)
}
- Output:
The following files have been used for testing:
// prog.cp Copy Rosetta Code Duplicate 2 Pasta! // prog2.cp CopyFile pasta.txt Duplicate 1 Pasta! // prog3.txt Copy Invalid Duplicate 1 Goto 3 Pasta! // pasta.txt I'm the pasta.txt file.
With the following results:
$ go build copypasta.go $ ./copypasta There should be exactly one command line argument, the CopyPasta file path. $ ./copypasta prog4.cp open prog4.cp: no such file or directory $ ./copypasta prog.cp Rosetta CodeRosetta CodeRosetta Code $ ./copypasta prog2.cp I'm the pasta.txt file. I'm the pasta.txt file. $ ./copypasta prog3.cp Unknown command, Goto
Java
import java.io.File;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
public class Copypasta
{
// a function to handle fatal errors
public static void fatal_error(String errtext)
{
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
StackTraceElement main = stack[stack.length - 1];
String mainClass = main.getClassName();
System.out.println("%" + errtext);
System.out.println("usage: " + mainClass + " [filename.cp]");
System.exit(1);
}
public static void main(String[] args)
{
// get a filename from the command line and read the file in
String fname = null;
String source = null;
try
{
fname = args[0];
source = new String(Files.readAllBytes(new File(fname).toPath()));
}
catch(Exception e)
{
fatal_error("error while trying to read from specified file");
}
// convert the source to lines of code
ArrayList<String> lines = new ArrayList<String>(Arrays.asList(source.split("\n")));
// a variable to represent the 'clipboard'
String clipboard = "";
// loop over the lines that were read
int loc = 0;
while(loc < lines.size())
{
// check which command is on this line
String command = lines.get(loc).trim();
try
{
if(command.equals("Copy"))
clipboard += lines.get(loc + 1);
else if(command.equals("CopyFile"))
{
if(lines.get(loc + 1).equals("TheF*ckingCode"))
clipboard += source;
else
{
String filetext = new String(Files.readAllBytes(new File(lines.get(loc + 1)).toPath()));
clipboard += filetext;
}
}
else if(command.equals("Duplicate"))
{
String origClipboard = clipboard;
int amount = Integer.parseInt(lines.get(loc + 1)) - 1;
for(int i = 0; i < amount; i++)
clipboard += origClipboard;
}
else if(command.equals("Pasta!"))
{
System.out.println(clipboard);
System.exit(0);
}
else
fatal_error("unknown command '" + command + "' encountered on line " + new Integer(loc + 1).toString());
}
catch(Exception e)
{
fatal_error("error while executing command '" + command + "' on line " + new Integer(loc + 1).toString());
}
// increment past the command and the next line
loc += 2;
}
}
}
The following files were used for testing:
prog1.cp
Copy Rosetta Code Duplicate 2 Pasta!
prog2.cp
CopyFile pasta.txt Duplicate 1 Pasta!
prog3.cp
Copy Invalid Duplicate 1 Goto 3 Pasta!
prog4.cp
CopyFile TheF*ckingCode Duplicate 2 Pasta!
pasta.txt
I'm the pasta.txt file.
- Output:
$ java Copypasta prog1.cp Rosetta CodeRosetta Code $ java Copypasta prog2.cp I'm the pasta.txt file. $ java Copypasta prog3.cp %unknown command '' encountered on line 5 usage: Copypasta [filename.cp] $ java Copypasta prog4.cp CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! $ java Copypasta doesntexist.cp %error while trying to read from specified file usage: Copypasta [filename.cp]
Julia
function interpretCopyPasta()
clipboard = String[]
if isempty(ARGS)
println("Usage: interpretcopypasta <filename>")
exit(1)
end
thecode = read(ARGS[1], String)
codelines = String.(strip.(split(thecode, "\n")))
nextline() = popfirst!(codelines)
Copy() = push!(clipboard, nextline())
function CopyFile()
txt = nextline()
push!(clipboard, txt == "TheF*ckingCode" ? thecode : read(txt, String))
end
function Duplicate()
ncopies, txt = parse(Int, nextline()), copy(clipboard)
clipboard = foldl(vcat, [txt for _ in 1:ncopies])
end
Pasta!() = (for t in clipboard, x in split(t, "\n") println(x) end; exit(0))
commands = Dict("Copy" => Copy, "CopyFile" => CopyFile,
"Duplicate" => Duplicate, "Pasta!" => Pasta!)
while !isempty(codelines)
line = nextline()
if haskey(commands, line)
commands[line]()
end
end
end
interpretCopyPasta()
- Output:
If run on the following CopyPasta "code" file:
Copy Beginning this run. CopyFile TheF*ckingCode Duplicate 2 Copy Ending this run. Pasta!
The output is:
Beginning this run. Copy Beginning this run. CopyFile TheF*ckingCode Duplicate 2 Copy Ending this run. Pasta! Beginning this run. Copy Beginning this run. CopyFile TheF*ckingCode Duplicate 2 Copy Ending this run. Pasta! Ending this run.
Nanoquery
// a function to handle fatal errors
def fatal_error(errtext)
println "%" + errtext
println "usage: " + args[1] + " [filename.cp]"
exit(1)
end
// get a filename from the command line and read the file in
fname = null
source = null
try
fname = args[2]
source = new(Nanoquery.IO.File, fname).readAll()
catch
fatal_error("error while trying to read from specified file")
end
// convert the source to lines of code
lines = split(source, "\n")
// a variable to represent the 'clipboard'
clipboard = ""
// loop over the lines that were read
loc = 0
while (loc < len(lines))
// check which command is on this line
command = trim(lines[loc])
try
if (command = "Copy")
clipboard += lines[loc + 1]
else if (command = "CopyFile")
if (lines[loc + 1] = "TheF*ckingCode")
clipboard += source
else
filetext = new(Nanoquery.IO.File, lines[loc + 1]).readAll()
clipboard += filetext
end
else if (command = "Duplicate")
clipboard += clipboard * ((int(lines[loc + 1])) - 1)
else if (command = "Pasta!")
println clipboard
exit
else
fatal_error("unknown command '" + command + "' encountered on line " + (loc + 1))
end
catch
fatal_error("error while executing command '" + command + "' on line " + (loc + 1))
end
// increment past the command and the next line
loc += 2
end
The following files were used for testing:
prog1.cp
Copy Rosetta Code Duplicate 2 Pasta!
prog2.cp
CopyFile pasta.txt Duplicate 1 Pasta!
prog3.cp
Copy Invalid Duplicate 1 Goto 3 Pasta!
prog4.cp
CopyFile TheF*ckingCode Duplicate 2 Pasta!
pasta.txt
I'm the pasta.txt file.
- Output:
$ java -jar ../nanoquery-2.3_1845.jar -b copypasta.nq prog1.cp Rosetta CodeRosetta Code $ java -jar ../nanoquery-2.3_1845.jar -b copypasta.nq prog2.cp I'm the pasta.txt file. $ java -jar ../nanoquery-2.3_1845.jar -b copypasta.nq prog3.cp %unknown command '' encountered on line 5 usage: copypasta.nq [filename.cp] $ java -jar ../nanoquery-2.3_1845.jar -b copypasta.nq prog4.cp CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! $ java -jar ../nanoquery-2.3_1845.jar -b copypasta.nq doesntexist.cp %error while trying to read from specified file usage: copypasta.nq [filename.cp]
Nim
import os, strutils
type CopyPastaError = object of CatchableError
template raiseError(message: string, linenum = 0) =
let prefix = if linenum != 0: "Line $1: ".format(linenum) else: ""
raise newException(CopyPastaError, prefix & message)
proc copyPasta() =
## Load and execute a program.
var clipboard: string
if paramCount() != 1:
echo "usage: ", getAppFilename().lastPathPart, " filename.cp"
quit QuitFailure
let path = paramStr(1)
let code = try: path.readFile()
except IOError: raiseError("Unable to read file “$1”.".format(path))
let lines = code.splitLines()
var linenum = 1 # Starting at index one for line number.
while linenum <= lines.len:
let command = lines[linenum - 1].strip()
case command
of "Copy":
if linenum == lines.len: raiseError("missing string to copy.", linenum)
clipboard.add lines[linenum]
of "CopyFile":
if linenum == lines.len: raiseError("missing file to copy from.", linenum)
let fpath = lines[linenum]
if fpath == "TheF*ckingCode":
clipboard.add code
else:
let text = try: fpath.readFile()
except IOError: raiseError("unable to read file “$1”.".format(fpath), linenum)
clipboard.add text
of "Duplicate":
if linenum == lines.len: raiseError("missing number of repetitions.", linenum)
let n = try: lines[linenum].parseInt()
except: raiseError("wrong number of repetitions.", linenum + 1)
clipboard.add repeat(clipboard, n)
of "Pasta!":
stdout.write clipboard
break
of "": # Empty mine: skip.
inc linenum
continue
else:
raiseError("unknown command “$1”.".format(command), linenum)
inc linenum, 2
try:
copyPasta()
except CopyPastaError:
quit getCurrentExceptionMsg(), QuitFailure
- Output:
File “prog1.cp”:
Copy Rosetta Code Duplicate 2 Pasta!
Result:
Rosetta CodeRosetta CodeRosetta Code
File “prog2.cp”:
CopyFile pasta.txt Duplicate 1 Pasta!
Result:
I'm the pasta.txt file. I'm the pasta.txt file.
File “prog3.cp”:
Copy Invalid Duplicate 1 Goto 3 Pasta!
Result:
Line 6: unknown command “Goto”.
File “prog4.cp”:
CopyFile TheF*ckingCode Pasta!
Result:
CopyFile TheF*ckingCode Pasta!
File “prog5.cp”:
Copy Rosetta code Duplicate A Pasta!
Result:
Line 4: wrong number of repetitions.
Perl
use strict;
use warnings;
use feature 'say';
use Path::Tiny;
sub CopyPasta {
my($code) = @_;
my @code = split /\n/, $code =~ s/\s*\n+\s*/\n/gr;
return "Program never ends!" unless grep { $_ eq 'Pasta!' } @code;
my @cb;
my $PC = 0;
while (1) {
if ($code[$PC] eq 'Copy') { push @cb, $code[++$PC] }
elsif ($code[$PC] eq 'CopyFile') { $PC++; push @cb, join ' ', $code[$PC] eq 'TheF*ckingCode' ? @code : path($code[$PC])->slurp }
elsif ($code[$PC] eq 'Duplicate') { @cb = (@cb) x $code[++$PC] }
elsif ($code[$PC] eq 'Pasta!') { return @cb }
else { return "Does not compute: $code[$PC]" }
$PC++;
}
}
path('pasta.txt')->spew( "I'm the pasta.txt file.");
for my $prog (
"Copy \nRosetta Code\n\tDuplicate\n2\n\nPasta!\nLa Vista",
"CopyFile\npasta.txt\nDuplicate\n1\nPasta!",
"Copy\nInvalid\n Duplicate\n1\n\nGoto\n3\nPasta!",
"CopyFile\nTheF*ckingCode\nDuplicate\n2\nPasta!",
"Copy\nRosetta Code\nDuplicate\n2\n\nPasta"
) {
say for CopyPasta($prog);
say '';
}
unlink 'pasta.txt';
- Output:
Rosetta Code Rosetta Code I'm the pasta.txt file. Does not compute: Goto CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! Program never ends!
Phix
Fakes four files so it can be run w/o any fiddly setup, but will handle (differently-named!) real files as well.
If run without command-line parameters it fakes four runs.
Assumes if clipboard is "hello ", Duplicate 2 should leave it as "hello hello hello ".
with javascript_semantics constant prog1_cp = """ Copy Rosetta Code Duplicate 2 Pasta! La Vista """, prog2_cp = """ CopyFile pasta.txt Duplicate 1 Pasta! """, prog3_cp = """ Copy Invalid Duplicate 1 Goto 3 Pasta! """, pasta_txt = """ I'm the pasta.txt file. """, fake_files = {"prog1.cp","prog2.cp","prog3.cp","pasta.txt"}, fake_texts = { prog1_cp , prog2_cp , prog3_cp , pasta_txt } function get_file_lines(string filename) sequence lines integer k = find(filename,fake_files) if k then lines = split(fake_texts[k],"\n",false) elsif platform()=JS or get_file_type(filename)!=FILETYPE_FILE then crash("file not found:%s",{filename}) else lines = get_text(filename,GT_LF_STRIPPED) end if return lines end function procedure interpret(string filename) printf(1,"\ninterpret(%s):\n",{filename}) sequence pgm = get_file_lines(filename)&{""} string clipboard = "" integer pc = 1 while true do if pc>=length(pgm) then crash("No Pasta! Sucha mistaka to maka") end if string cmd = trim(pgm[pc]), arg = pgm[pc+1] switch cmd do case "Copy": clipboard &= arg&"\n" case "CopyFile": clipboard &= join(iff(arg="TheF*ckingCode"?pgm:get_file_lines(arg)),"\n") case "Duplicate": clipboard &= join(repeat(clipboard,to_integer(arg)),"") case "Pasta!": puts(1,clipboard); return case "": pc -= 1; break -- (skip blank lines [w/o arg]) else crash("unknown command: %s on line %d",{cmd,pc}) end switch pc += 2 end while end procedure procedure main() sequence cl = command_line() if length(cl)=2 then for i=1 to 4 do try interpret(sprintf("prog%d.cp",i)) catch e ?e[E_USER] end try end for elsif length(cl)=3 then interpret(cl[3]) else crash("usage: CopyPasta filename") end if end procedure main()
- Output:
interpret(prog1.cp): Rosetta Code Rosetta Code Rosetta Code interpret(prog2.cp): I'm the pasta.txt file. I'm the pasta.txt file. interpret(prog3.cp): "crash(unknown command: Goto on line 6)" interpret(prog4.cp): "crash(file not found:prog4.cp)"
Python
import sys
# a function to handle fatal errors
def fatal_error(errtext):
print("%" + errtext)
print("usage: " + sys.argv[0] + " [filename.cp]")
sys.exit(1)
# get a filename from the command line and read the file in
fname = None
source = None
try:
fname = sys.argv[1]
source = open(fname).read()
except:
fatal_error("error while trying to read from specified file")
# convert the source to lines of code
lines = source.split("\n")
# a variable to represent the 'clipboard'
clipboard = ""
# loop over the lines that were read
loc = 0
while(loc < len(lines)):
# check which command is on this line
command = lines[loc].strip()
try:
if(command == "Copy"):
clipboard += lines[loc + 1]
elif(command == "CopyFile"):
if(lines[loc + 1] == "TheF*ckingCode"):
clipboard += source
else:
filetext = open(lines[loc+1]).read()
clipboard += filetext
elif(command == "Duplicate"):
clipboard += clipboard * ((int(lines[loc + 1])) - 1)
elif(command == "Pasta!"):
print(clipboard)
sys.exit(0)
else:
fatal_error("unknown command '" + command + "' encountered on line " + str(loc + 1))
except Exception as e:
fatal_error("error while executing command '" + command + "' on line " + str(loc + 1) + ": " + e)
# increment past the command and the next line
loc += 2
The following files were used for testing:
prog1.cp
Copy Rosetta Code Duplicate 2 Pasta!
prog2.cp
CopyFile pasta.txt Duplicate 1 Pasta!
prog3.cp
Copy Invalid Duplicate 1 Goto 3 Pasta!
prog4.cp
CopyFile TheF*ckingCode Duplicate 2 Pasta!
pasta.txt
I'm the pasta.txt file.
- Output:
$ python3 copypasta.py prog1.cp Rosetta CodeRosetta Code $ python3 copypasta.py prog2.cp I'm the pasta.txt file. $ python3 copypasta.py prog3.cp %unknown command '' encountered on line 5 usage: copypasta.nq [filename.cp] $ python3 copypasta.py prog4.cp CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! $ python3 copypasta.py doesntexist.cp %error while trying to read from specified file usage: copypasta.nq [filename.cp]
Raku
(formerly Perl 6)
sub CopyPasta ($code) {
my @code = $code.split("\n")>>.trim.grep: *.so;
return "Program never ends!" unless grep { $_ eq 'Pasta!' }, @code;
my @cb;
my $PC = 0;
loop {
given @code[$PC] {
when 'Copy' { @cb.push: @code[++$PC] }
when 'CopyFile' { $PC++; @cb.push: @code[$PC] eq 'TheF*ckingCode' ?? @code !! slurp @code[$PC] }
when 'Duplicate' { @cb = (flat @cb) xx @code[++$PC] }
when 'Pasta!' { return @cb }
default { return "Does not compute: @code[$PC]" }
}
$PC++;
}
}
spurt 'pasta.txt', "I'm the pasta.txt file.";
(say $_ for .&CopyPasta; say '')
for
"Copy \nRosetta Code\n\tDuplicate\n2\n\nPasta!\nLa Vista",
"CopyFile\npasta.txt\nDuplicate\n1\nPasta!",
"Copy\nInvalid\n Duplicate\n1\n\nGoto\n3\nPasta!",
"CopyFile\nTheF*ckingCode\nDuplicate\n2\nPasta!",
"Copy\nRosetta Code\nDuplicate\n2\n\nPasta";
unlink 'pasta.txt';
- Output:
Rosetta Code Rosetta Code I'm the pasta.txt file. Does not compute: Goto CopyFile TheF*ckingCode Duplicate 2 Pasta! CopyFile TheF*ckingCode Duplicate 2 Pasta! Program never ends!
Wren
import "os" for Platform, Process
import "io" for File
var clipboard = "" // don't have access to real thing
var interpret = Fn.new { |source|
var source2 = source
if (Platform.isWindows) source2 = source.replace("\r\n", "\n")
var lines = source2.split("\n")
var le = lines.count
var i = 0
while (i < le) {
lines[i] = lines[i].trim() // ignore leading & trailing whitespace
if (lines[i] == "Copy") {
if (i == le - 1) Fiber.abort("There are no lines after the Copy command.")
i = i + 1
clipboard = lines[i]
} else if (lines[i] == "CopyFile") {
if (i == le - 1) Fiber.abort("There are no lines after the CopyFile command.")
i = i + 1
if (lines[i] == "TheF*ckingCode") {
clipboard = source
} else {
var s = File.read(lines[i])
clipboard = s
}
} else if (lines[i] == "Duplicate") {
if (i == le - 1) Fiber.abort("There are no lines after the Duplicate command.")
i = i + 1
var times = Num.fromString(lines[i])
if (times < 0) Fiber.abort("Can't duplicate text a negative number of times.")
var text = clipboard
clipboard = text * (times + 1)
} else if (lines[i] == "Pasta!") {
var text = clipboard
System.print(text)
return
} else {
if (lines[i] == "") {
i = i + 1
continue // ignore blank lines
}
Fiber.abort("Unknown command, %(lines[i])")
}
i = i + 1
}
}
var args = Process.arguments
if (args.count != 1) {
Fiber.abort("There should be exactly one command line argument, the CopyPasta file path.")
}
var s = File.read(args[0])
interpret.call(s)
- Output:
Similar to Go entry.
zkl
var clipBoard=Data(), srcNm=vm.arglist[0];
pasta:=File(srcNm).read().howza(11); // zkl pastaprog.cp, stripped lines
foreach line in (pasta){
switch(line.toLower()){
case("copy"){ clipBoard.clear(next(__lineWalker),"\n") }
case("copyfile"){
n:=next(__lineWalker);
if(n=="TheF*ckingCode") clipBoard.clear(pasta);
else clipBoard.clear(File(n).read());
}
case("duplicate"){
n,t := next(__lineWalker,True), clipBoard.copy();
do(n){ t.append(clipBoard) } // noop if n<1
clipBoard=t;
}
case("pasta!"){ print(clipBoard.text); break; }
case(""){}
else{ error(__lineWalker,"Unknown command: ") }
}
}
fcn error(w,msg){
println("%s: %d: %s%s".fmt(srcNm, w.n, msg, w.value));
System.exit(1)
}
fcn next(w,wantInt=False){
try{
t:=w.next();
if(wantInt) t=t.toInt();
return(t)
}catch(TheEnd){ error(w,"Error: End of file: ") }
catch{ error(w,wantInt and "Not an int: " or "Error: ") }
}
Input programs:
//////////////prog.cp: Copy Rosetta Code Duplicate 2 Pasta! //////////////prog2.cp: CopyFile pasta.txt Duplicate 1 Pasta! /////////prog3.cp: Copy Invalid Duplicate 1 Goto 3 Pasta! //////////////pasta.txt: I'm the pasta.txt file.
- Output:
$ zkl copyPasta.zkl prog.cp Rosetta Code Rosetta Code Rosetta Code $ zkl copyPasta.zkl prog2.cp I'm the pasta.txt file. I'm the pasta.txt file. $ zkl copyPasta.zkl prog3.cp prog3.cp: 6: Unknown command: Goto