Tokenize una lingua basata su stack


15

Ho lavorato su un altro linguaggio di golf basato su stack chiamato Stackgoat . In questa sfida dovrai scrivere un tokenizer per Stackgoat (o davvero qualsiasi linguaggio generale basato su stack).

Esempi

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

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

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

"foo
['"foo"']

(empty input)
[]

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

specificazione

I tre tipi che dovrai gestire sono:

  • Stringhe, qualsiasi cosa all'interno""
  • Numeri, qualsiasi sequenza di cifre
  • Operatori, qualsiasi altro singolo carattere oltre agli spazi bianchi

Lo spazio bianco viene essenzialmente ignorato a meno che non sia all'interno di una stringa o separa due numeri.

Specifiche stringa / carattere:

  • Le stringhe sono delimitate da a "e quando \si incontra a, il carattere successivo deve essere evitato.
  • I caratteri sono preceduti da a 'e il carattere dopo che 'devono essere convertiti in una stringa letterale. 'a->"a"
  • ' avrà sempre un personaggio dopo di esso
  • Le virgolette di chiusura devono essere inserite automaticamente

Regole:

  • Non evalè consentita alcuna forma di

Input Output:

  • L'input può essere preso tramite STDIN, i parametri di funzione o l'equivalente della tua lingua.
  • L'output dovrebbe essere un array o l'equivalente più vicino alla tua lingua.

5
@Doorknob, sul serio?
LegionMammal978,

4
@ LegionMammal978 Sì, sul serio.
Alex A.

1
L'output può essere su STDOUT?
Maniglia della porta

2
@ZachGates Beh, sì, anche la maggior parte delle lingue gestisce \ come carattere di escape, quindi sì, dovrai evitarlo se la tua lingua ne ha ovviamente bisogno.
Downgoat,

1
Inoltre, nel primo esempio, dovrebbe essere il primo elemento del risultato '"PPCG"'anziché solo "PPCG"?
Finanzi la causa di Monica il

Risposte:


8

Retina , 68 64 63 byte

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

o

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

Penso che questo copra tutti i casi limite funky, anche quelli non coperti dai casi di test nella sfida.

Provalo online!


Dang, questo è breve. Ben fatto!
Finanzia la causa di Monica il

Sono stato in grado di tradurre questo in una funzione ES6 a 95 byte. Sarebbe stato 80 tranne per il fatto che i regexps non funzionano al contrario (troppi casi limite).
Neil,

2

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

Ho provato a usare il find(&:itself)trucco che ho visto ... da qualche parte, ma a quanto pare .itselfnon è in realtà un metodo. Inoltre, sto lavorando sul golf down della regex, ma è già illeggibile.

Se non è necessario eseguire l'output in modo elaborato (ovvero le stringhe non devono essere citate nell'array), è possibile salvare un sacco di byte:

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

Sono sicuro di poterlo giocare di più, ma non sono sicuro di come.


Ungolfed in arrivo. Ho iniziato a giocherellare con il golf direttamente ad un certo punto e dovrò stuzzicarlo.


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

Ecco una bella, lunga, due linee.


Provalo in Python 3. Ecco alcuni esempi:

$ 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
' ""
['" "', '""']
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.