Tokenizuj język oparty na stosie

15

Pracowałem nad innym językiem gry w golfa o nazwie Stackgoat . W tym wyzwaniu będziesz pisać Tokenizera dla Stackgoat (lub tak naprawdę innych ogólnych języków opartych na stosie).

Przykłady

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

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

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

"foo
['"foo"']

(empty input)
[]

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

Specyfikacja

Trzy typy, z którymi musisz sobie poradzić to:

  • Ciągi, wszystko w środku""
  • Liczby, dowolna sekwencja cyfr
  • Operatory, każdy inny pojedynczy znak oprócz białych znaków

Białe znaki są zasadniczo ignorowane, chyba że znajdują się w ciągu znaków lub nie rozdzielają dwóch liczb.

Specyfikacja string / char:

  • Ciągi są rozdzielane znakiem a ", a po \napotkaniu znaku należy uciec do następnego znaku.
  • Znaki są poprzedzane przez a, 'a po nim znak 'należy przekształcić w literał łańcuchowy.'a->"a"
  • ' zawsze będzie po nim miała postać
  • Cytaty końcowe powinny być wstawiane automatycznie

Zasady:

  • Żadna forma nie evaljest dozwolona

Wejście wyjście:

  • Dane wejściowe można pobierać poprzez STDIN, parametry funkcji lub odpowiednik języka.
  • Wynik powinien być tablicą lub najbliższym odpowiednikiem twojego języka.
Downgoat
źródło
5
@Doorknob, poważnie?
LegionMammal978
4
@ LegionMammal978 Tak, poważnie.
Alex A.
1
Czy wyjście może być w STDOUT?
Klamka
2
@ZachGates Cóż, tak, większość języków posługuje się także \ jako znakiem ucieczki, więc tak, musisz uciec przed tym, jeśli twój język tego potrzebuje.
Downgoat 13.01.16
1
Również w pierwszym przykładzie, czy pierwszy element wyniku powinien być '"PPCG"'zamiast po prostu "PPCG"?
Pozew Fund Moniki w dniu

Odpowiedzi:

8

Retina , 68 64 63 bajtów

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

lub

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

Myślę, że obejmuje to wszystkie funky Edge, nawet te nieobjęte testami w wyzwaniu.

Wypróbuj online!

Martin Ender
źródło
Dang, to jest krótkie. Ładnie wykonane!
Pozew Fund Moniki w dniu
Udało mi się to przetłumaczyć na 95-bajtową funkcję ES6. Byłoby 80, z wyjątkiem tego, że wyrażenia regularne nie działają w drugą stronę (zbyt wiele przypadków na krawędzi).
Neil
2

Rubinowy, 234 bajty

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', '}]"

Próbowałem użyć find(&:itself)sztuczki, którą widziałem ... gdzieś, ale najwyraźniej.itself tak naprawdę nie jest to metoda. Pracuję też nad golfem wyrażenia regularnego, ale jest to już nieczytelne.

Jeśli nie musimy wyprowadzać danych w żaden fantazyjny sposób (tzn. Ciągi nie muszą być cytowane w tablicy), mogę zapisać całe bajty lotta:

Still Ruby, 194 bajty:

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

Jestem pewien, że mogę grać w golfa bardziej, ale nie jestem pewien, jak to zrobić.


Niedoszły wkrótce. W pewnym momencie zacząłem majstrować przy golfie i będę musiał się z nim drażnić.

Powództwo Fund Moniki
źródło
0

Python 3, 228 bajtów

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())],[]))))))

Oto ładny, długi, dwuwarstwowy.


Przetestuj to w Pythonie 3. Oto kilka przykładów:

$ 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
źródło