2017-06-02 5 views
2

J'utilise Scala's Parser Combinator framework, étendant la classe RegexParsers. J'ai un jeton identifier qui commence par une lettre et peut contenir des caractères alphabétiques, des tirets, des traits de soulignement et des chiffres, tant que ce n'est pas un des mots réservés. J'ai essayé d'utiliser le not() de l'analyseur pour fonctionner afin d'empêcher l'utilisation de mots réservés, mais il s'agit également d'identifiants correspondants qui sont préfixés par un mot réservé.Comment filtrer les mots réservés dans les combinateurs d'analyseurs?

def reserved = "and" | "or" 

def identifier: Parser[String] = not(reserved) ~> """[a-zA-Z][\.a-zA-Z0-9_-]*""".r 

Cependant, quand j'ai essayé d'analyser un identifiant comme and-today je reçois une erreur disant Expected Failure.

Comment puis-je filtrer uniquement les mots réservés s'il s'agit d'une correspondance complète du jeton et pas seulement d'un préfixe?

Existe-t-il un moyen d'améliorer le rapport d'erreurs dans ce cas lors de l'utilisation de not()? Dans d'autres cas, je reçois l'expression régulière que l'analyseur attend, mais dans ce cas, il dit simplement Failure sans aucun détail.

+1

est-il absolument nécessaire que vous utilisez regex? Vous pouvez utiliser des paramètres de comparaison et de comparaison de motifs combinés comme '.equalsIgnoreCase' pour obtenir le résultat souhaité. –

+0

Vous ne savez pas exactement ce que vous entendez par combinaison de motifs. Oui, le jeton doit correspondre à l'expression régulière, à l'exception de quelques mots réservés (que je veux garder hors de la regex). C'est un analyseur assez important qui utilise le regex dans divers autres endroits. La solution de Maxim a parfaitement fonctionné. – jbx

Répondre

3

Vous pouvez utiliser les deux filterWithError pour filtrer les mots réservés et de personnaliser le message d'erreur comme ceci:

val reservedWords = HashSet("and", "or") 

    val idRegex= """[a-zA-Z][\.a-zA-Z0-9_-]*""".r 

    val identifier = Parser(input => 
     idRegex(input).filterWithError(
     !reservedWords.contains(_), 
     reservedWord => s"YOUR ERROR MESSAGE FOR $reservedWord", 
     input 
    ) 
    ) 
+0

Merci a parfaitement fonctionné. – jbx