Pegjs: Autoriser le retour du résultat de correspondance d'une expression spécifique dans une règle sans action

Créé le 23 mai 2016  ·  10Commentaires  ·  Source: pegjs/pegjs

Il est très courant de devoir renvoyer une valeur à partir de l'un des non-terminaux d'une règle ou à l'intérieur d'une sous-règle entre parenthèses. Par exemple:

varDecl = type:type id:ID init:( EQ e:expr {return e} )?
                { return scopedAST('VARDECL', {type, id, init}) }

Dans ce cas, j'avais besoin du expr étiqueté comme e à l'intérieur du niveau de parenthèse init pour une phrase facultative dans la langue. Je n'avais pas besoin du "mot de bruit" EQ dans le cadre de la valeur renvoyée.

Si le langage PEGjs avait un symbole à utiliser pour marquer les terminaux comme le expr ci-dessus afin qu'ils, et seulement eux, soient la valeur renvoyée par une règle ou une sous-règle de grammaire, ce cas serait plus simple.

Pour réécrire mon exemple ci-dessus :

varDecl = type:type id:ID init:( EQ ^expr )?
                { return scopedAST('VARDECL', {type, id, init}) }

Notez l'utilisation de ^ pour marquer la expr à l'intérieur de la sous-règle optionnelle init entre parenthèses pour désigner ce qui est lié à init . Cela simplifie de nombreuses situations avec et sans la sous-règle entre parenthèses illustrée dans cet exemple.

Merci d'avoir créé un outil si merveilleusement simple, élégant et puissant. J'adore les PEGjs ! :le sourire:

feature

Tous les 10 commentaires

J'adore cette idée ! ^ est également très intuitif.

Cela pourrait également fonctionner sur des règles non imbriquées :

WhiteSpacedIdentifier = WhiteSpace? identifier:Identifier WhiteSpace {return identifier;}
// becomes
WhiteSpacedIdentifier = WhiteSpace? ^Identifier WhiteSpace?

Très lisible ! Vraisemblablement, l'utilisation de plusieurs ^ fonctionnerait également, de sorte que :

a = ^b  c  ^d  e

Retournerait [b, d] ? Semble avoir du sens.

De même, il semble logique que si elles sont mélangées avec des captures nommées, les règles ^ soient ignorées, donc

x = a ^b foo:c { return foo; }

Je reviendrais seulement c.

Oh cette idée multiple est excellente. Le mélange avec des captures nommées doit être
une erreur.

Le mar. 5 juil. 2016, 01:07 Graham Wakefield [email protected]
a écrit:

Très lisible ! Vraisemblablement, l'utilisation de plusieurs ^ fonctionnerait également, de sorte que :

a = ^bc ^de

Retournerait [b, d] ? Semble avoir du sens.

De même, il semble logique que s'il est mélangé avec des captures nommées, le ^
les règles sont ignorées :

x = a ^b foo:c { return foo; }

-
Vous recevez ceci parce que vous avez créé le fil.

Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/pegjs/pegjs/issues/427#issuecomment -230413015, ou couper le son
le fil
https://github.com/notifications/unsubscribe/ABC26k8v0DIzuWUlkoDZGm2ep10Y5bcMks5qShDAgaJpZM4IkuA9
.

Je suis tout à fait d'accord que le modèle décrit est assez courant. Avoir un moyen de l'exprimer sans action a du sens.

Ce dont je ne suis pas si sûr de la solution proposée (l'opérateur ^ ). L'utilisation d'un caractère spécial dont la signification n'est pas immédiatement évidente est toujours problématique et ajoute à la courbe d'apprentissage. Il est également possible que le personnage soit mieux utilisé à d'autres fins. Enfin, je n'aime pas trop l'idée de mettre des choses qui n'influencent pas directement l'analyse dans les expressions. On peut affirmer qu'il existe déjà une instance de cela - l'opérateur $ - et je serais d'accord. Mais je ne sais pas si l'ajout de $ n'était pas une (petite) erreur. Si c'est le cas, j'aimerais éviter d'en refaire.

J'y réfléchirai plus en profondeur après la 1.0.0.

Encore un peu de matière à réflexion : puisque ^ et les expressions étiquetées entrent en collision ( @grrrwaaa suggèrent d'ignorer les ^ ), que diriez-vous au lieu de marquer le résultat, on pourrait marquer les expressions _ignorées_, par exemple (suggestion de syntaxe !) en fournissant une étiquette vide :

WhiteSpacedIdentifier = WhiteSpace? identifier:Identifier WhiteSpace {return identifier;}
// becomes
WhiteSpacedIdentifier = :WhiteSpace? Identifier :WhiteSpace?

Là, pas de nouvelle syntaxe (on a déjà : ), juste un peu d'extension sur la sémantique :

  • autoriser les étiquettes vides (appelez ces expressions « anonymes » ?)
  • s'il n'existe qu'une seule capture non anonyme, ne générez pas de tableau de correspondances d'expressions, renvoyez plutôt la seule correspondance

Dans ce cas, plus cohérent marquera avec des "étiquettes" vides les expressions qui devront être renvoyées en conséquence. Il ne s'agit d'ailleurs pas de casser la sémantique existante : l'étiquette existe, mais elle est sans nom ; comme les étiquettes sont introduites pour accéder au résultat, il est tout à fait logique que les étiquettes sans nom deviennent automatiquement résultat. L'existence simultanée d'étiquettes automatiques et concrètes est interdite. S'il n'existe qu'une seule étiquette automatique, alors le résultat unique, mais pas un tableau avec un élément, doit être renvoyé car un tel comportement est plus demandé.

@Mingun

Pourquoi ne pas simplement renvoyer n'importe quelle étiquette ?
start = "{" :expr "}" // return expr
start = "{" label:expr "}" // return label
Je pense qu'il est logique que si vous "étiquetez" quelque chose, vous vouliez en faire quelque chose (par exemple, le retourner).

D'un autre côté, pourquoi des règles comme start = ex:expr :expr devraient générer une erreur ?
Peut-être devrait-il faire quelque chose de similaire à la variable d'arguments des fonctions de javascript ? Par exemple, start = ex:expr :expr devrait renvoyer [ex, expr] . Lorsque vous avez une action, il devrait y avoir des variables étiquetées & arguments ( start = ex:expr :expr { return [ex, arguments[0], ex] } )

@alanmimms J'aime cette idée. Nous n'avons pas besoin de créer un nom (une variable/une étiquette) juste pour renvoyer une valeur simple.
Je pense qu'une étiquette sans nom ( :expr ) serait mieux que ^expr

Pourquoi ne pas simplement renvoyer n'importe quelle étiquette ?

@nedzadarek car si vous donnez un nom à une expression, il est plus probable que vous ne l'

Malheureusement, il faut reconnaître que les labels automatiques dans ce regard dans ce qu'ils sont proposés par @opatut , c'est impossible à mettre en place car cela crée une ambiguïté dans la grammaire. L'exemple élémentaire :

start = a :b;// `a` - it is rule reference or label?
a = .;
b = .;

Donc, à cette fin, vous devez sélectionner un autre personnage. Pour le moment, vous avez le choix entre : ~ , (backslash) , @ , # , % , ^ , - , | , \ et , .


Une autre solution -- introduire quelques pseudo-actions -- un raccourci pour la création de fonctions simples pour le retour, par exemple, {=>[]} peut signifier _"collecter les résultats étiquetés de la séquence et les renvoyer dans le tableau"_ , et {=>{}} -- le même, mais pour retourner un objet, avec les clés égales aux noms des étiquettes. Mais la mise en œuvre de ce comportement ne nécessite pas d'extension de grammaire et peut être tout à fait réalisée par des plug-ins. Je dirais même qu'il est plus préférable d'avoir une telle implémentation par plug-ins :

start1 = a:'a' b c d:. {=>[]};// returns ['a', <d value>]
start2 = a:'a' b c d:. {=>{}};// returns { a: 'a', d: <d value> }

@Mingun

car si vous donnez un nom à une expression, il est plus probable que vous ne l'utilisiez pas dans une expression non triviale. Au moins, le nom est important pour vous, sinon vous ne le donneriez pas, vraiment ?

Oui, le nom est important => je veux l'utiliser => je veux le rendre.
Quel est le problème avec les expressions non triviales ?

Malheureusement, il faut reconnaître que les labels automatiques dans ce regard dans ce qu'ils sont proposés par @opatut , c'est impossible à mettre en place car cela crée une ambiguïté dans la grammaire. L'exemple élémentaire :

Oui.
Je suppose que ::expression est aussi déroutant ? @dmajda

Fermé en tant que doublon de #235

Edit: Ajout d'une note au commentaire d'OP sur # 235 qui fait référence à ce problème

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

gatsbyz picture gatsbyz  ·  3Commentaires

futagoza picture futagoza  ·  6Commentaires

marek-baranowski picture marek-baranowski  ·  6Commentaires

dmajda picture dmajda  ·  7Commentaires

emmenko picture emmenko  ·  15Commentaires