# 编写Clem解释器

11

Clem是一种基于堆栈的最小编程语言，具有一流的功能。您的目标是为Clem语言编写一个解释器。它应正确执行参考实现中包含的所有示例，可从此处获得

• 像往常一样，存在标准漏洞
• 按字节数最小的条目获胜。

## 克莱姆语言

Clem是具有一流功能的基于堆栈的编程语言。学习Clem的最好方法是`clem`不带参数地运行解释器。它将以交互模式启动，使您可以使用可用的命令进行播放。要运行示例程序，请键入`clem example.clm`where example是程序的名称。这个简短的教程应该足以让您入门。

## 原子功能

``````> -10
001: (-10)
>
``````

``````> +11
002: (-10)
001: (11)
>
``````

``````@  Rotate the top three functions on the stack
#  Pop the function on top of the stack and push it twice
\$  Swap the top two functions on top of the stack
%  Pop the function on top of the stack and throw it away
/  Pop a compound function. Split off the first function, push what's left,
then push the first function.
.  Pop two functions, concatenate them and push the result
+  Pop a function. If its a constant then increment it. Push it
-  Pop a function. If its a constant then decrement it. Push it
<  Get a character from STDIN and push it to the stack. Pushes -1 on EOF.
>  Pop a function and print its ASCII character if its a constant
c  Pop a function and print its value if its a constant
w  Pop a function from the stack. Peek at the top of the stack. While it is
a non-zero constant, execute the function.
``````

``````> #
003: (-10)
002: (11)
001: (11)
>
``````

``````> %
002: (-10)
001: (11)
>
``````

``````> (-)
003: (-10)
002: (11)
001: (-)
>
``````

## 复合功能

``````> (\$+\$)
004: (-10)
003: (11)
002: (-)
001: (\$ + \$)
>
``````

``````> .
003: (-10)
002: (11)
001: (- \$ + \$)
>
``````

``````> w
002: (1)
001: (0)
>
``````

``````> %10
002: (1)
001: (10)
>
``````

``````> (-\$+\$)w%
001: (11)
>
``````

（请注意，该算法仅在堆栈上的第一个常数为正数时有效）。

## 弦乐

``````> 0 10 "Hi!"
005: (0)
004: (10)
003: (33)
002: (105)
001: (72)
>
``````

``````> (>)w
Hi!
001: (0)
>
``````

## 结论

Clem的esolangs.org页面

C中的参考实现

COTO 2014年

@COTO是正确的。我创建了语言。
Orby 2014年

5

Martin Ender 2014年

4
@MartinBüttner：“ klem” :)
Orby

2

002-

Answers:

1

# 哈斯克尔（931） 921 875

``````import Text.Parsec
import Control.Monad.State
import Control.Monad.Trans.Class
import Data.Char
'#'%(x:y)=x:x:y
'%'%(x:y)=y
'@'%(x:y:z:w)=y:z:x:w
'\$'%(x:y:z)=y:x:z
'/'%((a:b):s)=[a]:b:s
'+'%(a:b)=i a(show.succ)a:b
'.'%(a:b:c)=(a++b):c
_%x=x
b=concat&between(s"(")(s")")(many\$many1(noneOf"()")<|>('(':)&((++")")&b))
e=choice[s"w">>c(do p<-t;let d=h>>= \x->if x=="0"then a else u p>>d in d),m&k,s"-">>(m&(' ':)&k<|>c(o(\(a:b)->i a(show.pred)a:b))),s"c">>c(do
d<-t
i d(j.putStr.show)a),o&(++)&map(show.ord)&between(s"\"")(s"\"")(many\$noneOf"\""),(do
s"<"
c\$j getChar>>=m.show.ord),(do
s">"
c\$do
g<-t
i g(j.putChar.chr)a),m&b,o&(%)&anyChar]
k=many1 digit
i s f g|(reads s::[(Int,String)])>[]=f\$(read s::Int)|0<1=g
t=h>>=(o tail>>).c
c n=return n
a=c()
h=head&get
(&)f=fmap f
m=o.(:)
o=modify
u=(\(Right r)->r).parse(sequence_&many e)""
r=(`runStateT`[]).u
s=string
j=lift
``````

5

# Python，1684 1281个字符

``````import sys,os,copy as C
L=len
S=[]
n=[S]
Q=lambda:S and S.pop()or 0
def P(o):
if o:n[0].append(o)
def X():x=Q();P(x);P(C.deepcopy(x))
def W():S[-2::]=S[-1:-3:-1]
def R():a,b,c=Q(),Q(),Q();P(a);P(c);P(b)
def A(d):
a=Q()
if a and a[0]:a=[1,a[1]+d,lambda:P(a)]
P(a)
def V():
a=Q();P(a)
if a and a[0]-1and L(a[2])>1:r=a[2].pop(0);P(r)
def T():
b,a=Q(),Q()
if a!=b:P([0,0,(a[2],[a])[a[0]]+(b[2],[b])[b[0]]])
else:P(a);P(b)
def r():a=os.read(0,1);F(ord(a)if a else-1)
def q(f):
a=Q()
if a and a[0]:os.write(1,(chr(a[1]%256),str(a[1]))[f])
def e(f,x=0):f[2]()if f[0]+f[1]else([e(z)for z in f[2]]if x else P(f))
def w():
a=Q()
while a and S and S[-1][0]and S[-1][1]:e(a,1)
def Y():n[:0]=[[]]
def Z():
x=n.pop(0)
if x:n[0]+=([[0,0,x]],x)[L(x)+L(n)==2]
D={'%':Q,'#':X,'\$':W,'@':R,'+':lambda:A(1),'-':lambda:A(-1),'/':V,'.':T,'<':r,'>':lambda:q(0),'c':lambda:q(1),'w':w,'(':Y,')':Z}
def g(c):D[c]()if L(n)<2or c in'()'else P([0,1,D[c]])
N=['']
def F(x):a=[1,x,lambda:P(a)];a[2]()
def E():
if'-'==N[0]:g('-')
elif N[0]:F(int(N[0]))
N[0]=''
s=j=""
for c in open(sys.argv[1]).read()+' ':
if j:j=c!="\n"
elif'"'==c:E();s and map(F,map(ord,s[:0:-1]));s=(c,'')[L(s)>0]
elif s:s+=c
elif';'==c:E();j=1
else:
if'-'==c:E()
if c in'-0123456789':N[0]+=c
else:E();c in D and g(c)
``````

clemint.pyclemtest_data.pyclemtest.py和已编译的`clem`二进制文件收集到目录中并运行`clemtest.py`

`S`是主堆栈。堆栈中的每个项目都是一个3列表，其中之一：

``````Constant: [1, value, f]
Atomic: [0, 1, f]
Compound: [0, 0, fs]
``````

`xec`执行一个项目。如果它是常量或原子，则仅执行该函数。如果是复合的话，如果还没有递归，它将执行每个函数。因此，执行`(10 20 - 30)`将执行每个功能`10``20``-`，和`30`，留`10 19 30`在堆栈上。如果有递归，那么它只是将复合函数推入堆栈。例如，执行时`(10 20 (3 4) 30)`，结果应为`10 20 (3 4) 30`而不是`10 20 3 4 30`

Orby

@Orby：我当然做到了！这是一种有趣的语言，绝对是一种奇怪的语言。我希望我能得到一个<1k的口译员。不确定其他提交内容会带来什么。
Claudiu 2014年

4

# C 837

``````#define Q strcpy
#define F(x)bcopy(b,f,p-b);f[p-b-x]=!Q(r,p);
#define C(x,y)Q(S[s-x],S[s-y]);
#define N[9999]
#define A Q(S[s++]
#define D sprintf(S[s++],"%d"
#define G(x)}if(*f==x){
#define H(x)G(x)s--;
#define R return
#define Z(x)T(t,u,v)-1||putchar(x);H(
char S N N;s;c;T(b,f,r)char*b,*f,*r;{char*p;strtol(b+=strspn(b," "),&p,0);if(p>b){F(0)R 1;}if(c=*b==40){for(p=++b;c;)c+=(*p==40)-(*p++==41);F(1)R-1;}p++;F(0)*r*=!!*b;R 0;}*P(char*p){if(*p==34)R++p;char*r=P(p+1);D,*p);R r;}E(char*x){char*p,c N,f N,r N,t N,u N,v N;for(Q(c,x);*c;Q(c,p)){Q(t,S[s-1]);if(T(c,f,p=r))A,f);else{{G(64)C(0,1)C(1,2)C(2,3)C(3,0)G(35)A,t);G(36)C(0,2)C(2,1)C(1,0)H(37)H(47)T(t,u,v);*v&&A,v);A,u);H(46)strcat(strcat(S[s-1]," "),t);H(43)D,atoi(t)+1);H(45)D,atoi(t)-1);G(60)D,getchar());H(62)Z(atoi(u))99)Z(*u)119)for(Q(u,t);atoi(S[s-1]);)E(u);G(34)p=P(p);}}}}
``````

``````#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define FIRST_REST(x) memcpy(first, b, p - b); first[p - b - x] = '\0'; strcpy(rest, p);
#define COPY(dest,src) strcpy(stack[size + dest], stack[size + src]);
char stack[9999][9999]; int size = 0;
int token(char *b, char *first, char *rest)
{
while (*b == 32) b++;
char *p; int x = strtol(b, &p, 0);
if (p > b) { FIRST_REST(0) return 1; }
if (*b == '(') { int c = 1; for (p = ++b; c; ++p) c += (*p == '(') - (*p == ')'); FIRST_REST(1) return -1; }
p++; FIRST_REST(0) if (!*b) *rest = '\0'; return 0;
}
char *push(char *pointer)
{
if (*pointer == '\"') return pointer+1;
char *result = push(pointer+1);
sprintf(stack[size++], "%d", *pointer);
return result;
}
void eval(char *x)
{
char program[9999], first[9999], rest[9999], tos[9999], tmp1[9999], tmp2[9999];
char *pointer;
for (strcpy(program, x); *program; strcpy(program, pointer))
{
*stack[size] = '\0';
strcpy(tos, stack[size-1]);
if (token(program, first, rest))
{
pointer = rest;
strcpy(stack[size++], first);
}
else
{
pointer = rest;
if (*first == '@'){
COPY(0, -1) COPY(-1, -2) COPY(-2, -3) COPY(-3, 0) }
if (*first == '#')
strcpy(stack[size++], tos);
if (*first == '\$'){
COPY(0, -2) COPY(-2, -1) COPY(-1, 0) }
if (*first == '%')
size--;
if (*first == '/'){
size--; token(tos, tmp1, tmp2); if (*tmp2) strcpy(stack[size++], tmp2); strcpy(stack[size++], tmp1); }
if (*first == '.'){
size--; strcat(stack[size - 1], " "); strcat(stack[size - 1], tos); }
if (*first == '+'){
size--; sprintf(stack[size++], "%d", atoi(tos) + 1); }
if (*first == '-'){
size--; sprintf(stack[size++], "%d", atoi(tos) - 1); }
if (*first == '<')
sprintf(stack[size++], "%d", getchar());
if (*first == '>'){
size--; if (token(tos, tmp1, tmp2) == 1) putchar(atoi(tmp1)); }
if (*first == 'c'){
size--; if (token(tos, tmp1, tmp2) == 1) printf("%s", tmp1); }
if (*first == 'w'){
size--; strcpy(tmp1, tos); while (atoi(stack[size - 1])) eval(tmp1); }
if (*first == '\"')
pointer=push(pointer);
}
}
}
int main(int argc, char **argv)
{
char program[9999] = "";
int i = 0, comment = 0, quote = 0, space = 0;
if (!strcmp(argv[1], "-e"))
strcpy(program, argv[2]);
else
{
FILE* f = fopen(argv[1], "r");
for (;;) {
char ch = fgetc(f);
if (ch < 0) break;
if (!quote) {
if (ch == '\n') comment = 0;
if (ch == ';') comment = 1;
if (comment) continue;
if (ch <= ' ') { ch = ' '; if (space++) continue; }
else space = 0;
}
if (ch == '\"') quote = 1 - quote;
program[i++] = ch;
}
fclose(f);
}
eval(program);
for (int i = 0; i < size; i++) printf("%03d: (%s)\r\n",size-i,stack[i]);
return 0;
}
``````

Claudiu 2014年

@Claudiu我也这么认为-但我不知道怎么做。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.