Manipulação de condições de erro em Lex, em vez de Yacc?
-
16-09-2019 - |
Pergunta
Suponha que eu tenho uma expressão regular lex como
[aA][0-9]{2,2}[pP][sS][nN]? { return TOKEN; }
Se um usuário digita ??p>
A75PsN
A75PS
Ele irá corresponder
Mas se um usuário diz algo como
A75PKN
Eu gostaria que erro e dizer "Character K não reconhecido, esperando S"
O que estou fazendo agora é apenas escrevê-lo como
let [a-zA-Z]
num [0-9]
{let}{num}{2,2}{let}{2,3}
E, em seguida, essencialmente re-lexing a corda no Yacc para que eu possa ter condições de erro significativas
Como posso resolver isso?
A única coisa que posso pensar é usar grupos nomeados?
Solução
Wow! esquema interessante.
Se você estiver indo para detectar que no analisador léxico, você teria que ter um catch-all regra que lida com 'qualquer seqüência de outra forma não reconhecido' e produz uma mensagem de erro.
A determinação de que era a K que causou o problema vai ser o inferno.
[^aA][0-9]{2,2}[pP][sS][nN]? { report_error(); return ERROR; }
[aA][0-9]{2,2}[^pP][sS][nN]? { report_error(); return ERROR; }
[aA][0-9]{2,2}[pP][^sS][nN]? { report_error(); return ERROR; }
[aA][0-9]{2,2}[pP][sS][^nN] { report_error(); return ERROR; }
Observe a colocação dos sinais de intercalação, e a ausência do ponto de interrogação! Lidar com os não-dígitos, ou muitos dígitos, ou muito poucos dígitos - urgh
Geralmente, você seria melhor de reconhecer todos os 'identificadores' e, em seguida, validar quais são OK:
[a-zA-Z][0-9]{2,2}[a-zA-Z]{2,5} { return validate_id_string(); }
Escolha o seu veneno que você permitir que a rotina de validação; ele decide se o que foi digitado foi OK ou não, e seus controles valor de retorno o que o Lex regra retorna para a gramática. Esta é uma maneira de distinguir palavras-chave de identificadores também.
generalizar e simplificar a expressão regular para atender o que realmente se passa.