Phân tích cú pháp hai chiều


25

Lý lịch

Alice và Bob đang tạo ra một ngôn ngữ chơi gôn để giành chiến thắng trong mọi thử thách PPCG. Alice muốn tạo một ngôn ngữ hai chiều, như> <>, nhưng Bob thích cú pháp tiền tố như trong J. Như một sự thỏa hiệp, họ quyết định tạo ra một ngôn ngữ tiền tố hai chiều. Trình phân tích cú pháp là một nỗi đau để viết, và họ cần sự giúp đỡ của bạn!

Đặc tả cú pháp

Trong ngôn ngữ của Alice và Bob, có các biến , được biểu thị bằng các chữ cái ASCII chữ thường a-zvà các hàm , được biểu thị bằng các chữ cái ASCII viết hoa A-Z. Một hàm có thể được gọi với một hoặc hai đối số. Một chương trình là một lưới hình chữ nhật gồm các chữ cái a-zA-Zvà khoảng trắng, và góc trên cùng bên trái không được chứa một khoảng trắng. Đây là một ví dụ về một chương trình hợp lệ:

F Gy
H   
R x 

Khi chương trình được phân tích cú pháp, nó được chuyển thành biểu thức của ngôn ngữ kiểu C (C, Java, Python ...) có chứa các biến đơn và các lệnh gọi hàm theo định dạng <func>(<arg>)hoặc <func>(<arg1>,<arg2>). Ví dụ, chương trình trên dẫn đến biểu thức này:

F(H(R(x)),G(x,y))

Các chi tiết của quá trình phân tích cú pháp như sau:

  • Các khoảng trắng chỉ là phụ, vì vậy chúng không được phân tích cú pháp.
  • Mỗi biến a-zluôn được phân tích cú pháp như chính nó.
  • Mỗi chức năng A-Zđược phân tích cú pháp như một cuộc gọi chức năng. Đối số của nó là các biểu thức gần nhất bên dưới nó và bên phải của nó trong lưới, theo thứ tự này. Nếu chỉ có một trong số này là hiện tại, nó được đưa ra như là đối số duy nhất. Bạn có thể giả sử rằng tất cả các hàm có ít nhất một đối số trong lưới.

Trong ví dụ trên, các biến xyđược phân tích cú pháp như chính chúng. Hàm Rkhông có gì bên dưới nó và xbên phải của nó, vì vậy nó được phân tích cú pháp như là một lời gọi một đối số R(x). Tương tự, Hđược phân tích cú pháp như H(R(x)), vì nó có Rbên dưới nó. Hàm Gnày xnằm bên dưới nó và ybên phải của nó, vì vậy nó được phân tích cú pháp G(x,y)và tương tự như vậy F. Biểu thức được phân tích cú pháp ở góc trên cùng bên trái là kết quả của quá trình phân tích cú pháp.

Đầu vào và đầu ra

Đầu vào của bạn là một mảng các ký tự hình chữ nhật không trống. Nó sẽ luôn là một chương trình hợp lệ trong ngôn ngữ của Alice và Bob, nhưng nó có thể chứa các biểu thức không được sử dụng trong đầu ra. Đầu ra của bạn sẽ là biểu thức được phân tích cú pháp từ quá trình trên.

Quy tắc và tính điểm

Bạn có thể viết một chương trình đầy đủ của một chức năng. Số byte thấp nhất sẽ thắng và các sơ hở tiêu chuẩn không được phép.

Các trường hợp thử nghiệm

Chúng được đưa ra trong định dạng grid <newline> expression, với dấu gạch nối ---giữa các trường hợp. Định dạng SE để trống một số dòng, nhưng chúng nên được lấp đầy bằng khoảng trắng.

x
x
---
x y
z  
x
---
Fx
F(x)
---
Fx
y 
F(y,x)
---
ABu
A(B(u))
---
G
H
k
G(H(k))
---
ABCA
x xs
 DFk
A(x,B(D(F(k)),C(x,A(s))))
---
A  B  

C  D x
A(C(D(x)),B(D(x)))
---
RT Hq 
I xR k
R(I(x),T(H(R(k),q)))
---
A A  A a 
 S A  b  
B  C   Dx
d X  u f 
A(B(d,C(D(f,x))),A(X(u),A(u,a)))

Một đầu ra như thế nào (A (B (D x)) (C (D x)))là phù hợp hay là định dạng cố định?
coredump

1
@coredump Trong thử thách này, định dạng đầu ra rất nghiêm ngặt; Alice và Bob muốn có thể sử dụng biểu thức được phân tích cú pháp trực tiếp.
Zgarb

Phần "infix" của ngôn ngữ nằm ở đâu? Tôi chỉ thấy tiền tố.
Paŭlo Ebermann

6
Bạn có thể thực sự tạo ra một ngôn ngữ với cú pháp này? :)
Martin Ender

4
Thử thách tiếp theo: viết một meta-golfer cho cú pháp này (được cung cấp một cây biểu thức, tìm lưới nhỏ nhất tương ứng với nó). Đối với khó khăn thêm, phân biệt giữa chức năng giao hoán và không giao hoán.
Martin Ender

Câu trả lời:


8

CJam, 67 62 60 58 57 54 byte

Cảm ơn Dennis vì đã tiết kiệm 4 byte.

{:Gsc_32&{"()"[GGz2{1m<_{S#}#>W<\}*z]{},{J}%',**+}|}:J

Điều này xác định một khối được đặt tên (chức năng) Jvà để nó trên ngăn xếp. Chính hàm này mong đợi một chuỗi các chuỗi trên ngăn xếp, đại diện cho lưới đầu vào và để lại chuỗi mong muốn thay cho nó.

Kiểm tra nó ở đây.

Tôi đã có ý định giải quyết vấn đề này kể từ khi nó được đăng, nhưng rõ ràng tôi cần một tiền thưởng và một giải pháp Pyth quá dài để thúc đẩy bản thân đầy đủ.

Giải trình

Giải pháp tất nhiên là đệ quy và dần dần xây dựng chuỗi.

{
  :G       e#  Store the current grid in G.
  sc       e#  Convert the grid to a string, flattening it, then to a character, which
           e#  discards everything but the first character. This is a golfed 0=0=.
           e#  This character will either be an upper-case letter (function) or a lower-
           e#  case letter (variable).
  _32&     e#  Make a copy of the character and take bitwise AND with 32. This gives a
           e#  NULL character for functions and a space for variables.
  {        e#  If the result is falsy... (i.e. NULL, i.e. we have a function)
    "()"   e#   Push parentheses for later use.
    [      e#   Remember the current stack depth.
    GGz    e#   Push an array which contains the grid and its transpose.
    2{     e#   Run this block twice... (it will be applied once to each grid)
      1m<  e#    Rotate the rows. This has two effects: a) It removes the first row
           e#    from the front such that we can go looking for the next non-space
           e#    character down the first column from the start. b) It places a row
           e#    at the end which we know doesn't start with a space, which acts as
           e#    a guard in case there are no further letters below the current one.
      _    e#    Duplicate this grid.
      {    e#    Find the first index where this block yields something truthy...
        S# e#     Find the index of the first space in the current row. If the row
           e#     starts with a space, this is 0, i.e. falsy and the search continues.
           e#     If there is a space in any later position, that will be positive and
           e#     truthy, so this index gets returned. If there is no space at all,
           e#     the result is -1 which is also truthy and ends the search.
      }#        
      >    e#     Discard all lines up to (but not including) the found index.
      W<   e#     Discard the guard row at the end.
      \    e#     Swap the grids so that the next pass processes the other grid.
    }*       
    z      e#    Transpose the second grid back to its original orientation.
    ]      e#    Wrap both processed grids in an array.
    {},    e#    Remove a grid if it's empty.
    {J}/   e#    For each remaining grid, call J recursively.
    ',*    e#    Join the grids with commas if there are still two of them.
    *      e#    Wrap this string in the parentheses below on the stack.
    +      e#    Prepend the function name.
  }|
}:J

5

Python 2, 227 223 192 182 179 177 byte

def r(i,y=0,x=0):
 c=i[y][x];z=[]
 for t in"pq":
    p=q=0
    try:
     while" "==i[y+p][x+q]or 1>p+q:exec t+"+=1"
     z+=[r(i,y+p,x+q)]
    except:1
 return c+"(%s)"%",".join(z)*c.isupper()

(Bốn không gian trên thực tế là các tab)

Lấy danh sách 2 ký tự làm đối số đầu tiên cho r.


5

Bình thường, 97 byte

D:TkdI}p@@QTkGR)=Z0p\(V2JK0W|q\ @@Q=b+TJ=H+kK!+JK=J+NJ=K+!NK)I!|gblQgHl@Q0p*Z\,:bH+=Z1d))p\);:000

Trời ơi mà mất nhiều thời gian để làm (khoảng 5/6 giờ?). Pyth thực sự không được thiết kế cho việc này ...

Hãy thử nó ở đây .

Cố gắng giải thích cũng như trăn tương đương

Q = literal_eval(input())

def at_slice(T,k,d):
  if Pprint(Q[T][k]) in "abcdefghijklmnopqrstuvwxyz": return 
  Z = 0
  Pprint("(")
  for N in range(2):
    J=K=0
    while " "==Q[assign('b',T+J)][assign('H',k+K)] or not J+K:
      J+=N
      K+=not N
    if not (b>=len(Q) or H>=len(Q[0])):
      Pprint(Z*",")
      at_slice(b,H,assign('Z',1)+d)
   Pprint(")")
at_slice(0,0,0)

Nơi các chức năng Pprintassigntrả lại những gì họ được cung cấp.


Nhiều sự can thiệp. Wow như vậy.
Addison Crump

5

Haskell, 124 122 120 119 byte

r@((c:_):_)#g|c>'_'=[c]|c<'!'=g%r|1<2=c:'(':(tail%r)!(map tail%r)++")"
_#_=""
g%r=g r#g
a!b=a++[','|a>"",b>""]++b
(#id)

Ví dụ sử dụng: (#id) ["RT Hq ","I xR k"]-> "R(I(x),T(H(R(k),q)))".

Cách thức hoạt động: bên cạnh lưới đầu vào r, hàm #lấy một hàm khác glàm đối số được áp dụng rbất cứ khi nào ký tự trên cùng bên trái là khoảng trắng. Nếu đó là một chữ thường thay thế, trả lại nó. Nếu không, nó phải là một ký tự viết hoa và #được gọi đệ quy, một lần tailđi xuống và một lần map tailđi đúng. !tham gia kết quả từ các cuộc gọi đệ quy với a ,, nếu cần. Tất cả bắt đầu với lưới đầu vào và chức năng nhận dạng.


0

Python 3, 187 byte

Vẫn đang tìm cách để giải quyết vấn đề này, nhưng tôi hài lòng, tôi đã xoay sở để biến nó thành một lớp lót.

lambda g,r=0,c=0:g[r][c]+'(%s)'%','.join([p(g,R,c)for R in range(r+1,len(g))if c<len(g[R])and' '!=g[R][c]][:1]+[p(g,r,C)for C in range(c+1,len(g[r]))if' '!=g[r][C]][:1])*g[r][c].isupper()
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.