C変数宣言を読み取る


41

バックグラウンド

Cの変数宣言ステートメントは、変数の名前、そのベース型、および型修飾子の3つの部分で構成されています。

タイプ修飾子には次の3種類があります。

  • ポインター*(プレフィックス)
  • 配列[N](後置)
  • 関数()(後置)
    • 括弧内に関数引数のリストを指定できますが、この課題のために、それを無視して使用します()(技術的には「関数は任意の種類の引数を取ることができます」)。

また、表記を読み取る方法は次のとおりです。

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

キャッチは、私たちのようなより複雑なタイプ、形成するために、これらのすべてを混在させることができるということである配列の配列関数ポインタの配列ポインタの配列へのポインタを

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

これらの複雑なステートメントをどのように読みましたか?

  1. 変数名から始めます。 (name) is ...
  2. 優先順位が最も高い修飾子を選択します。
  3. それを読んで:
    • * -> pointer to ...
    • [N] -> array of N ...
    • () -> function returning ...
  4. 修飾子がなくなるまで2と3を繰り返します。
  5. 最後に、基本型を読みます。 ... (base type).

Cでは、後置演算子は前置演算子よりも優先され、型修飾子も例外ではありません。したがって、[]そして()、その後、最初のバインド*。ペアのペア内にあるもの(...)(関数演算子と混同しないでください)は、最初に外部のものにバインドします。

図解された例:

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

仕事

Cで記述された変数宣言ステートメントの行を指定し、上記の方法を使用して、行を説明する英語の式を出力します。

入力

入力は、単一の基本型、単一の変数名、0個以上の型修飾子、および末尾のセミコロンを含む単一のCステートメントです。上記のすべての構文要素に加えて、以下を実装する必要があります。

  • 基本型と変数名の両方が正規表現と一致します[A-Za-z_][A-Za-z0-9_]*
  • 理論的には、プログラムは無制限の型修飾子をサポートする必要があります。

次の方法で他のC構文要素を単純化できます(完全な実装も歓迎します)。

  • 基本型は、常に一つの単語である、例えばintfloatuint32_tmyStruct。のようなものunsigned long longはテストされません。
  • 配列表記の[N]場合、数値Nは常に基数10で書かれた単一の正の整数になります。のようなものint a[5+5]int a[SIZE]またはint a[0x0f]テストされません。
  • 関数表記では()、上で指摘したように、パラメーターはまったく指定されません。
  • 空白の場合、スペース文字のみ0x20が使用されます。プログラムを空白の特定の使用に制限することができます。例えば
    • 基本タイプの後にスペースを1つだけ使用します
    • トークン間のどこでもスペースを使用する
  • ただし、トークンセパレーターよりも多くの情報を伝えるために2つ以上の連続したスペースを使用することはできません。

C構文によると、次の3つの組み合わせは無効であるため、テストされません。

  • f()() 関数を返す関数
  • f()[] 配列を返す関数
  • a[]() N個の関数の配列

C開発者は、代わりにこれらの同等の形式を使用します(これらはすべてテストケースでカバーされています)。

  • (*f())()関数へのポインターを返す関数
  • *f()配列の最初の要素へのポインターを返す関数
  • (*a[])()関数へのN ポインターの配列

出力

出力は単一の英語の文です。英語の文法を尊重する必要はありません(ただし、必要な場合は可能ですa, an, the)。結果が人間が読めるように、各単語は1つ以上の空白(スペース、タブ、改行)で区切る必要があります。

繰り返しますが、変換プロセスは次のとおりです。

  1. 変数名から始めます。 (name) is ...
  2. 優先順位が最も高い修飾子を選択します。
  3. それを読んで:
    • * -> pointer to ...
    • [N] -> array of N ...
    • () -> function returning ...
  4. 修飾子がなくなるまで2と3を繰り返します。
  5. 最後に、基本型を読みます。 ... (base type).

テストケース

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 */

スコアリングと勝利の基準

これは挑戦です。最小バイト数のプログラムが勝ちます。


9
関連:cdecl.org
user202729

int arr[3][4];であるan array of 3 arrays of 4 ints(あなたが言うように)、またはan array of 4 arrays of 3 ints
チャーリー

1
@Charlie前者は正しいです。sizeof(arr[0]) == sizeof(int[4])、したがってのアイテムにarrは4つintのが含まれます。
バブラー

1
入力;には行の終わりが含まれていますか?
ブラックフクロウカイ

2
@KamilDrakari後者です。「関数へのポインターの配列」は本質的に「ポインターの配列」であり、Cで完全に有効です
。–バブラー

回答:


17

Pythonの3331の312 294 261 240バイト

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)

オンラインでお試しください!

python 2に切り替えてクラス定義を exec

正規表現をから[a-zA-Z_][a-zA-Z0-9_]*に変更して-18バイト、\\w+Kevin Cruijssenに感謝

Lynnのおかげで、Python 3に戻って、クラス定義の魔法を使い、strを利用して-33バイト

infmagic2047のおかげで、複数の正規表現をマージして-21バイト

(タイプと式の間の)入力にスペースが1つだけ含まれている必要があります。

これは問題に対する非常にユニークなアプローチだと思います。これは主に、Python自体が文字列を評価し(**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5])、関数呼び出し、配列インデックス、ポインターの正しいシーケンスを取得でき、ユーザーがこれらをオーバーロードできるという事実を使用します。


1
素敵なアプローチ、私からの+1!ゴルフ[a-zA-Z_][A-Za-z0-9_]*[a-zA-Z_]\\w*て数バイト節約できます。編集:実際には、の\\w+代わりに使用できると思います[a-zA-Z_][A-Za-z0-9_]*
ケビンクルーイッセン

私はこのアプローチのように:)ここではである253バイト
リン・

1
それは良い点です。261そうです。
リン

1
Python 3.6以降の[0]代わりに使用できます.group()
infmagic2047

1
そして、これは240バイトのバージョンです。
infmagic2047

13

網膜0.8.2142の 138 128 117バイト

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

オンラインでお試しください!リンクにはテストケースが含まれます。より良い文法。編集:@DLoscのPipソリューションを移植することで10 21バイトを保存しました。説明:

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

型を最後に移動し()、アウターが含まれている場合に備えて、宣言の残りをsでラップし*ます。

\(\)
 function returning

機能を処理します。

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

配列を処理します。

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

ポインタを角かっこの最後に移動し、角かっこを削除し、角かっこの最も外側のセットから内側に向​​かって繰り返し作業します。

\*
 pointer to

ポインターを処理します。

1` 
 is 

を挿入しisます。


7

Java 11、469 467 463 450バイト

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

オンラインでお試しください。

説明:

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)

冗長な括弧を使用したテストケースでは失敗します。
バブラー

@Bubbler Ah、その新しいテストケースに気付かなかった。幸いなことに、それは簡単な修正です。
ケビンクルーイッセン

6

Bash + cdecl + GNU sed、180

cdeclは、ここで必要なほとんどのことを行う由緒あるUnixユーティリティですが、I / O要件に一致させるためには、いくつかのsed前処理と後処理が必要です。

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'
  • 文法を修正する試みは行われませんでした。

sed前処理:

  • s/^/explain struct /- すべての行の先頭に「explain struct」を追加します
  • s/struct (int|char double|float|void) /\1 /struct-C言語タイプを扱う場合は削除します
  • s/\bfunc/_func/g -「func」はcdeclによってキーワードとして認識されます-これを抑制します

sed後処理:

  • s/^declare // -行頭の「宣言」を削除
  • s/as/is/ -自明
  • s/struct //g -すべての「構造」キーワードを削除する
  • s/([0-9]+) of/of \1/g -「」の正しい順序
  • s/\b_func/func/g -前処理で置き換えられた「_func」を元に戻す

動作中:

$ < 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
$ 

s/\bfu/_fu/g完全なfunc置換のバイトを実行して保存するだけで十分ですか?
DLosc

それが本当のユーティリティだと思う?私はいつもそれがウェブサイトの名前だと思っていました
-phuclv

@phuclv cdeclは実際のユーティリティであり、C宣言の確認に非常に役立ちます。
パトリシアシャナハン


という名前の変数では失敗しますas(修正するスペースの場合は+4バイト)。私はアクセスできませんがcdecl、を使用して64バイトを節約できると思います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'
ニール

6

PIP -s152 150 148 139 137 126 125 123バイト

第三のアプローチ!

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

宣言をコマンドライン入力として受け取ります。オンラインでお試しください!

説明

コードは3つの部分に分かれています。初期セットアップと関数と配列の処理。括弧とポインターを処理するループ。最後の再配置。

セットアップ、機能、配列

宣言全体をカッコで囲むようにしたいので(後でループするのに役立ちます)、に変更type ...;type (...)ます。次に、関数と配列の説明で並べ替えが行われないことを確認します。したがって、最終出力に影響を与えることなく、これらすべての置換を最初に実行できます。

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"

私たちの元の入力があった場合、私たちfloat *((*p()))[16];は今持っていfloat (*((*p function returning)) array of 16)ます。

括弧とポインター

括弧の一番外側のペアと開始括弧のすぐ内側にあるアスタリスクを置き換えるループを実行します。

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
    }

手順の例:

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

掃除

残っているのは、型を最後に移動して「is」を追加することだけです。

{[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)

のような定義の場合int x;、このアプローチでは余分なスペースが生じますが、これはチャレンジで許可されています。


5

JavaScript(ES6)、316 ... 268 253バイト

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`!`)

オンラインでお試しください!

コメント済み

ヘルパー機能

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

主要部分

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 '!'

あなたが使用した理由私は思っていた[...s.split`()`.join`!`]だけではなく、のを[...s.replace('()','!')]、私はそれがまったく同じバイト数です実現... :)
ケビンCruijssen

@KevinCruijssen主な理由はs.replace('()','!')、最初の出現のみを置き換えることです。
アーナルド

ああ、もちろん。JSの置き換えを忘れるのは、Javaの置換とは異なります。Javaでは.replace、すべての出現.replaceAllが置換され、正規表現が有効になっているすべての出現が置換されます。いつも私は彼らと呼ばれていたなどのネーミングは、Javaでこれらの2つの方法のために非常に悪いと思った.replaceAllし、.regexReplaceAllそれらの線に沿って、または何かを、私はそれはのように短いですcodegolfのために推測.replaceして.replaceAll
ケビンクルイッセン

1
ところで、私はあなたが~自分の答えの最初のバージョンを投稿した直後に同じテクニックを使用していることに気づきました。偉大な心は同じように思う、と思う。:p
アーナウルド

3

クリーン、415バイト

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)

オンラインでお試しください!


3

R225 218バイト

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

オンラインでお試しください!

すべてのテストケースを一度に簡単にテストできるように、TIOの機能にラップされた完全なプログラム。

まず、我々は、フォームの入力を変換するために、正規表現を使用type ...name...;します..."name is"..."type"()次に、関数表記は、優先順位の高い連結演算子を使用してテキストに変換されます。残念ながら、前者は単項演算子として受け入れられないため*、に置き換える必要+があります。残りはeval、オーバーロードされた演算子を使用してRによって行われます。


1
賢い解決策!
J.Doe

3

Perl 6の209の 190 171 162 153バイト

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

オンラインでお試しください!

再帰的な正規表現アプローチ。3バイトのコストで回避できる余分なスペース文字を生成します

説明

{     # 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バイト[249?]

これは250バイトを使用します:

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))

説明:

基本的に、aトークン化された入力であるbufferから読み取ります。評価モードがトリガーされるまでa、トークンをバッファーからスタックに継続的に移動しsます。評価モードでは()、最初に[]バッファから後置操作を使用し、次に*スタックからプレフィックス演算子を使用します。評価モードは、状態が単語のある場所にあるときにトリガーされます(typenameが検出されて消費されるか、エンディング)が検出されて削除されます)。プレフィックス/ポストフィックス演算子が見つからなくなると、評価モードは無効になります。

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
)

注意

「トークン間のどこでもスペースを使用する」を正しく理解している場合:

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))

技術的に有効であり、

249バイト

すべてのトークンの間にスペースがあると仮定します。


2
簡単そうに見えても、これには何時間もかかりました。350文字から始めて、おそらく1時間あたり5〜10バイトをノックしました。確かに私には命がありません。
ニコラスピピトーン

2
私は「私は私の現在のアルゴリズムで最適ヒット- RIP」を考えたとき、私は325程度であったが、その後、何らかの理由で、私はまだ5〜10 /時間をノックすることができた各が続くノックにもかかわらず、「オーケー、これは間違いなく、最適な結果」。250を叩くと、それが君臨253を破った最初だったので、任意だった私はまだ「オーケー、これがあると言うので、にもかかわらず、間違いなく最適な結果」であり、さらに最適化することがあるかもしれません。
ニコラスピピトーン

1

418 410バイト

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

オンラインでお試しください!

説明:

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)、文字625、バイト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

これは、本のコードからC言語からAPLへの翻訳の1つに過ぎません。ブライアンW.カーニングハンとデニスM.リッチーの5.12章「リングアジオC」です。私はそのコードを100%理解していなかったため、そしてAPLについてあまり知らないので、すべてをどのように削減するのかわかりません...それを行使するための関数はfです; エラーのネストされた括弧 '(' ')'は150個しか許可されていないと思います。他の方がエラーをよりよく見るため、これは他のバージョンよりも文字数が少なくても良くないようです。いくつかのテスト:

  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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.