Pegjs: Comment conserver les séparateurs d'espaces blancs ?

Créé le 3 oct. 2019  ·  6Commentaires  ·  Source: pegjs/pegjs

Type de probleme

  • Rapport de bogue : _non_
  • Demande de fonctionnalité : _non_
  • Question : _oui_
  • Pas un problème : _non_

Conditions préalables

  • Pouvez-vous reproduire le problème ? : _oui_
  • Avez-vous recherché les problèmes du référentiel ? : _oui_
  • Avez-vous consulté les forums ? : _oui_
  • Avez-vous effectué une recherche sur le Web (google, yahoo, etc.) ? : _oui_

J'ai du mal à faire en sorte que l'analyseur PEG.js conserve les espaces blancs d'origine de l'équation.

Comportement actuel : 2 * 5 + SUM(1, 2, 3)

[
   "2",
   "*",
   "5",
   "+",
   "SUM",
   "(",
   [
      "1",
      ",",
      "2",
      ",",
      "3"
   ],
   ")"
]

Comportement souhaité : 2 * 5 + SUM(1, 2, 3)

[
   "2",
   " ",
   "*",
   " ",
   "5",
   " ",
   "+",
   " ",
   "SUM",
   "(",
   [
      "1",
      ",",
      " ",
      "2",
      ",",
      " ",
      "3"
   ],
   ")"
]

Grammaire à copier : https://pastebin.com/zpwqT6Uw
Aire de jeux PEG.js https://pegjs.org/online

Qu'est-ce que je rate?

Commentaire le plus utile

@marek-baranowski Un autre ping doux :smiley_cat:

De plus, j'ai écrit un plugin PEG.js pegjs-syntactic-actions pour faciliter le débogage des grammaires, et voir spécifiquement quels caractères sont capturés par quelle règle indépendamment des actions, ce qui est probablement votre problème ici comme expliqué par @StoneCypher.

Le raisonnement de ce plugin est le suivant : je trouve qu'il est souvent/parfois difficile de comprendre le résultat global lorsqu'il n'est pas celui auquel on s'attend, car il résulte de la combinaison de nombreuses petites actions, et trouver l'action qui se comporte mal/étrangement pourrait être long. Avec ce plugin, nous voyons quelle règle capture quel personnage, et il donne le nom de l'action sur laquelle agir.

Tous les 6 commentaires

@futagoza incroyablement désolé de vous déranger mais c'est la première fois que je traite avec PEG.js et ce problème est critique pour moi. Puis-je vous demander un petit indice ?

Meilleures salutations,
marek

J'ai essayé de parcourir votre grammaire (hier et tout à l'heure) mais parce que c'est vraiment difficile à comprendre (conventions de nommage mises à part, le format, pour être honnête, est partout), il m'a fallu un certain temps pour trouver une solution :

  1. Les règles qui consomment de l'espace et des données le renvoient (par exemple, const renvoie [left_space, cnst, right_space] )
  2. Toute règle/action qui prend le résultat doit faire quelque chose comme ceci : [].concat.apply([], con)

Même encore, pour être honnête avec vous, cela me semble être une solution de piratage. Avez-vous un lien vers une spécification ou quelque chose? Cela aiderait à savoir quelles règles je peux et ne peux pas changer pour obtenir le résultat souhaité sans la solution hacky ci-dessus.

Sinon, tant que vous êtes prêt à consacrer du temps et à ranger la grammaire et à renommer certaines règles (c'est donc plus facile de comprendre ce que vous voulez), alors j'essaierai volontiers d'essayer à nouveau 😉

@marek-baranowski - Désolé je n'ai pas vu ça jusqu'à maintenant. J'espère que cela vous sera toujours utile

Si vous souhaitez conserver les espaces, traitez-les simplement comme du contenu correspondant.

Ce n'est pas vraiment clair exactement ce que vous voudriez pour deux espaces. Vous pouvez soit avoir une chaîne de deux espaces, soit un tableau de deux chaînes d'un espace. Normalement, je m'attendrais au premier, mais ... tout votre truc est par personnage

Aussi ... pourquoi voudriez-vous des caractères parasites comme ça, sauf pour l'appel de fonction ? L'analyseur devrait les résumer pour vous.

En tous cas

C'est ce que tu as demandé :

Document = Expression*

Whitespace
  = tx:[ \r\n]+ { return tx.join(''); }

Number
  = str:[0-9]+ { return str.join(''); }

Oper
  = '+'
  / '-'
  / '/'
  / '*'
  / ','

Label
  = l:[a-zA-Z]+ { return l.join(''); }

Parens 
  = '(' Whitespace? ex:Expression* Whitespace? ')' { return ex; }

Expression 
  = Number 
  / Oper
  / Whitespace
  / Label
  / Parens
  / [^()]+

image

Le fait est que je ne suis pas super convaincu que c'est réellement ce que vous voulez. Par exemple, à la place, vous pouvez analyser les nombres et les opérateurs, et renvoyer une forme de nœud standardisée pour chacun :

Document = Expression*

Whitespace
  = tx:[ \r\n]+ { return { 
    ast: 'whitespace', value: tx.join('') 
  }; }

Number
  = str:[0-9]+ { return {
    ast: 'number', value: parseInt(str,10)
  }; }

Oper
  = '+' { return { ast: 'oper', value: 'add' }}
  / '-' { return { ast: 'oper', value: 'subtract' }}
  / '/' { return { ast: 'oper', value: 'divide' }}
  / '*' { return { ast: 'oper', value: 'multiply' }}
  / ',' { return { ast: 'oper', value: 'sequence' }}

Label
  = l:[a-zA-Z]+ { return { 
    ast: 'label', value: l.join('') 
  }; }

Parens 
  = '(' Whitespace? ex:Expression* Whitespace? ')' { 
    return { ast: 'parens', value: ex 
  }; }

Expression 
  = Number 
  / Oper
  / Whitespace
  / Label
  / Parens
  / [^()]+

Maintenant, vous avez toujours votre espace blanc, mais vous avez également un arbre analysé approprié, et vous n'avez pas besoin d'écrire un analyseur pour analyser la sortie de votre analyseur, et il est également simple comme bonjour de commencer à ajouter des fonctionnalités régularisées telles que les numéros de ligne, etc.

image

@marek-baranowski - J'aimerais réduire quelque peu la taille de ce suivi des problèmes

Si ce qui précède est ce dont vous avez besoin, pourriez-vous envisager de fermer ce problème ? Merci 😄

Si ce n'est pas le cas, dites-moi pourquoi, et je réessayerai

@marek-baranowski Un autre ping doux :smiley_cat:

De plus, j'ai écrit un plugin PEG.js pegjs-syntactic-actions pour faciliter le débogage des grammaires, et voir spécifiquement quels caractères sont capturés par quelle règle indépendamment des actions, ce qui est probablement votre problème ici comme expliqué par @StoneCypher.

Le raisonnement de ce plugin est le suivant : je trouve qu'il est souvent/parfois difficile de comprendre le résultat global lorsqu'il n'est pas celui auquel on s'attend, car il résulte de la combinaison de nombreuses petites actions, et trouver l'action qui se comporte mal/étrangement pourrait être long. Avec ce plugin, nous voyons quelle règle capture quel personnage, et il donne le nom de l'action sur laquelle agir.

oh wow c'est vraiment chouette en fait

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