Tokenisieren Sie eine Stack-basierte Sprache

15

Ich habe an einer anderen Stack-basierten Golfsprache namens Stackgoat gearbeitet . In dieser Herausforderung schreiben Sie einen Tokenizer für Stackgoat (oder wirklich alle allgemeinen Stack-basierten Sprachen).

Beispiele

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

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

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

"foo
['"foo"']

(empty input)
[]

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

Spezifikation

Die drei Typen, mit denen Sie umgehen müssen, sind:

  • Streicher, alles drin""
  • Zahlen, beliebige Ziffernfolge
  • Operatoren, jedes andere einzelne Zeichen außer Leerzeichen

Leerzeichen werden im Wesentlichen ignoriert, es sei denn, sie befinden sich in einer Zeichenfolge oder trennen zwei Zahlen.

String / char spec:

  • Zeichenfolgen werden durch a begrenzt. "Wenn ein \Zeichen auftritt, sollte das nächste Zeichen mit einem Escapezeichen versehen werden.
  • 'Zeichen werden mit einem vorangestellt, und das Zeichen nach dem 'sollte in ein Zeichenkettenliteral umgewandelt werden. 'a->"a"
  • ' wird immer einen Charakter danach haben
  • Das Schließen von Anführungszeichen sollte automatisch erfolgen

Regeln:

  • Keine Form von evalist erlaubt

Input-Output:

  • Die Eingabe kann über STDIN, Funktionsparameter oder die entsprechende Sprache erfolgen.
  • Die Ausgabe sollte ein Array oder die nächstliegende Entsprechung Ihrer Sprache sein.
Downgoat
quelle
5
@Doorknob, im Ernst?
LegionMammal978
4
@ LegionMammal978 Ja, im Ernst.
Alex A.
1
Kann die Ausgabe auf STDOUT erfolgen?
Türklinke
2
@ZachGates Nun ja, die meisten Sprachen behandeln \ auch als Escape-Zeichen. Ja, Sie müssen es maskieren, wenn Ihre Sprache es offensichtlich benötigt.
Downgoat
1
Sollte im ersten Beispiel auch das erste Element des Ergebnisses '"PPCG"'statt nur sein "PPCG"?
Fund Monica's Lawsuit

Antworten:

8

Retina , 68 64 63 Bytes

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

oder

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

Ich denke, das deckt alle funky Edge-Fälle ab, auch die, die nicht von den Testfällen in der Challenge abgedeckt werden.

Probieren Sie es online!

Martin Ender
quelle
Verdammt, das ist kurz. Schön gemacht!
Fund Monica's Lawsuit
Ich konnte dies in eine 95-Byte-ES6-Funktion übersetzen. Es wäre 80 gewesen, außer dass die regulären Ausdrücke nicht umgekehrt funktionieren (zu viele Randfälle).
Neil
2

Ruby, 234 Bytes

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

Ich habe versucht, den find(&:itself)Trick zu verwenden, den ich gesehen habe ... irgendwo, aber anscheinend .itselfist es keine Methode. Außerdem arbeite ich daran, die Regex herunterzuspielen, aber sie ist bereits unlesbar.

Wenn wir nicht auf ausgefallene Weise ausgeben müssen (dh Strings müssen nicht in Anführungszeichen gesetzt werden), kann ich eine ganze Menge Bytes sparen:

Immer noch Ruby, 194 Bytes:

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

Ich bin mir sicher, dass ich mehr Golf spielen kann, aber ich bin mir nicht ganz sicher, wie.


Ungolfed kommt bald. Irgendwann fing ich an, direkt mit den Golfspielern zu spielen, und ich muss es herausziehen.

Fund Monica Klage
quelle
0

Python 3, 228 Bytes

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

Hier ist ein schöner langer Doppelliner.


Testen Sie es in Python 3. Hier sind einige Beispiele:

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