Tokenize bahasa Berbasis Stack

15

Saya telah bekerja di lain tumpukan berbasis bahasa golf disebut Stackgoat . Dalam tantangan ini Anda akan menulis Tokenizer untuk Stackgoat (atau benar-benar bahasa berbasis stack umum).

Contohnya

"PPCG"23+
["PPCG", '23', '+']

'a "bc" +
['"a"', '"bc"', '+']

12 34+-"abc\"de'fg\\"
['12', '34', '+', '-', '"abc\"de'fg\\"']

"foo
['"foo"']

(empty input)
[]

' ""
['" "', '""']

Spesifikasi

Tiga jenis yang perlu Anda tangani adalah:

  • String, apa pun di dalamnya""
  • Bilangan, urutan angka apa pun
  • Operator, karakter tunggal lainnya selain spasi putih

Whitespace pada dasarnya diabaikan kecuali dalam string atau memisahkan dua angka.

String / spesifikasi char:

  • String dibatasi oleh a ", dan ketika \ditemui, karakter selanjutnya harus melarikan diri.
  • 'Karakter diawali dengan a dan karakter setelah 'harus dikonversi menjadi string literal. 'a->"a"
  • ' akan selalu memiliki karakter setelahnya
  • Kutipan penutup harus dimasukkan secara otomatis

Aturan:

  • Tidak ada bentuk evalyang diizinkan

Input output:

  • Input dapat diambil melalui STDIN, parameter fungsi, atau yang setara dengan bahasa Anda.
  • Output harus berupa array atau padanan terdekat bahasa Anda.
Downgoat
sumber
5
@ Doorknob, serius?
LegionMammal978
4
@ LegionMammal978 Ya, serius.
Alex A.
1
Bisakah output ke STDOUT?
Gagang Pintu
2
@ZachGates Ya, sebagian besar bahasa memang menangani \ sebagai karakter pelarian juga, jadi ya, Anda perlu menghindarinya jika bahasa Anda membutuhkannya dengan jelas.
Downgoat
1
Juga, dalam contoh pertama, haruskah elemen pertama hasilnya '"PPCG"'bukannya adil "PPCG"?
Dana Gugatan Monica

Jawaban:

8

Retina , 68 64 63 byte

M!s`"(\\.|[^"])*"?|'.|\d+|\S
ms`^'(.)|^"(([^\\"]|\\.)*$)
"$1$2"

atau

s`\s*((")(\\.|[^"])*(?<-2>")?|'.|\d+|.)\s*
$1$2¶
\ms`^'(.)
"$1"

Saya pikir ini mencakup semua kasus tepi yang funky, bahkan yang tidak dicakup oleh kasus uji dalam tantangan.

Cobalah online!

Martin Ender
sumber
Dang, ini pendek. Bagus sekali!
Dana Gugatan Monica
Saya dapat menerjemahkan ini ke dalam fungsi ES6 95 byte. Itu akan menjadi 80 kecuali bahwa regexps tidak bekerja sebaliknya (terlalu banyak kasus tepi).
Neil
2

Ruby, 234 byte

puts"[#{$stdin.read.scan(/("(?:(?<!\\)\\"|[^"])+(?:"|$))|'(.)|(\d+)|(.)/).map{|m|(m[0]?(m[0].end_with?('"')?m[0]: m[0]+'"'): m[1]?"\"#{m[1]}\"": m.compact[0]).strip}.reject(&:empty?).map{|i|"'#{/\d+|./=~i ?i: i.inspect}'"}.join', '}]"

Saya mencoba menggunakan find(&:itself) trik yang saya lihat ... di suatu tempat, tetapi ternyata .itselfsebenarnya bukan metode. Juga, saya sedang berusaha menurunkan regex, tapi itu sudah tidak bisa dibaca.

Jika kita tidak perlu menampilkan dengan cara mewah (yaitu string tidak harus dikutip dalam array) Saya dapat menyimpan seluruh byte lotta:

Still Ruby, 194 byte:

p$stdin.read.scan(/("(?:(?<!\\)\\"|[^"])+(?:"|$))|'(.)|(\d+)|(.)/).map{|m|(m[0]?(m[0].end_with?('"')?m[0]: m[0]+'"').gsub(/\\(.)/,'\1'): m[1]?"\"#{m[1]}\"": m.compact[0]).strip}.reject(&:empty?)

Saya yakin saya bisa bermain golf lebih banyak, tetapi saya tidak yakin bagaimana caranya.


Ungolfed segera hadir. Saya mulai mengutak-atik golf langsung di beberapa titik dan saya harus menggodanya.

Dana Gugatan Monica
sumber
0

Python 3, 228 byte

import re;L=list
print(L(map(lambda i:i+'"'if i[0]=='"'and not i[-1]=='"'else i,map(lambda i:'"%s"'%i[1]if i[0]=="'"else i,filter(None,sum([L(i)for i in re.findall('(\'.)|(".*")|(\d+)|([^\w\"\'\s\\\])|(".*"?)',input())],[]))))))

Ini bagus, panjang, dua baris.


Uji dengan Python 3. Ini beberapa contoh:

$ python3 test.py
"PPCG"23+
['"PPCG"', '23', '+']

$ python3 test.py
'a "bc" +
['"a"', '"bc"', '+']

$ python3 test.py
12 34+-"abc"de'fg\"
['12', '34', '+', '-', '"abc"de\'fg\\"']

$ python3 test.py
"foo
['"foo"']

$ python3 test.py

[]

$ python3 test.py
' ""
['" "', '""']
Zach Gates
sumber