Токенизация стекового языка


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"
  • ' после него всегда будет персонаж
  • Закрывающие кавычки должны быть вставлены автоматически

Правила:

  • Форма evalне разрешена

Ввод, вывод:

  • Ввод может быть сделан через STDIN, параметры функции или эквивалент вашего языка.
  • Вывод должен быть массивом или ближайшим эквивалентом вашего языка.

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

4
@ LegionMammal978 Да, серьезно.
Алекс А.

1
Может ли вывод быть STDOUT?
Дверная ручка

2
@ZachGates Ну да, большинство языков тоже обрабатывают \ как escape-символ, так что да, вам придется избегать этого, если ваш язык явно нуждается в этом.
Даунгейт

1
Кроме того, в первом примере должен быть первый элемент результата '"PPCG"'вместо просто "PPCG"?
Фонд Моника иск

Ответы:


8

Retina , 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самом деле это не метод. Кроме того, я работаю над игрой в regex, но это уже невозможно прочитать.

Если нам не нужно выводить каким-либо причудливым способом (т. Е. Строки не должны заключаться в кавычки в массиве), я могу сохранить целые байты:

Still Ruby, 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?)

Я уверен, что могу играть в гольф больше, но я не совсем уверен, как.


Скоро выйдет Ungolfed. В какой-то момент я начал возиться с игрой в гольф, и мне придется дразнить ее.


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.