Pegjs: Raccourci pour les actions sémantiques

Créé le 10 sept. 2018  ·  13Commentaires  ·  Source: pegjs/pegjs

Ce serait bien d'ajouter un raccourci pour les actions sémantiques.

Disons qu'au lieu d'écrire { return value } , nous écrivons, par exemple { extract } qui est défini dans l'initialiseur.

Par exemple:

{
  function extract(value) {
    return value;
  }
  function concat(head, tail) {
    return head ? [head].concat(tail) : [];
  }
  function toAddExpr(head, tail) {
    return { type: 'addExpr', expressions: concat(head, tail) };
  }
}

List
  = '(' _ head:Item? tail:( _ ',' _ value:Item { extract } )* _ ')' { concat }

// Another kind of list
Add
  = '(' _ head:Multiply? tail:( _ '+' _ value:Multiply { extract } )* _ ')' { toAddExpr }

Tout d'abord, cela nous permettra de réutiliser des fonctions... d'une manière plus agréable :smile:
Deuxièmement, cela rendra notre grammaire un peu plus lisible.

Je pense que cela sera également plus utile lorsque l'expression contenue dans le raccourci d'action est une expression membre { foo.bar.baz } au lieu d'un simple identifiant { foo } . Pour que les rédacteurs de grammaire puissent organiser leurs fonctions à l'intérieur d'un objet ou même d'un module.

discussion feature

Commentaire le plus utile

En fait, j'ai pensé que ces changements pourraient bien fonctionner :

CodeBlock "code block"
  = "=>" _ expession:CallExpression {
       return `return ${ expession };`;
     }
  / "{" <strong i="6">@Code</strong> "}"
  / "{" { error("Unbalanced brace."); }

// Will be based on ECMAScript's CallExpression
CallExpression
  = ...
  / MemberExpression

// Will be based on ECMAScript's MemberExpression
MemberExpression
  = ...
  / ValidIdentifier

// Change `LabelIdentifier` into `ValidIdentifier`

Cette méthode nécessitera toujours d'intégrer des éléments tels que les expressions primaires d'ECMAScript (nombres, booléens, tableaux, etc.) à utiliser comme arguments, vous devrez donc déterminer soigneusement ce qu'il faut ajouter.


supports d'équilibrage et accolades

Cela ne sera pas corrigé tant qu'un analyseur JavaScript approprié ne sera pas intégré à l'analyseur PEG.js, mais pour être honnête, j'hésite un peu à ce sujet car il existe quelques projets de plug-in qui génèrent des analyseurs dans d'autres langages (C, PHP, TypeScript , etc), et je travaille également sur un langage informatique dans lequel j'espère générer un jour des parseurs.


Parallèlement à _PEG.js v0.12_, je travaillerai sur OpenPEG , qui offrira un package NPM qui est essentiellement une version allégée de PEG.js sans aucune génération de JavaScript et d'analyseur, mais suffisamment de fonctionnalités pour que les projets basés sur JavaScript comme PEG.js peut l'utiliser comme backend. Lorsque _v0.12_ sortira, j'essaierai de m'assurer que tous les projets de plug-in qui génèrent des analyseurs personnalisés sont informés d'OpenPEG et, avant la v1, implémenter un analyseur complet ECMAScript 2015 dans l'analyseur de grammaire PEG.js.

Tous les 13 commentaires

Idée intéressante, mais personnellement, je ne pense pas que ce serait un moyen plus clair, car il n'est pas évident quels arguments sont transmis à la fonction. De plus, si vous avez besoin de passer un paramètre "personnalisé", vous devez les mélanger avec des appels de fonction réguliers, de sorte qu'il n'aura pas l'air aussi propre que dans les cas les plus simples.

Quelqu'un au #235 a suggéré la syntaxe => pour accompagner les fonctions fléchées, ce que j'ai trouvé assez propre et concis.

  = '(' expr:some_expression ')' => expr
  ;

Je penche pour choisir l'un des éléments suivants pour la syntaxe des raccourcis :

  • => expr; _(nécessite un support pour la syntaxe)_
  • { => expr } _(utilisable maintenant, mais doit être déballé)_
  • { > expr } _(nécessite un support pour la syntaxe)_

Je n'ai pas encore décidé, donc c'est ouvert à la discussion.

Quant à ce que veut l'OP, il serait préférable d'implémenter un plugin (après ou avant que la syntaxe abrégée ne soit décidée) qui utilise Acorn ou @babel/parser pour déballer l'identifiant ou l'expression membre, le transformer en une expression d'appel tout en ajoutant le labels comme arguments et renvoient le code généré.

=> expr;

Le meilleur à mon avis.

{ => expr }

Conflits avec la syntaxe Javascript IMO. Comme il se trouve à l'intérieur de { } vous vous attendez à ce qu'il s'agisse d'une fonction flèche complète ( () => ).

{ > expr}

Un peu orthogonal à toute autre syntaxe dans PegJS ou Javascript, ne lit pas immédiatement "cela renvoie une valeur, un raccourci" IMO - principalement parce que c'est entre accolades, je pense. Même argument que {=> expr} , vous vous attendez à ce que Javascript soit présent.


De plus, l'ajout d'une syntaxe non JS dans {} est un problème pour les surligneurs de syntaxe, les linters, etc. Je le déconseille.

Si je peux suggérer encore une autre option, peut-être > par lui-même (pas à l'intérieur d'un bloc de prédicat). Cela aide à garder les choses alignées lorsque vous espacez verticalement les règles :

    = foo:bar qux:(' '+ @qix)+
    > {foo, qux}
    ;

ainsi qu'en ligne

some_rule = foo:bar qux:(' '+ @qix)+ > {foo, qux};

Pourquoi le point-virgule est-il nécessaire pour '=>' ? J'aimerais retourner une valeur dans du code imbriqué au lieu d'utiliser buildList() par exemple :

  = "(" _ head:Expression _ tail:("," _ expr:Expression => expr)* ")" {
      return [head, ...tail]
    }

Je trouve cela plus propre que d'utiliser un index magique (ci-dessous). Une autre option est la possibilité de faire référence à des étiquettes imbriquées. par exemple ("," _ tail:Expression)* ")"

  = "(" _ head:Expression _ tail:("," _ Expression)* ")" {
      return buildList(head, tail, 2)
    }

Je regardais parser.pegjs, et je vois autour de la ligne 434 il y a CodeBlock. Que faudrait-il faire pour l'essayer? La règle Code lit simplement SourceCharacter, qui est juste '.'

CodeBlock "code block"
  = "=>" __ <strong i="13">@Code</strong> // this?
  / "{" <strong i="14">@Code</strong> "}"

@mikeaustin Oui, c'est à peu près juste, mais il n'y a aucun moyen pour qu'il sache où terminer cette séquence alors, donc consommera tout après =>

Peut-être que "Code" pourrait être un peu plus intelligent, en équilibrant les crochets et les accolades, et en gérant LineTerminator ? Il n'aurait pas besoin de connaître JavaScript complet, mais cela peut être plus difficile qu'il n'y paraît.

En fait, j'ai pensé que ces changements pourraient bien fonctionner :

CodeBlock "code block"
  = "=>" _ expession:CallExpression {
       return `return ${ expession };`;
     }
  / "{" <strong i="6">@Code</strong> "}"
  / "{" { error("Unbalanced brace."); }

// Will be based on ECMAScript's CallExpression
CallExpression
  = ...
  / MemberExpression

// Will be based on ECMAScript's MemberExpression
MemberExpression
  = ...
  / ValidIdentifier

// Change `LabelIdentifier` into `ValidIdentifier`

Cette méthode nécessitera toujours d'intégrer des éléments tels que les expressions primaires d'ECMAScript (nombres, booléens, tableaux, etc.) à utiliser comme arguments, vous devrez donc déterminer soigneusement ce qu'il faut ajouter.


supports d'équilibrage et accolades

Cela ne sera pas corrigé tant qu'un analyseur JavaScript approprié ne sera pas intégré à l'analyseur PEG.js, mais pour être honnête, j'hésite un peu à ce sujet car il existe quelques projets de plug-in qui génèrent des analyseurs dans d'autres langages (C, PHP, TypeScript , etc), et je travaille également sur un langage informatique dans lequel j'espère générer un jour des parseurs.


Parallèlement à _PEG.js v0.12_, je travaillerai sur OpenPEG , qui offrira un package NPM qui est essentiellement une version allégée de PEG.js sans aucune génération de JavaScript et d'analyseur, mais suffisamment de fonctionnalités pour que les projets basés sur JavaScript comme PEG.js peut l'utiliser comme backend. Lorsque _v0.12_ sortira, j'essaierai de m'assurer que tous les projets de plug-in qui génèrent des analyseurs personnalisés sont informés d'OpenPEG et, avant la v1, implémenter un analyseur complet ECMAScript 2015 dans l'analyseur de grammaire PEG.js.

FWIW, j'ai commencé à utiliser des littéraux de modèle pour cela. Cela m'aide également avec la coloration syntaxique de JS par mon éditeur de texte...

exports = module.exports = functionBodies`${grammarScript}
...
objectText =
    head:word
    rest:(_txt_ word)*
    ${f=>{
        return new Txt(rest.reduce((a,b)=>([...a,...b]),[head]))
        }}
word = ch:(wordCharacter/escapedCharacter)+ ${chJoin}
...
`
function functionBodies(glue, ...fns){
    return glue.map( (str,i) => str + (fns[i]||'').toString().replace(/^[^{]*/,'').replace(/[^}]*$/, '') ).join('')
    }

function chJoin(ch){return ch.join('')}

Que diriez-vous d'utiliser l'opérateur de canal proposé (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Pipeline_operator) ? Puisque, fondamentalement, vous demandez à rediriger les données ?

{
  function extract(value) {
    return value;
  }
  function concat(head, tail) {
    return head ? [head].concat(tail) : [];
  }
  function toAddExpr(head, tail) {
    return { type: 'addExpr', expressions: concat(head, tail) };
  }
}

List
  = '(' _ head:Item? tail:( _ ',' _ value:Item |> extract )* _ ')' |> concat

// Another kind of list
Add
  = '(' _ head:Multiply? tail:( _ '+' _ value:Multiply |> extract  )* _ ')' |> toAddExpr

Rien de tout cela ne devrait arriver. Il ne devrait pas y avoir de syntaxe courte.

Rien de tout cela n'est nécessaire si nous analysons simplement les flèches normalement, au lieu d'essayer de les caler latéralement.

Bien que ce soit une bonne idée, cela crée des ambiguïtés grammaticales étendues par rapport à JavaScript. Quiconque a analysé JS et se souvient de la débâcle de with sait que cela tuera essentiellement un analyseur.

Au lieu d'essayer de créer de nouvelles choses sophistiquées, nous devrions simplement prendre en charge Javascript. Les fonctions fléchées sont plus anciennes que ES6 et ES6 date de 2015. Cela a été résolu il y a six ans. Aucune invention ne devrait se produire ici.

L'opérateur pipe est très défectueux et ne le fera probablement pas réellement en Javascript, et le langage dont il provient à l'origine (F#) et le langage qui l'a popularisé (Elixir) s'en éloignent. De plus, ce n'est en aucun cas de la tuyauterie.

La raison pour laquelle PEG a connu un tel succès était qu'il était minimal et qu'il restait proche du langage, ce qui lui permettait d'être rapide, petit et prévisible.

Les fonctions fléchées sont plus anciennes que ES6 et ES6 date de 2015. Cela a été résolu il y a six ans. Aucune invention ne devrait se produire ici.

Euh. C'est une nouvelle pour moi. Souhaitez-vous étendre?

La raison pour laquelle PEG a connu un tel succès était qu'il était minimal et qu'il restait proche du langage, ce qui lui permettait d'être rapide, petit et prévisible.

La raison pour laquelle PEG (en tant que concept, pas cette bibliothèque) est un succès est due à sa capacité à représenter des grammaires complexes (récursives, etc.) d'une manière simpliste. Packrat n'a pas été inventé avec cette bibliothèque ; ce n'est pas une syntaxe. C'est un algorithme.

Les fonctions fléchées sont plus anciennes que ES6 et ES6 date de 2015. Cela a été résolu il y a six ans. Aucune invention ne devrait se produire ici.

Euh. C'est une nouvelle pour moi. Souhaitez-vous étendre?

Je ne sais pas vraiment ce que vous demandez.

Les fonctions fléchées sont plus anciennes que ES6. C'était le deuxième plus gros combat de l'ES6, c'est ce qui a fait dérailler ES4 et ES5+. Tout le monde les demandait, à ce moment-là, depuis le milieu des années 90, car ils existaient déjà dans E4X, et ont été retirés parce que Google et Apple ont critiqué Hixie à propos du fait que Microsoft ait jamais inventé quoi que ce soit.

Vous connaissez maintenant E4X sous le nom de React et pensez que Facebook l'a inventé. Facebook pense avoir arnaqué Hyperscript. Le gars d'Hyperscript est clair qu'il réimplémentait juste une chose utile de l'ancien IE.

Ils allaient être complètement exclus de l'ES6, tout comme les chaînes de modèles, mais Coffeescript est arrivé et a donné les deux à la communauté JS, puis la communauté JS a crié jusqu'à ce que les gens de l'ECMA bougent. n'a pris que 18 mois

Les fonctions fléchées font tout ce qui doit se produire ici. Vous semblez même être la personne qui les a évoqués dans ce fil, en 2018, ce qui rend votre désaccord assez surprenant; J'essayais de te soutenir.

Plus important pour moi, si c'est fait avec une fonction flèche, rien n'a été ajouté.

Les différences entre Peg et JS sont absolument minimes. Soutenir cela en faisant simplement des trucs ES6 signifie que la liste ne change pas.

C'est extrêmement précieux.


La raison pour laquelle PEG (en tant que concept, pas cette bibliothèque) est un succès est due à sa capacité à représenter des grammaires complexes (récursives, etc.) d'une manière simpliste.

Je ne suis pas d'accord. De nombreux analyseurs font un bien meilleur travail et ne sont même pas un peu populaires, même auprès des personnes qui les connaissent (comme Earley.)

L'explication traditionnelle est une combinaison de qualité et de vitesse des messages d'erreur, mais je ne suis pas d'accord avec cela non plus, car de nombreux analyseurs ont de meilleurs messages d'erreur plus rapidement (encore une fois, comme Earley) et ne sont même pas légèrement populaires, même avec les gens qui les connaissent

Notez également que PEG a trois plafonds de complexité sérieux.

Premièrement, tout ce que vous voulez faire passer par une grammaire peg doit avoir une expression combinatoire qui ne submerge pas le cache de la machine locale et le débit d'évaluation (par exemple #623)

Deux, de nombreux travaux courants, tels que l'analyse de BNF, sont souvent brutalement difficiles en peg (par exemple #489)

Troisièmement, il convient de noter que toutes les autres bibliothèques JS PEG, même les plus puissantes, ont échoué. J'ai essayé de m'éloigner et je suis revenu plusieurs fois. En particulier, j'ai essayé de passer à canopy un tas de fois, car cela me permet de cibler c , ruby , et python en plus à javascript

Certes, tout ce pour quoi je peux parler, ce sont les deux douzaines de personnes que je connais qui l'utilisent. Et je peux, parce que j'ai demandé il y a quelques jours, quand j'ai réalisé que le nouveau non-mainteneur jetait le logiciel et le remplaçait par quelque chose qu'il avait fait à partir de zéro, après des années sans modifications publiées

Mais chacun d'entre eux m'a dit soit qu'ils avaient besoin d'un analyseur qui n'a pas beaucoup de surcharge conceptuelle native, soit qu'ils avaient besoin de quelque chose de rapide et petit dont le comportement était fiable

Unreleased 0.11 se comporte de manière significativement différente dans node vs chrome, et node est fait de chrome. Essayez d'écrire des tests de propriétés contre elle. C'est franchement un peu terrifiant.

.

Packrat n'a pas été inventé avec cette bibliothèque ; ce n'est pas une syntaxe. C'est un algorithme.

Je n'ai rien dit à propos de Packrat, mon ami. Je ne sais pas ce que vous essayez de corriger.

L'analyse syntaxique Packrat n'est cependant pas un algorithme, pour la même raison que le tri n'est pas un algorithme. L'analyse syntaxique Packrat est une tâche, et il existe de nombreuses façons de s'y prendre.

En effet, la plupart des livres d'introduction haskell vous font faire trois ou quatre analyseurs packrat différents, car ils sont un excellent moyen de vraiment vous attarder sur les problèmes de performances de l'approche haskell des monades, et ils veulent vous montrer comment changer l'approche de l'écriture packrats (c'est-à-dire en changeant l'algorithme) donne de meilleurs résultats.

.

Veuillez reconsidérer cela. Cette bibliothèque est morte depuis trois ans, et j'aimerais la ressusciter maintenant.

Une partie de la raison pour laquelle la bibliothèque est morte est que les gens continuent d'essayer d'inventer des fonctionnalités, au lieu d'effectuer une simple maintenance, comme l'ajout de la fonction de module es() qui est en développement depuis deux ans

Je dois modifier manuellement mes analyseurs PEG en coupant des lignes et en agrafant du javascript écrit à la main à leur extrémité

Les yeux étoilés devraient se fermer pendant un petit moment et quelques coudes gras pratiques devraient commencer. PEG est la seule grande bibliothèque NPM que j'aie jamais vue avec une utilisation en baisse. Étant donné que je ne suis pas au courant d'un remplacement raisonnable, c'est bizarre et déroutant pour moi.

image

J'ai des corrections de bugs que je veux apporter maintenant, mais je ne peux pas, car

  1. 0.10 n'a pas été publié depuis le départ de dmajda,
  2. 0.11 trois ans, n'a jamais été publié, et il a été annoncé il y a un mois qu'il ne serait jamais publié, et
  3. Le remplacement, 0.12 , n'est pas du tout indexé, mais quelque chose que l'autre a écrit à partir de zéro dans un langage de programmation différent, et aucun de nous ne peut le voir

Je sais que c'est impoli, mais nous devons admettre que cette bibliothèque est en train d'être tuée

Il est temps de faire face au fait que nous devons accepter un processus de développement normal si cette bibliothèque doit à nouveau voir des mises à jour. Nous sommes en 2020. Nous n'avons rien vu depuis 2017.

Non, la branche dev ne compte pas. Et le nouveau mainteneur va devoir rouvrir de nombreux problèmes, car 0.11 n'est pas d'une qualité suffisante, et recommencer à partir de 10 est beaucoup moins de travail que de réparer 11

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

Questions connexes

gatsbyz picture gatsbyz  ·  3Commentaires

richb-hanover picture richb-hanover  ·  7Commentaires

futagoza picture futagoza  ·  6Commentaires

Coffee2CodeNL picture Coffee2CodeNL  ·  13Commentaires

brettz9 picture brettz9  ·  8Commentaires