Токенізувати мову на основі стека


15

Я працював над іншою мовою для гри в гольф, що називається Stackgoat . У цьому виклику ви будете писати Tokenizer для Stackgoat (або насправді будь-яких загальних мов на основі стека).

Приклади

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

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

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

"foo
['"foo"']

(empty input)
[]

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

Специфікація

Три типи, з якими вам потрібно впоратися:

  • Струни, все , що всередині""
  • Числа, будь-яка послідовність цифр
  • Оператори, будь-який інший символ, крім пробілу

Пробіл по суті ігнорується, якщо він не знаходиться в рядку або не розділяє два числа.

Технічні характеристики:

  • Рядки розмежовані символом a ", а коли \зустрінеться a, слід перейти до наступного символу.
  • Символи задані 'символом a, а символ після символу 'повинен бути перетворений в літеральний рядок. 'a->"a"
  • ' завжди матиме характер після нього
  • Закривальні котирування повинні бути автоматично вставлені

Правила:

  • Не evalдопускається жодна форма

Введення-виведення:

  • Введення даних може здійснюватися через STDIN, параметри функції або еквівалент вашої мови.
  • Вихід повинен бути масивом або найближчим еквівалентом вашої мови.

5
@Doorknob, серйозно?
LegionMammal978

4
@ LegionMammal978 Так, серйозно.
Олексій А.

1
Чи може висновок бути STDOUT?
Дверна ручка

2
@ZachGates Так, так, більшість мов також справляють \ як символ втечі, так що так, вам потрібно буде уникати цього, якщо ваша мова явно потребує цього.
Пуховик

1
Також у першому прикладі перший елемент результату повинен бути '"PPCG"'замість просто "PPCG"?
Фонд позову Моніки

Відповіді:


8

Сітківка , 68 64 63 байт

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

або

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

Я думаю, що це охоплює всі стильні крайові випадки, навіть ті, які не охоплені тестовими кейсами у виклику.

Спробуйте в Інтернеті!


Данг, це коротко. Чудово зроблено!
Фонд позову Моніки

Мені вдалося перевести це у 95-байтну функцію ES6. Було б 80, за винятком того, що регулярні виправлення не працюють навпаки (занадто багато крайових випадків).
Ніл

2

Рубін, 234 байти

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

Я спробував використати find(&:itself)трюк, який я побачив десь, але, мабуть, .itselfце насправді не метод. Також я працюю над гольф-регексом вниз, але це вже не читається.

Якщо нам не доведеться виводити будь-яким фантазійним способом (тобто рядки не потрібно цитувати в масиві), я можу зберегти цілий байт лота:

Ще Рубі, 194 байти:

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

Я впевнений, що можу пограти більше, але я не зовсім впевнений, як.


Невдоволений найближчим часом. Я в якийсь момент почав битися з гольфами, і мені доведеться дражнити його.


0

Python 3, 228 байт

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

Ось приємний, довгий, двоколісний.


Перевірте це на Python 3. Ось кілька прикладів:

$ 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
' ""
['" "', '""']
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.