Tokenizar un lenguaje basado en pila


15

He estado trabajando en otro lenguaje de golf basado en pila llamado Stackgoat . En este desafío, escribirás un Tokenizer para Stackgoat (o realmente cualquier lenguaje general basado en pila).

Ejemplos

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

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

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

"foo
['"foo"']

(empty input)
[]

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

Especificación

Los tres tipos que necesitará manejar son:

  • Cuerdas, cualquier cosa dentro""
  • Números, cualquier secuencia de dígitos
  • Operadores, cualquier otro caracter aparte del espacio en blanco

El espacio en blanco se ignora esencialmente a menos que esté dentro de una cadena o separe dos números.

String / char spec:

  • Las cadenas están delimitadas por a ", y cuando \se encuentra a, se debe escapar al siguiente carácter.
  • Los caracteres están precedidos por a 'y el carácter después del 'debe convertirse en un literal de cadena. 'a->"a"
  • ' siempre tendrá un personaje después
  • Las comillas de cierre deben insertarse automáticamente

Reglas:

  • No evalse permite ninguna forma de

De entrada y salida:

  • La entrada se puede tomar a través de STDIN, parámetros de función o el equivalente de su idioma.
  • La salida debe ser una matriz o el equivalente más cercano de su idioma.

55
@Pomo de la puerta, ¿en serio?
LegionMammal978

44
@ LegionMammal978 Sí, en serio.
Alex A.

1
¿La salida puede ser STDOUT?
Pomo de la puerta

2
@ZachGates Bueno, sí, la mayoría de los idiomas también manejan \ como un carácter de escape, así que sí, tendrá que escapar de eso si su idioma lo necesita obviamente.
Downgoat

1
Además, en el primer ejemplo, ¿el primer elemento del resultado debería ser en '"PPCG"'lugar de justo "PPCG"?
Financia la demanda de Mónica el

Respuestas:


8

Retina , 68 64 63 bytes

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

o

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

Creo que esto cubre todos los casos de borde funky, incluso aquellos no cubiertos por los casos de prueba en el desafío.

Pruébalo en línea!


Dang, esto es corto. ¡Bien hecho!
Financia la demanda de Mónica el

Pude traducir esto en una función ES6 de 95 bytes. Hubiera sido 80, excepto que las expresiones regulares no funcionan al revés (demasiados casos extremos).
Neil

2

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

Intenté usar el find(&:itself)truco que vi ... en alguna parte, pero aparentemente .itselfno es en realidad un método. Además, estoy trabajando en el golf de la expresión regular hacia abajo, pero ya no se puede leer.

Si no tenemos que emitir de manera elegante (es decir, las cadenas no tienen que ser citadas en la matriz), puedo guardar una gran cantidad de bytes:

Todavía 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?)

Estoy seguro de que puedo jugar más al golf, pero no estoy muy seguro de cómo.


Ungolfed próximamente. Comencé a jugar con el golf directamente en algún momento y tendré que sacarlo.


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

Aquí hay un bonito, largo, de dos líneas.


Pruébelo en Python 3. Aquí hay algunos ejemplos:

$ 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
' ""
['" "', '""']
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.