Viết một trình thông dịch cho ngôn ngữ bí truyền mới của tôi PulumLang


8

Tôi đã thiết kế một ngôn ngữ trong đó số học con trỏ là công cụ chính của lập trình.

Dưới đây là một số ví dụ.

(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]

Đặc tả ngôn ngữ

Định nghĩa ngôn ngữ rất đơn giản. Bạn sẽ hiểu rất dễ dàng nếu bạn có kinh nghiệm với C, nhưng tôi sẽ không cho là như vậy.

Mọi chương trình trong PulumLang đều có con trỏ , nói ngắn gọn là P. Bạn có thể nghĩ nó như một biến toàn cục duy nhất ẩn mà bạn có thể kiểm soát bằng cách sử dụng các lệnh . Pban đầu chỉ vào đầu của mảng . Mỗi phần tử trong mảng có loại intlà số nguyên có chữ ký 32 bit.

Dành cho lập trình viên C

int32_t *P = malloc(1000);

Trong PulumLang, có các lệnhđối số . Một đối số là một intphải đi sau một lệnh. Tất cả các lệnh được thực hiện từ trái sang phải trừ khi có quy định khác. Sau đây là danh sách các lệnh. Alà viết tắt của lập luận. Một lệnh không Acó nghĩa là nó không có đối số. Một lệnh với Aphải có một đối số. Bên trong dấu ngoặc đơn là biểu thức C tương đương.

  • =A: gán A tại P ( *P = A)
  • +A: thêm A tại P ( *P += A)
  • -A: trừ A tại P ( *P -= A)
  • *A: nhân với A tại P ( *P *= A)
  • /A: chia cho A tại P ( *P /= A)
  • >A: di chuyển Pbởi A( P += A)
  • .: in số nguyên tại P ( printf("%d", *P))
  • !: in số nguyên tại P dưới dạng ASCII ( printf("%c", (char)*P))
  • [: nếu giá trị tại P bằng 0, hãy chuyển đến lệnh sau ]( while (*P) {)
  • ]: đi đến trước [đó là cặp phù hợp ( })
  • ;A: nếu Alà tích cực, đi đến lệnh sau Alần thứ ]tiếp theo; nếu Alà tiêu cực, đi đến Athứ [đến trước; nếu A bằng 0, không làm gì cả.

Một số nguyên là một đối số.

Hai sau đây là các đối số đặc biệt có một đối số.

  • -A: được đánh giá là một đối số có cùng giá trị tuyệt đối như Avà dấu ngược lại của A; trừ đơn phương
  • *A: di chuyển Ptheo A, đánh giá giá trị tại P, di chuyển Ptheo -A( P[A])

Tất cả các nhận xét trong PulumLang nằm giữa dấu ngoặc đơn (comment).

Chương trình ví dụ

Chương trình này tính từ 1 đến 10 là một ví dụ tốt để hoàn thành sự hiểu biết của bạn.

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

Hãy cẩn thận khi bạn giải thích -*-1. -là lệnh và *-1là đối số. Một số nguyên có nghĩa là kết thúc một cặp đối số lệnh.

Nó có thể được dịch sang C với sự tương ứng 1-1

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;
}

Phần mở rộng có thể được áp dụng cho ngôn ngữ này, chẳng hạn như ký tự, mảng, chuỗi ký tự, v.v., nhưng bạn không phải thực hiện chúng, vì đơn giản.

Các thách thức

Bạn phải triển khai các tính năng cốt lõi được nêu chi tiết trong phần Đặc tả ngôn ngữ và các GHI CHÚ bên dưới. Hãy thử với ngôn ngữ lập trình yêu thích của bạn, viết chương trình ngắn nhất có thể.

CHÚ THÍCH 1: Kích thước của mảng không xác định. Nhưng nó phải đủ lớn để giải quyết hầu hết các vấn đề.

CHÚ THÍCH 2: Tràn số nguyên không xác định.

CHÚ THÍCH 3: Thông số kỹ thuật chỉ xác định kết quả hoặc hiệu ứng của các cấu trúc ngôn ngữ nhất định. Ví dụ: bạn không phải thực hiện chính xác các bước trong định nghĩa của đối số *.

CHÚ THÍCH 4: Bất kỳ ký tự nào không phải là lệnh, đối số hoặc nhận xét Khoảng trắng đều bị bỏ qua. =104!=105!cũng giống như = 1 0 4! = 1 05 !ví dụ.

CHÚ THÍCH 5: Nhận xét không được lồng nhau. ((comment))là một lỗi cú pháp.

CHÚ THÍCH 6: Tôi đã thực hiện một thay đổi đột phá để sửa một lỗ hổng trong ngôn ngữ của mình. Các ~lệnh bây giờ không sử dụng và ;luôn có một đối số.

CHÚ THÍCH 7: Mỗi số nguyên là số thập phân.


13
Có phải chỉ là tôi hay điều này về cơ bản là brainfuck?
Claudiu

chúng ta có thể cho rằng tất cả các tuyên bố thông qua là hợp lệ? tức là tất cả các niềng răng đều đóng cửa
Levi

Bạn có chắc chắn ví dụ đầu tiên =9[>1=9-*-1.>-1-1]in 0 đến 9? Sau khi nó gợi ý 8 vì P [0] = 1 thì nó trừ 1 ngay trước khi kết thúc vòng lặp làm cho P [0] = 0 và sau đó khi nó bắt đầu lại vòng lặp, nó sẽ thoát vì P [0] = 0 vì vậy ví dụ chỉ nên in 0 đến 8. Hay tôi thực sự bối rối?
Jerry Jeremiah

@JerryJeremiah hmm .. chắc chắn đó là lỗi của tôi, sẽ sửa ngay.
xiver77

Điều này giống như những gì BrainFuck muốn trở thành.
SS Anne

Câu trả lời:


4

C 413

Cảm ơn @ceilingcat cho một số bài đánh gôn rất hay - giờ thậm chí còn ngắn hơn

#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;}

Hãy thử trực tuyến!

và phiên bản ít chơi hơn của câu trả lời ban đầu của tôi:

#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;
}

@ceilingcat Ok, bây giờ không thể thực hiện được nữa nên tôi không biết nó hoạt động như thế nào. Làm thế nào để bạn tiếp tục làm cho nó ngắn hơn?
Jerry Jeremiah

Chỉ cần thay thế switch(...){case'(':...case'.':...bằng j=='('?...:j=='.'?...và thực hiện các lệnh gọi hàm để phù hợp với toán tử ternary.
trần mèo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.