Menulis penerjemah untuk bahasa esoterik baru saya PointerLang

8

Saya merancang bahasa di mana pointer aritmatika adalah alat utama pemrograman.

Berikut ini beberapa contohnya.

(print 0 to 8)
=9[>1=9-*-1.>-1-1]

(print 1 to 10 with spaces in between, character literal extension used)
=1[.>1=10-*-1[>1=' '!>-2+1;-2];1]='\n'!

(compute the factorial of 10)
=10>1=*-1-1[>-1**1>1-1]>-1.

(print "hi")
=104!=105!

(print "hi" with extension for arrays)
={104,105,0}[!>1]

(print "Hello, world!" with extension for C-style string literals)
="Hello, world!"[!>1]

Spesifikasi Bahasa

Definisi bahasa sangat sederhana. Anda akan memahami dengan mudah jika Anda memiliki pengalaman dengan C, tetapi saya tidak akan menganggapnya demikian.

Setiap program di PointerLang memiliki pointer , singkatnya P,. Anda dapat menganggapnya sebagai variabel global tunggal tersembunyi, yang dapat Anda kontrol dengan menggunakan perintah . Pawalnya menunjuk ke awal array . Setiap elemen dalam array memiliki tipe intyang merupakan integer bertanda 32-bit.

Untuk programmer C.

int32_t *P = malloc(1000);

Di PointerLang, ada perintah dan argumen . Argumen adalah intyang harus datang setelah perintah. Semua perintah dijalankan dari kiri ke kanan kecuali ditentukan lain. Berikut ini adalah daftar perintah. Asingkatan argumen. Perintah tanpa Aberarti itu tidak mengambil argumen. Perintah dengan Aharus mengambil argumen. Di dalam tanda kurung adalah ekspresi C setara.

  • =A: assign A at P ( *P = A)
  • +A: tambahkan A at P ( *P += A)
  • -A: kurangi A at P ( *P -= A)
  • *A: kalikan dengan A di P ( *P *= A)
  • /A: bagi dengan A at P ( *P /= A)
  • >A: pindah Poleh A( P += A)
  • .: cetak bilangan bulat di P ( printf("%d", *P))
  • !: cetak integer di P as ASCII ( printf("%c", (char)*P))
  • [: jika nilai pada P adalah 0 pergi ke perintah setelah next ]( while (*P) {)
  • ]: buka sebelumnya [yang merupakan pasangan yang cocok ( })
  • ;A: jika Apositif, buka perintah setelah Ath ]datang berikutnya; jika Anegatif, pergi ke Ath [datang sebelum; jika A adalah 0, jangan lakukan apa pun.

Literal integer adalah argumen.

Dua berikut adalah argumen khusus yang mengambil argumen.

  • -A: dievaluasi sebagai argumen yang memiliki nilai absolut yang sama dengan Adan tanda kebalikan dari A; minus unary
  • *A: Pindah Poleh A, mengevaluasi nilai pada P, bergerak Pdengan -A( P[A])

Semua komentar di PointerLang ada di antara tanda kurung (comment).

Contoh Program

Program ini yang dihitung dari 1 hingga 10 adalah contoh yang baik untuk melengkapi pemahaman Anda.

(print 1 to 10 with spaces in between)
=1[.>1=10-*-1[>1=32!>-2+1;-2];1]=10!

Berhati-hatilah saat menafsirkan -*-1. -adalah perintah dan *-1argumennya. Integer literal secara efektif menunjukkan akhir dari pasangan argumen-perintah.

Ini dapat diterjemahkan ke C dengan korespondensi 1-ke-1 sebagai

int main(void) {
    int32_t *P = malloc(1000);
    *P = 1; // =1
l:
    while (*P) { // [
        printf("%d", *P); // .
        P += 1; // > 1
        *P = 10; // =10
        *P -= P[-1]; // -*-1
        while (*P) { // [
            P += 1; // >1
            *P = 32; // =32
            printf("%c", (char)*P); // !
            P += -2; // >-2
            *P += 1; // +1
            goto l; // ;-2
        } // ]
        break; // ;1
    } // ]
    *P = 10; // =10
    printf("%c", (char)*P); // !
    return 0;
}

Ekstensi dapat diterapkan ke bahasa ini seperti literal karakter, array, string string dll, tetapi Anda tidak harus mengimplementasikannya, untuk kesederhanaan.

Tantangan

Anda harus mengimplementasikan fitur inti yang dirinci di bagian Spesifikasi Bahasa dan CATATAN di bawah ini. Cobalah dengan bahasa pemrograman favorit Anda, tuliskan program sesingkat mungkin.

CATATAN1: Ukuran array tidak ditentukan. Tetapi harus cukup besar untuk menyelesaikan sebagian besar masalah.

CATATAN2: Overflow bilangan bulat tidak ditentukan.

CATATAN3: Spesifikasi hanya mendefinisikan hasil atau efek dari konstruksi bahasa tertentu. Misalnya, Anda tidak harus mengikuti langkah-langkah dalam definisi argumen dengan tepat *.

CATATAN4: Setiap karakter yang bukan perintah, argumen, atau komentar Whitespaces diabaikan. =104!=105!sama seperti = 1 0 4! = 1 05 !misalnya.

CATATAN5: Komentar tidak disarangkan. ((comment))adalah kesalahan sintaksis.

NOTE6: Saya telah membuat perubahan untuk memperbaiki lubang dalam bahasa saya. The ~perintah sekarang tidak terpakai dan ;selalu membawa argumen.

CATATAN7: Setiap literal bilangan bulat adalah desimal.

xiver77
sumber
13
Apakah hanya saya atau ini pada dasarnya brainfuck?
Claudiu
dapatkah kita menganggap semua pernyataan yang disampaikan itu valid? yaitu semua kawat gigi ditutup
Lewi
Apakah Anda yakin contoh pertama =9[>1=9-*-1.>-1-1]mencetak 0 hingga 9? Setelah itu ptints 8 karena P [0] = 1 maka kemudian kurangi 1 tepat sebelum akhir dari loop yang membuat P [0] = 0 dan kemudian ketika memulai loop lagi itu harus keluar karena P [0] = 0 sehingga Misalnya hanya mencetak 0 hingga 8. Atau apakah saya benar-benar bingung?
Jerry Jeremiah
@JerryJeremiah hmm .. yakin sepertinya kesalahan saya, akan diperbaiki sekarang.
xiver77
Ini seperti yang diinginkan BrainFuck.
SS Anne

Jawaban:

4

C 413

Berkat @ceilingcat untuk beberapa permainan golf yang sangat bagus - sekarang bahkan lebih pendek

#define L strtol(I++,&I,10)
#define A*I==42?I++,P[L]:L
#define F(a)-91-a|i;i-=*I-93+a?*I==91+a:-1);}
i;char*I;X[999],*P=X;Y(){for(;*I++F(2)B(){for(i=!--I;*--I F(0)Z(c){for(c=A;c;c+=c<0?1:-1)if(i=c<1)B();else for(;*I++F(2)main(j,a)char**a;{for(I=a[1];j=*I++;printf(j-4?j+9?j==19?*P=A:j==1?*P+=A:j==3?*P-=A:!j?*P*=A:j==5?*P/=A:j==20?P+=A:j-17?j-51?j-49?I=j+2?I:index(I,41)+1:*P||Y(i=1):B():Z(),"":P:"%d",*P))j-=42;}

Cobalah online!

dan versi yang sedikit kurang golf dari jawaban asli saya:

#include <stdio.h>
#include <stdlib.h>
#define L strtol(I++,&I,10)
#define A *I=='*'?I++,P[L]:L
int X[999],*P=X;
int main(int i, char *a[])
{
  char* I=a[1];
  while(*I)
  {
    switch(*I++)
    {
      case '(': while(*I++!=')'); break;
      case '.': printf("%d",*P); break;
      case '!': printf("%c",(char*)*P); break;
      case '[': if(!*P)
                  for(i=1;*I++!=']'||i;)
                  {
                    if(*I=='[')
                      i+=1;
                    if(*I==']')
                      i-=1;
                  }
                break;
      case ']': for(--I,i=0;*--I !='['||i;)
                {
                  if(*I==']')
                    i+=1;
                  if(*I=='[')
                    i-=1;
                }
                break;
      case '=': *P=A; break;
      case '+': *P+=A; break;
      case '-': *P-=A; break;
      case '*': *P*=A; break;
      case '/': *P/=A; break;
      case '>': P+=A; break;
      case ';': for(int c=A; c; c+=c<0?1:-1)
                {
                  if(c>0)
                    for(i=0;*I++!=']'||i;)
                    {
                      if(*I=='[')
                        i+=1;
                      if(*I==']')
                        i-=1;
                    }
                  else
                    for(--I,i=0;*--I !='['||i;)
                    {
                      if(*I==']')
                        i+=1;
                      if(*I=='[')
                        i-=1;
                    }
                }
    }
  }
  return 0;
}
Jerry Jeremiah
sumber
@ceilingcat Ok, sekarang ungolfing tidak mungkin lagi jadi saya tidak tahu cara kerjanya. Bagaimana Anda membuatnya lebih pendek?
Jerry Jeremiah
Baru diganti switch(...){case'(':...case'.':...dengan j=='('?...:j=='.'?...dan memfaktorkan panggilan fungsi agar sesuai dengan operator ternary.
ceilingcat