Bacakan deklarasi variabel C


41

Latar Belakang

Pernyataan deklarasi variabel dalam C terdiri dari tiga bagian: nama variabel, tipe dasarnya , dan tipe pengubah .

Ada tiga jenis pengubah tipe:

  • Pointer *(awalan)
  • Array [N](postfix)
  • Fungsi ()(postfix)
    • Anda dapat menentukan daftar argumen fungsi di dalam parens, tetapi untuk tantangan ini, mari kita abaikan dan gunakan saja ()(yang secara teknis berarti "fungsi dapat mengambil segala jenis argumen").

Dan cara membaca notasi adalah sebagai berikut:

int i;             // i is an int
float *f;          // f is a pointer to a float
my_struct_t s[10]; // s is an array of 10 my_struct_t
int func();        // func is a function returning an int

Tangkapannya adalah kita dapat menggabungkan semua ini untuk membentuk tipe yang lebih rumit, seperti array array atau array fungsi pointer atau pointer ke array pointer :

int arr[3][4];
// arr is an array of 3 arrays of 4 ints

int (*fptrs[10])();
// fptrs is an array of 10 pointers to functions returning an int

float *(*p)[16];
// p is a pointer to an array of 16 pointers to float

Bagaimana saya membaca pernyataan rumit ini?

  1. Mulai dari nama variabel. (name) is ...
  2. Pilih pengubah dengan prioritas tertinggi.
  3. Membacanya:
    • * -> pointer to ...
    • [N] -> array of N ...
    • () -> function returning ...
  4. Ulangi 2 dan 3 sampai pengubah habis.
  5. Terakhir, baca tipe dasar. ... (base type).

Dalam C, operator postfix didahulukan dari pada operator prefix, dan pengubah tipe tidak terkecuali. Karena itu, []dan ()ikat terlebih dahulu, lalu *. Apa pun di dalam sepasang parens (...)(jangan dikelirukan dengan operator fungsi) mengikat pertama di atas apa pun di luar.

Contoh ilustrasi:

int (*fptrs[10])();
      fptrs           fptrs is ...
           [10]       array of 10 ... // [] takes precedence over *
    (*         )      pointer to ...
                ()    function returning ...
int                   int

Tugas

Diberikan garis pernyataan deklarasi variabel yang ditulis dalam C, output ekspresi bahasa Inggris yang menggambarkan garis, menggunakan metode yang ditunjukkan di atas.

Memasukkan

Input adalah pernyataan C tunggal yang mencakup jenis basis tunggal, nama variabel tunggal, nol atau lebih jenis pengubah dan titik koma akhir. Anda harus menerapkan semua elemen sintaks yang dibahas di atas, ditambah:

  • Baik tipe dasar dan nama variabel cocok dengan ekspresi reguler [A-Za-z_][A-Za-z0-9_]*.
  • Secara teoritis, program Anda harus mendukung pengubah tipe dalam jumlah tidak terbatas.

Anda dapat menyederhanakan elemen sintaks C lainnya dengan cara berikut (implementasi penuh juga diterima):

  • Jenis dasar selalu satu kata, misalnya int, float, uint32_t, myStruct. Sesuatu seperti unsigned long longtidak akan diuji.
  • Untuk notasi array [N], angka Nakan selalu berupa bilangan bulat positif tunggal yang ditulis dalam basis 10. Hal-hal seperti int a[5+5], int a[SIZE]atau int a[0x0f]tidak akan diuji.
  • Untuk notasi fungsi (), tidak ada parameter yang ditentukan sama sekali, seperti yang ditunjukkan di atas.
  • Untuk spasi putih, hanya karakter spasi yang 0x20akan digunakan. Anda dapat membatasi program Anda untuk penggunaan spasi putih tertentu, misalnya
    • Gunakan hanya satu spasi setelah tipe dasar
    • Gunakan ruang di mana-mana di antara token
  • Namun, Anda tidak dapat menggunakan dua atau lebih spasi berturut-turut untuk menyampaikan lebih banyak informasi daripada menjadi pemisah token.

Menurut sintaks C, tiga kombinasi berikut tidak valid, dan karenanya tidak akan diuji:

  • f()() Fungsi mengembalikan fungsi
  • f()[] Berfungsi mengembalikan array
  • a[]() Array fungsi N

Pengembang C menggunakan formulir yang setara ini sebagai gantinya (dan semua ini tercakup dalam kasus uji):

  • (*f())()Fungsi mengembalikan pointer ke fungsi
  • *f()Fungsi mengembalikan pointer ke elemen pertama array
  • (*a[])()Array N pointer berfungsi

Keluaran

Outputnya adalah satu kalimat bahasa Inggris. Anda tidak perlu (tetapi Anda bisa jika mau) menghormati tata bahasa Inggris, misalnya penggunaan a, an, the, bentuk tunggal / jamak, dan titik akhir (titik). Setiap kata harus dipisahkan oleh satu atau lebih spasi putih (spasi, tab, baris baru) sehingga hasilnya dapat dibaca oleh manusia.

Sekali lagi, inilah proses konversi:

  1. Mulai dari nama variabel. (name) is ...
  2. Pilih pengubah dengan prioritas tertinggi.
  3. Membacanya:
    • * -> pointer to ...
    • [N] -> array of N ...
    • () -> function returning ...
  4. Ulangi 2 dan 3 sampai pengubah habis.
  5. Terakhir, baca tipe dasar. ... (base type).

Uji kasus

int i;              // i is int
float *f;           // f is pointer to float
my_struct_t s[10];  // s is array of 10 my_struct_t
int func();         // func is function returning int
int arr[3][4];      // arr is array of 3 array of 4 int
int (*fptrs[10])(); // fptrs is array of 10 pointer to function returning int
float *(*p)[16];    // p is pointer to array of 16 pointer to float

_RANdom_TYPE_123 (**(*_WTH_is_TH15)())[1234][567];
/* _WTH_is_TH15 is pointer to function returning pointer to pointer to array of
   1234 array of 567 _RANdom_TYPE_123 */

uint32_t **(*(**(*(***p)[2])())[123])[4][5];
/* p is pointer to pointer to pointer to array of 2 pointer to function returning
   pointer to pointer to array of 123 pointer to array of 4 array of 5 pointer to
   pointer to uint32_t */

uint32_t (**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5]);
// Same as above, just more redundant parens

some_type (*(*(*(*(*curried_func())())())())())();
/* curried_func is function returning pointer to function returning pointer to
   function returning pointer to function returning pointer to
   function returning pointer to function returning some_type */

Kriteria Penilaian & Menang

Ini adalah tantangan . Program dengan jumlah byte terkecil menang.


9
Terkait: cdecl.org
user202729

int arr[3][4];adalah an array of 3 arrays of 4 ints(seperti yang Anda katakan), atau an array of 4 arrays of 3 ints?
Charlie

1
@Charlie Yang pertama benar. sizeof(arr[0]) == sizeof(int[4]), jadi item arrberisi empat ints.
Bubbler

1
Apakah input berisi ;di akhir baris?
Black Owl Kai

2
@ KamilDrakari Ini yang terakhir. "array pointer berfungsi" pada dasarnya "array pointer", yang sangat valid dalam C.
Bubbler

Jawaban:


17

Python 3 , 331 312 294 261 240 byte

from re import*
class V(str):__pos__=lambda s:V(s+'pointer to ');__call__=lambda s:V(s+'function returning ');__getitem__=lambda s,i:V(s+'array of %i '%i)
t,e=input().split()
print(eval(sub('\*','+',sub('(\w+)',r'V("\1 is ")',e[:-1],1)))+t)

Cobalah online!

-19 byte dengan beralih ke python 2 dan menempatkan definisi kelas menjadi sebuah exec

-18 byte dengan mengubah regex dari [a-zA-Z_][a-zA-Z0-9_]*menjadi \\w+, terima kasih kepada Kevin Cruijssen

-33 byte dengan mengerjakan beberapa sihir definisi kelas dan memanfaatkan str, terima kasih kepada Lynn, berubah kembali ke python 3

-21 byte dengan menggabungkan beberapa regex, berkat infmagic2047

Mengharuskan hanya satu ruang yang terkandung dalam input (antara jenis dan ekspresi).

Saya pikir ini adalah pendekatan yang cukup unik untuk masalah ini. Ini sebagian besar menggunakan fakta bahwa Python sendiri dapat mengevaluasi string seperti (**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5])dan mendapatkan urutan yang benar dari panggilan fungsi, indeks array dan pointer - dan bahwa pengguna dapat membebani ini.


1
Pendekatan yang bagus, +1 dari saya! Anda dapat golf [a-zA-Z_][A-Za-z0-9_]*untuk [a-zA-Z_]\\w*menyimpan beberapa byte. EDIT: Sebenarnya, saya pikir Anda bisa menggunakan \\w+saja [a-zA-Z_][A-Za-z0-9_]*.
Kevin Cruijssen

Saya suka pendekatan ini :) ini dia dalam 253 byte
Lynn

1
Itu poin yang bagus. 261 kalau begitu.
Lynn

1
Anda dapat menggunakan [0]daripada .group()sejak Python 3.6.
infmagic2047

1
Dan ini adalah versi 240 byte .
infmagic2047

13

Retina 0.8.2 , 142 138 128 117 byte

(\w+) (.+);
($2) $1
\(\)
 function returning
\[(\d+)?]
 array of$#1$* $1
+`\((\**)(.+)\)
$2$1
\*
 pointer to
1` 
 is 

Cobalah online! Tautan termasuk kasus uji. Tata bahasa yang lebih baik . Sunting: Disimpan 10 21 bytes dengan porting @ solusi DLosc Pip. Penjelasan:

(\w+) (.+);
($2) $1

Pindahkan tipe ke ujung dan bungkus sisa dari deklarasi ()s jika seandainya itu mengandung bagian luar *.

\(\)
 function returning

Memproses fungsi apa pun.

\[(\d+)?]
 array of$#1$* $1

Memproses array apa pun.

+`\((\**)(.+)\)
$2$1

Pindahkan pointer ke ujung tanda kurung mereka, dan hapus tanda kurung, berulang kali bekerja dari set kurung terluar ke dalam.

\*
 pointer to

Memproses petunjuk apa pun.

1` 
 is 

Masukkan is.


7

Java 11, 469 467 463 450 byte

s->{String r="",t,S[];for(s=s.replace("()","~");s.contains("(");s=s.replace(t,"").replace("()",""),r+=t+";")t=s.replaceAll(".*(\\([^()]+\\)).*","$1");S=s.split(" ");t=S[0];r+=r.isEmpty()?S[1]:s;S=r.split(";");r=S[0].replaceAll(".*?(\\w+).*","$1 is ");for(var p:S)r+=p.replaceAll("[A-Za-z_]+\\d+|[^\\[\\d]","").replaceAll("\\[(\\d+)","array of $1 ")+(p.contains("~")?"function returning ":"")+"pointer to ".repeat(p.split("\\*").length-1);return r+t;}

Cobalah online.

Penjelasan:

s->{               // Method with String as both parameter and return-type
  String r="",     //  Result-String, starting empty
         t,        //  Temp-String, starting uninitialized
         S[];      //  Temp String-array, starting uninitialized
  for(s=s.replace("()","~");
                   //  Replace all "()" in the input `s` with "~"
      s.contains("(");
                   //  Loop as long as the input `s` still contains "("
      ;            //    After every iteration:
       s=s.replace(t,"")
                   //     Remove `t` from `s`
          .replace("()",""),
                   //     And also remove any redundant parenthesis groups
       r+=t+";")   //     Append `t` and a semi-colon to the result-String
    t=s.replaceAll(".*(\\([^()]+\\)).*","$1");
                   //   Set `t` to the inner-most group within parenthesis
  S=s.split(" ");  //  After the loop, split the remainder of `s` on the space
  t=S[0];          //  Set `t` to the first item (the type)
  r+=              //  Append the result-String with:
    r.isEmpty()?   //   If the result-String is empty
                   //   (so there were no parenthesis groups)
     S[1]          //    Set the result-String to the second item
    :              //   Else:
     s;            //    Simple append the remainder of `s`
  S=r.split(";");  //  Then split `r` on semi-colons
  r=S[0].replaceAll(".*?(\\w+).*",
                   //  Extract the variable name from the first item
     "$1 is ");    //  And set `r` to this name appended with " is "
  for(var p:S)     //  Loop over the parts split by semi-colons:
    r+=            //   Append the result-String with:
      p.replaceAll("[A-Za-z_]+\\d+
                   //    First remove the variable name (may contain digits)
         |[^\\[\\d]","")
                   //    And then keep only digits and "["
       .replaceAll("\\[(\\d+)",
                   //    Extract the number after "["
         "array of $1 ")
                   //    And append the result-String with "array of " and this nr
      +(p.contains("~")?
                   //    If the part contains "~"
         "function returning "
                   //     Append the result-String with "function returning "
       :           //    Else:
        "")        //     Leave the result-String the same
      +"pointer to ".repeat(
                   //    And append "pointer to " repeated
         p.split("\\*").length-1);
                   //    the amount of "*" in the part amount of time
  return r         //  Then return the result-String
          +t;}     //  appended with the temp-String (type)

Gagal pada kasus uji dengan kurung yang berlebihan.
Bubbler

@Bblbler Ah, tidak menyadari bahwa test case baru. Untungnya ini adalah perbaikan yang mudah.
Kevin Cruijssen

6

Bash + cdecl + sed GNU, 180

cdecladalah utilitas Unix yang terhormat yang melakukan sebagian besar dari apa yang diperlukan di sini, tetapi untuk mencocokkan persyaratan I / O, diperlukan beberapa sedpra dan pasca pemrosesan:

sed -r 's/^/explain struct /;s/struct (int|char double|float|void) /\1 /;s/\bfunc/_func/g'|cdecl|sed -r 's/^declare //;s/as/is/;s/struct //g;s/([0-9]+) of/of \1/g;s/\b_func/func/g'
  • Tidak ada upaya untuk memperbaiki tata bahasa.

sed Pra-pemrosesan:

  • s/^/explain struct /- Tambahkan "jelaskan struct" ke awal setiap baris
  • s/struct (int|char double|float|void) /\1 /- Hapus structsaat berhadapan dengan jenis bahasa C.
  • s/\bfunc/_func/g - "func" dikenali sebagai kata kunci oleh cdecl - suppress this

sed Pasca pemrosesan:

  • s/^declare // - hapus "nyatakan" pada awal baris
  • s/as/is/ - Cukup jelas
  • s/struct //g - hapus semua kata kunci "struct"
  • s/([0-9]+) of/of \1/g - pemesanan "dari" yang benar
  • s/\b_func/func/g - kembalikan "_func" apa pun yang diganti pada pra-pemrosesan

Beraksi:

$ < cdecls.txt sed -r 's/^/explain struct /;s/struct (int|char double|float|void) /\1 /;s/\bfunc/_func/g'|cdecl|sed -r 's/^declare //;s/as/is/;s/struct //g;s/([0-9]+) of/of \1/g;s/\b_func/func/g'
i is int
f is pointer to float
s is array of 10 my_struct_t
func is function returning int
arr is array of 3 array of 4 int
fptrs is array of 10 pointer to function returning int
p is pointer to array of 16 pointer to float
_WTH_is_TH15 is pointer to function returning pointer to pointer to array of 1234 array of 567 _RANdom_TYPE_123
p is pointer to pointer to pointer to array of 2 pointer to function returning pointer to pointer to array of 123 pointer to array of 4 array of 5 pointer to pointer to uint32_t
p is pointer to pointer to pointer to array of 2 pointer to function returning pointer to pointer to array of 123 pointer to array of 4 array of 5 pointer to pointer to uint32_t
curried_func is function returning pointer to function returning pointer to function returning pointer to function returning pointer to function returning pointer to function returning some_type
$ 

Apakah cukup untuk melakukan s/\bfu/_fu/gdan menyimpan byte dari funcpenggantian penuh ?
DLosc

tunggu itu utilitas nyata? Saya selalu berpikir bahwa itu adalah nama situs web
phuclv

@ phuclv cdecl adalah utilitas nyata, dan sangat berguna untuk memeriksa deklarasi C.
Patricia Shanahan


Gagal untuk variabel bernama as(+4 byte untuk spasi untuk diperbaiki). Saya tidak memiliki akses ke cdecltetapi saya pikir Anda dapat menghemat 64 byte menggunakan sed -r 's/^(\w+)(\W+)/explain struct \1_\2_/'|cdecl|sed -r 's/^declare struct _|_$//;s/ as / is /;s/([0-9]+) of/of \1/g'.
Neil

6

Pip -s , 152 150 148 139 137 126 125 123 byte

Pendekatan ketiga!

YaRs" ("R';')R`\[(\d+)]`` array of \1`R"()"" function returning"L#aYyR`\((\**)(.+)\)`{c." pointer to"X#b}{[b"is"g@>2a]}Vy^s

Mengambil deklarasi sebagai input baris perintah. Cobalah online!

Penjelasan

Kode ini ada dalam tiga bagian: pengaturan awal dan penanganan fungsi dan array; loop yang menangani tanda kurung dan pointer; dan penataan ulang akhir.

Pengaturan, fungsi & array

Kami ingin seluruh deklarasi menjadi tanda kurung (ini membantu dengan loop nanti), jadi kami mengubahnya type ...;menjadi type (...). Kemudian, amati bahwa tidak ada pemesanan ulang yang dilakukan dengan deskripsi fungsi dan array, sehingga kami dapat melakukan semua penggantian itu terlebih dahulu tanpa mempengaruhi hasil akhir.

Y                         Yank into y variable...
 a                        The result of a (the cmdline arg)...
  R s                     Replace the space
   " ("                    with " ("
  R ';                    Replace the semicolon
   ')                      with a closing paren
  R `\[(\d+)]`            Replace digits in square brackets
   ` array of \1`          with " array of <digits>"
  R "()"                  Replace function parens
   " function returning"   with " function returning"

Jika input asli kami adalah float *((*p()))[16];, sekarang kami miliki float (*((*p function returning)) array of 16).

Tanda kurung dan pointer

Kami menjalankan lingkaran menggantikan sepasang kurung terluar dan tanda bintang yang langsung di dalam paren pembuka.

L#a                   Loop len(a) times (enough to complete all replacements):
 Y                    Yank into y variable...
  y                   The result of y...
   R `\((\**)(.+)\)`  Replace open paren, 0 or more asterisks (group 1), 1 or more
                      characters (group 2), and close paren
    {                  with this callback function (b = group 1, c = group 2):
     c .               The stuff in the middle, concatenated to...
      " pointer to"    that string
       X #b            repeated len(asterisks) times
    }

Langkah-langkah contoh:

float (*((*p function returning)) array of 16)
float ((*p function returning)) array of 16 pointer to
float (*p function returning) array of 16 pointer to
float p function returning pointer to array of 16 pointer to

Membersihkan

Satu-satunya yang tersisa adalah memindahkan tipe ke ujung dan menambahkan "adalah":

{[b"is"g@>2a]}Vy^s
               y^s  Split y on spaces
{            }V     Use the resulting list as arguments to this function:
 [          ]        Return a list of:
  b                   2nd argument (the variable name)
   "is"               That string
       g@>2           All arguments after the 2nd
           a          1st argument (the type)
                    The resulting list is printed, joining on spaces (-s flag)

Untuk definisi seperti int x;, pendekatan ini akan menghasilkan ruang tambahan, yang diizinkan oleh tantangan.


5

JavaScript (ES6), 316 ... 268 253 byte

s=>(g=s=>[/\d+(?=])/,/\*/,/!/,/.+ /,/\w+/].some((r,i)=>(S=s.replace(r,s=>(O=[O+`array of ${s} `,O+'pointer to ','function returning '+O,O+s,s+' is '+O][i],'')))!=s)?g(S):'',F=s=>(O='',S=s.replace(/\(([^()]*)\)/,g))!=s?O+F(S):g(s)+O)(s.split`()`.join`!`)

Cobalah online!

Berkomentar

Fungsi pembantu

g = s =>                             // s = expression to parse
  [                                  // look for the following patterns in s:
    /\d+(?=])/,                      //   array
    /\*/,                            //   pointer
    /!/,                             //   function
    /.+ /,                           //   type
    /\w+/                            //   variable name
  ].some((r, i) =>                   // for each pattern r at index i:
    ( S = s.replace(                 //   S = new string obtained by removing
      r,                             //       the pattern matching r from s
      s => (                         //     using the first match s and the index i,
        O = [                        //     update the output O:
          O + `array of ${s} `,      //       array
          O + 'pointer to ',         //       pointer
          'function returning ' + O, //       function
          O + s,                     //       type
          s + ' is ' + O             //       variable name
        ][i],                        //
        ''                           //     replace the match with an empty string
    )))                              //   end of replace()
    != s                             //   make some() succeed if S is not equal to s
  ) ?                                // end of some(); if truthy:
    g(S)                             //   do a recursive call with S
  :                                  // else:
    ''                               //   stop recursion and return an empty string

Bagian utama

s => (                 // s = input
  g = …,               // define the helper function g (see above)
  F = s => (           // F = recursive function, taking a string s
    O = '',            //   O = iteration output, initialized to an empty string
    S = s.replace(     //   S = new string obtained by removing the next expression from s
      /\(([^()]*)\)/,  //     look for the deepest expression within parentheses
      g                //     and process it with the helper function g
    )                  //   end of replace()
  ) != s ?             // if S is not equal to s:
    O + F(S)           //   append O to the final output and do a recursive call with S
  :                    // else (we didn't find an expression within parentheses):
    g(s) + O           //   process the remaining expression with g and return O
)(s.split`()`.join`!`) // initial call to F with all strings '()' in s replaced with '!'

Saya bertanya-tanya mengapa Anda menggunakan [...s.split`()`.join`!`]bukan hanya [...s.replace('()','!')], tetapi saya menyadari itu adalah byte-count yang sama persis .. :)
Kevin Cruijssen

@KevinCruijssen Alasan utamanya adalah s.replace('()','!')hanya mengganti kejadian pertama.
Arnauld

Ah, tentu saja. Lupa ganti JS tidak sama dengan Java. Di Jawa .replacemenggantikan semua kejadian, dan .replaceAllmengganti semua kejadian dengan mengaktifkan regex. Selalu berpikir penamaan itu cukup buruk untuk kedua metode ini di Jawa, karena saya akan memanggil mereka .replaceAlldan .regexReplaceAllatau sesuatu di sepanjang garis itu, tapi saya kira untuk codegolf lebih pendek sebagai .replacedan .replaceAll.
Kevin Cruijssen

1
BTW, saya perhatikan bahwa Anda menggunakan teknik yang sama (dengan ~) setelah memposting versi pertama dari jawaban saya sendiri. Pikiran besar berpikir sama, saya kira. : p
Arnauld

3

Bersih , 415 byte

import StdEnv,Text
$s#(b,[_:d])=span((<>)' ')(init s)
=join" "(?d++[""<+b])
?[]=[]
?['()':s]=["function returning": ?s]
?['*':s]= ?s++["pointer to"]
?['[':s]#(n,[_:t])=span((<>)']')s
=["array of "<+n: ?t]
?s=case@0s of(['(':h],t)= ?(init h)++ ?t;(h,t)|t>[]= ?h++ ?t=[h<+" is"]
~c=app2((++)[c],id)
@n[c:s]=case c of'('= ~c(@(n+1)s);')'|n>1= ~c(@(n-1)s)=([c],s);_|n>0= ~c(@n s)=span(\c=c<>'('&&c<>'[')[c:s]
@_ e=(e,e)

Cobalah online!


3

R , 225 218 byte

g=gsub
"&"="@"=paste
"["=function(a,b)a&"array of"&b
"+"=function(a)a&"pointer to"
eval(parse(t=g('\\(\\)','@"function returning"',g('(\\w+) (.*?)([A-Za-z_]\\w*)(.*);','\\2"\\3 is"\\4&"\\1"',g('\\*','+',readline())))))

Cobalah online!

Program lengkap, dibungkus dengan fungsi pada TIO untuk memudahkan pengujian semua kasus uji sekaligus.

Pertama, kami menggunakan Regex untuk mengonversi input formulir type ...name...;ke ..."name is"..."type". Notasi fungsi ()kemudian dikonversi ke teks dengan operator gabungan didahulukan tinggi. Sayangnya, kami juga harus mengganti *dengan +yang sebelumnya tidak dapat diterima sebagai operator unary. Sisanya dilakukan oleh R's evaldengan operator kelebihan beban.


1
Solusi pintar!
J.Do

3

Perl 6 , 209 190 171 162 153 byte

{~({(.[1]Z'is'),.<e>.&?BLOCK,('array of'X .[2]),('function returning','pointer to'Zxx.[3,0])if $_}(m:g/(\*)*[(\w+)+|\(<e=~~>.][\[(\d+).]*(\(.)*/[1]),$0)}

Cobalah online!

Pendekatan regex rekursif. Menghasilkan beberapa karakter ruang ekstra yang dapat dihindari dengan biaya 3 byte .

Penjelasan

{     # Anonymous block
 ~(   # Convert list to string
   {  # Block converting a regex match to a nested list
     (.[1]            # Array of 0 or 1 variable names
       Z'is'),        # zipped with string "is"
     .<e>.&?BLOCK,    # Recursive call to block with subexpression
     ('array of'      # String "array of"
       X .[2]),       # prepended to each array size
     ('function returning',  # Strings "function returning"
      'pointer to'           # and "pointer to"
      Zxx             # zipped repetition with
      .[3,0])         # number of function and pointer matches
     if $_            # Only if there's an argument
   }
   (             # Call block
     m:g/        # Input matched against regex
      (\*)*      # Sequence of asterisks, stored in [0]
      [          # Either
       (\w+)+    # the variable name, stored as 1-element array in [1]
       |         # or
       \(        # literal (
         <e=~~>  # the same regex matched recursively, stored in <e>
       .         # )
      ]
      [\[(\d+).]*  # Sequence of "[n]" with sizes stored in [2]
      (\(.)*       # Sequence of "()" stored in [3]
     /
     [1]  # Second match
   ),
   $0     # First match (base type)
 )
}

2

JavaScript 250 Bytes [249?]

Ini menggunakan 250 Bytes:

k=>(a=k.match(/\W|\w+/g),s=[v=j=r=""],f=y=>!j&!a[i+1]||(m=a[i],v?(r+=v=m=='['?`array of ${a[i+=3,i-2]} `:m<')'?(i+=2,"function returning "):s[j-1]=='*'?j--&&"pointer to ":""):m==')'?v=j--|i++:m<'+'?s[j++]=a[i++]:r+=a[v=i++]+" is ",f(),r+a[0]),f(i=2))

Penjelasan:

Pada dasarnya, ini membaca dari buffer a, yang merupakan input tokenized. Ini terus-menerus memindahkan token dari buffer ake tumpukan s, hingga mode evaluasi dipicu. Mode evaluasi akan mengkonsumsi operasi postfix terlebih dahulu (), []dari buffer, dan kemudian akan mengkonsumsi operator prefix *dari stack. Mode evaluasi dipicu ketika keadaan di mana kata akan berada (Entah nama ketik ditemukan dan dikonsumsi, atau akhir )ditemukan dan dihapus). Mode evaluasi dinonaktifkan ketika tidak ada lagi operator awalan / postfix yang ditemukan.

k=>( // k is input
    a=k.match(/\W|\w+/g), // split by symbol or word
    s=[v=j=r=""], // j=0, v=false, r="", s=[]
    // s is the stack, r is the return string,
    // v is true if we're in evaluation mode (Consume (), [], *)
    // v is false if we're waiting to see a ) or token, which triggers evaluation
    // j is the index of the top of the stack (Stack pointer)
    f=y=>!j&!a[i+1]||( // !j means stack is empty, !a[i+1] means we're at the ;
        m=a[i], // Save a[i] in a variable
        v // Are we evaluating?
        ?(
        r+=v=
            m=='[' // Array
            ?`array of ${a[i+=3,i-2]} ` // Skip three tokens: "[", "10", "]"
                                        // a[i-2] is the "10"
            :m<')' // m == '('
                ?(i+=2,"function returning ") // Skip two tokens: "(", ")"
                :s[j-1]=='*' // Stack has a pointer
                    ?j--&&"pointer to " // Pop the stack
                    :"" // Set v to be false, r+=""
        )
        :m==')'
            ?v=j--|i++ // Pop the '(', skip over the ')', v = Evaluation mode
            :m<'+' // m == '*' || m == '('
                ?s[j++]=a[i++] // push(s, pop(a))
                :r+=a[v=i++]+" is " // Otherwise we have the token
        , f(), r+a[0] // Recurse f(), and return r+a[0]. a[0] is the type.
    ),
    f(i=2) // Set i=2, and call f(), which returns the final value r + type
    // a = ["type", " ", ...], so i=2 give the first real token
    // This soln assumes there is only one space, which is an allowed assumption
)

CATATAN

Jika saya mengerti "Gunakan spasi di mana-mana di antara token" dengan benar:

k=>(a=k.split(" "),s=[v=j=r=""],f=y=>!j&!a[i+1]||(v?(r+=v=a[i]=='['?`array of ${a[i+=3,i-2]} `:a[i]<')'?(i+=2,"function returning "):s[j-1]=='*'?j--&&"pointer to ":""):a[i]==')'?v=j--|i++:a[i]<'+'?s[j++]=a[i++]:r+=a[v=i++]+" is ",f(),r+a[0]),f(i=1))

secara teknis valid, dan menggunakan

249 Bytes

Dengan asumsi ada ruang di antara setiap token.


2
Ini menghabiskan waktu berjam-jam, meskipun terlihat langsung. Saya mungkin mengetuk 5-10 byte / jam, dimulai dengan 350 karakter. Aku memang tidak punya kehidupan.
Nicholas Pipitone

2
Saya berada di sekitar 325 ketika saya berpikir "Saya mencapai optimalitas dengan algoritma saya saat ini - rip", tetapi kemudian untuk beberapa alasan saya masih bisa mengetuk 5-10 / jam, meskipun setiap ketukan diikuti oleh "Oke, ini jelas merupakan hasil optimal ". Memukul 250 adalah sewenang-wenang karena itu adalah yang pertama mengalahkan 253 yang berkuasa, jadi meskipun saya masih mengatakan "Oke, ini jelas merupakan hasil yang optimal", mungkin masih ada lebih banyak untuk mengoptimalkan.
Nicholas Pipitone

1

Merah , 418 410 byte

func[s][n: t:""a: charset[#"a"-#"z"#"A"-#"Z"#"0"-#"9""_"]parse s[remove[copy x thru" "(t: x)]to a
change[copy x[any a](n: x)]"#"]b: copy[]until[c: next find s"#"switch c/1[#"("[append
b"function returning"take/part c 2]#"["[parse c[remove[skip copy d to"]"(append b
reduce["array of"d])skip]]]#")"#";"[take c c: back back c while[#"*"= c/1][take c
c: back c append b"pointer to"]take c]]s =""]reduce[n"is"b t]]

Cobalah online!

Penjelasan:

f: func [ s ] [
    n: t: 0                                         ; n is the name, t is the type
    a: charset [ #"a"-#"z" #"A"-#"Z" #"0"-#"9" "_" ]; characters set for parsing 
    parse s[                                        ; parse the input with the following rules
        remove [ copy x thru " " ](t: x)            ; find the type, save it to t and remove it from the string
        to a                                        ; skip to the next alphanumerical symbol
        change [ copy n [ any a ] (n: x) ] "#"      ; save it to n and replace it with '#'
    ]
    b: copy [ ]                                     ; block for the modifiers 
    until [                                         ; repeat 
       c: next find s "#"                           ; find the place of the name   
       switch c/1 [                                 ; and check what is the next symbol
           #"(" [ append b "function returning"     ; if it's a '('- it's a function - add the modifier       
                  take/part c 2                     ; and drop the "()"
                ]
           #"[" [ parse c [                         ; '[' - an array
                     remove [ skip copy d to "]"    ; save the number
                             (append b reduce [     ; and add the modifier 
                                  "array of" d
                              ] )                   
                             skip ]                 ; and remove it from the string
                     ]
                ]
           #")"                                     ; a closing bracket 
           #";" [ take c                            ; or ';' - drop it
                    c: back back c                  ; go to the left 
                    while [ #"*" = c/1 ]            ; and while there are '*'
                    [
                        take c                      ; drop them
                        c: back c                   ; go to the left
                        append b "pointer to"       ; add the modifier
                    ]
                    take c                          ; drop '(' (or space)
                 ]
       ]
       s = ""                                       ; until the string is exhausted
    ]
    reduce [ n "is" b t ]                     ; display the resul
]

0

APL (NARS), karakter 625, byte 1250

CH←⎕D,⎕A,⎕a,'_'⋄tkn←nm←∆←''⋄in←⍬⋄⍙←lmt←lin←0
eb←{∊(1(0 1 0)(0 1)(1 0))[⍺⍺¨⍵]}
tb←{x←({⍵='[':3⋄⍵=']':4⋄⍵∊CH,' ':1⋄2}eb⍵)\⍵⋄(x≠' ')⊂x}

gt
tkn←''⋄→0×⍳⍙>lin⋄tkn←∊⍙⊃in⋄⍙+←1⋄→0×⍳(⍙>lin)∨'('≠↑tkn⋄→0×⍳')'≠↑⍙⊃in⋄tkn←tkn,⍙⊃in⋄⍙+←1

r←dcl;n
   n←0
B: gt⋄→D×⍳'*'≠↑tkn⋄n+←1⋄→B×⍳tkn≢''
D: r←ddcl⋄∆←∆,∊n⍴⊂'pointer to '

r←ddcl;q
   r←¯1⋄→0×⍳0>lmt-←1
   →A×⍳∼'('=↑tkn⋄q←dcl⋄→F×⍳')'=↑tkn⋄→0
A: →B×⍳∼(↑tkn)∊CH⋄nm←tkn⋄→F
B: r←¯2⋄→0
F: gt⋄→G×⍳∼tkn≡'()'⋄∆←∆,'function that return '⋄→F
G: →Z×⍳∼'['=↑tkn⋄∆←∆,'array of ',{''≡p←(¯1↓1↓tkn):''⋄p,' '}⋄→F
Z: r←0

r←f w;q
   nm←∆←''⋄in←tb w⋄⍙←1⋄lin←↑⍴in⋄lmt←150⋄gt⋄→A×⍳∼0>q←dcl⋄r←⍕q⋄→0
A: r←nm,' is a ',∆,1⊃in

ini hanya satu traslasi dari bahasa C ke APL dari kode dalam buku: "Linguaggio C" oleh Brian W. Kerninghan dan Dennis M. Ritchie bab 5.12. Saya tidak tahu bagaimana mengurangi semua itu karena saya belum mengerti 100% kode itu, dan karena saya tidak tahu terlalu banyak tentang APL ... Fungsi untuk latihan itu adalah f; saya pikir hanya diperbolehkan 150 nested parentesis '(' ')' untuk kesalahan mengembalikan satu batang dengan satu nilai negatif di dalamnya atau string descrition jika semuanya ok. Tampaknya ini tidak lebih baik daripada versi lain meskipun karakternya lebih sedikit karena yang lain melihat kesalahan lebih baik. Beberapa tes:

  f 'int f()()'
f is a function that return function that return int
  f 'int a[]()'
a is a array of function that return int
  f 'int f()[]'
f is a function that return array of int
  f 'int i;'
i is a int
  f 'float *f;'
f is a pointer to float
  f 'my_struct_t s[10];'
s is a array of 10 my_struct_t
  f 'int func();'
func is a function that return int
  f 'int arr[3][4];'
arr is a array of 3 array of 4 int
  f 'int (*fptrs[10])();'
fptrs is a array of 10 pointer to function that return int
  f 'float *(*p)[16]; '
p is a pointer to array of 16 pointer to float
  f '_RANdom_TYPE_123 (**(*_WTH_is_TH15)())[1234][567];'
_WTH_is_TH15 is a pointer to function that return pointer to pointe
  r to array of 1234 array of 567 _RANdom_TYPE_123
  f 'uint32_t (**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5]);'
p is a pointer to pointer to pointer to array of 2 pointer to funct
  ion that return pointer to pointer to array of 123 pointer to
   array of 4 array of 5 pointer to pointer to uint32_t
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.