Используйте PLY для соответствия обычной строке

Я пишу парсер, используя PLY. Вопрос похож на этот Как написать регулярное выражение для соответствия строковому литералу, где экранирование является удвоением символа кавычки?. Однако я использую двойные кавычки для открытия и закрытия строки. Например:

"Я не знаю, что такое \"А\""

Я определяю обычный строковый лексер как:

t_NORMSTRING = r'"([^"\n]|(\\"))*"$'

и у меня есть другой лексер для переменной:

def t_VAR(t):
   r'[a-zA-Z_][a-zA-Z_0-9]*'

Проблема в том, что мой лексер не распознает «Я не знаю, что такое \"A\"» как токен NORMSTRING. Он возвращает ошибку

Illegal character '"' at 1
Syntax error at 'LexToken(VAR,'do',10,210)'

Пожалуйста, дайте мне знать, почему это неправильно.


person Loi.Luu    schedule 02.01.2014    source источник


Ответы (1)


Изучив эту проблему с помощью небольшой программы PLY, я думаю, что ваша проблема связана с различиями между обработкой raw и не необработанные строки при обработке данных, а не при разборе PLY и самом лексическом сопоставлении. (Кроме того, между python V2 и python v3 в этой области обработки строк я ограничил свой код python v2).

Вы получаете ошибку, которую видите, только если используете не необработанную строку или используете input вместо raw_input. Это показано в моем примере кода и результатах ниже:

Команды:

$ python --version
Python 2.7.5
$ python string.py
import sys

if ".." not in sys.path: sys.path.insert(0,"..")
import ply.lex as lex
tokens = (
    'NORMSTRING',
    'VAR'
)

def t_NORMSTRING(t):
     r'"([^"\n]|(\\"))*"$'
     print "String: '%s'" % t.value

def t_VAR(t):
   r'[a-zA-Z_][a-zA-Z_0-9]*'

t_ignore = ' \t\r\n'

def t_error(t):
    print "Illegal character '%s'" % t.value[0]
    t.lexer.skip(1)

lexer = lex.lex()

data = r'"I do not know what \"A\" is"'

print "Data: '%s'" % data

lexer.input(data)

while True:
   tok = lexer.token()
   if not tok: break
   print tok

Выход:

Data: '"I do not know what \"A\" is"'
String: '"I do not know what \"A\" is"'
data = '"I do not know what \"A\" is"'

print "Data: '%s'" % data

lexer.input(data)

while True:
   tok = lexer.token()
   if not tok: break
   print tok

Выход:

Data: '"I do not know what "A" is"'
Illegal character '"'
Illegal character '"'
String: '" is"'
lexer.input(raw_input("Please type your line: "));

while True:
   tok = lexer.token()
   if not tok: break
   print tok

Выход:

Please type your line: "I do not know what \"A\" is"
String: '"I do not know what \"A\" is"'
lexer.input(input("Please type your line: "));

while True:
   tok = lexer.token()
   if not tok: break
   print tok

Выход:

Please type your line: "I do not know what \"A\" is"
Illegal character '"'
Illegal character '"'

И последнее замечание: вам, вероятно, не нужна якорь строки $ в регулярном выражении.

person Brian Tompsett - 汤莱恩    schedule 23.04.2015