3 votes

Analyse des arguments de fonction sans délimiteurs d'arguments

Je travaille sur un projet où j'ai besoin de traduire NetLogo dans un autre langage de programmation. J'utilise Boost Spirit et j'ai déjà implémenté certaines des grammaires du projet qui stockent la syntaxe du code simple dans un AST.

Le problème auquel je suis confronté est qu'en ce moment, je ne peux pas dire si un identifiant est un nom de variable ou un nom de fonction. De plus, je ne sais pas si un appel de fonction spécifique nécessite un, deux ou plusieurs arguments, donc je ne sais pas quand arrêter de chercher plus d'arguments.

Par exemple, un appel de fonction peut ressembler à

id1 id2 id3 id4

Cela pourrait être :

  • id3 est une fonction qui a id4 comme argument (disons que la valeur de retour est id5), et id1 est une fonction qui a id2 et id5 comme arguments

Mais cela pourrait aussi être :

  • id1 a id2 id3 id4 comme arguments (tous sauf id1 sont des noms de variables)

J'ai pensé à utiliser des symboles et à ajouter de nouveaux éléments à chaque fois qu'une variable ou une fonction est déclarée, cela aiderait à différencier les noms de variable des noms de fonction, mais...

  • Comment/dois-je stocker le nombre d'arguments qu'une fonction nécessite en utilisant Boost Spirit ? Peut-être en utilisant une autre table de symboles avec des actions sémantiques lors de l'analyse de la définition de la fonction ?
  • Une fois que je sais comment obtenir le nombre d'arguments requis, comment puis-je obtenir cette valeur lorsque je trouve un identifiant de fonction lors de l'analyse d'une expression ?
  • Est-ce une bonne solution d'utiliser des symboles pour différencier les noms de variable des noms de fonction ?

0voto

Reynau Points 184

Enfin, ce que j'ai fait est le suivant :

  • Créé une table de symboles en utilisant le nom de la fonction comme clé, et le nombre d'arguments comme données stockées.

    qi::symbols f_args;

  • Utilisé une Action Sémantique sur le parseur de fonction pour obtenir le nom de la fonction et la liste des arguments, puis l'envoyer à une fonction externe pour stocker les données dans la table de symboles.

    void store_function (std::string name, std::list args) { f_args.add(name, args.size()); std::cout << name << " " << args.size() << std::endl; }

    function = ( lexeme[(string("to-report") | string("to")) >> !(alnum | '')] // s'assurer d'avoir des mots entiers

    identifier ('[' > argumentlist > ']') body lexeme[string("end") >> !(alnum | '')] ) [ phx::bind(&store_function, _2, _3) ];

  • Lorsqu'un nom de fonction est trouvé en dehors d'une définition de fonction (ce qui signifie qu'il s'agit d'un appel de fonction), je charge les données stockées dans la Table de Symboles pour les utiliser dans une directive repeat et m'attends au nombre exact d'arguments dont la fonction a besoin.

    function_call = function_name >> repeat( phx::ref(n_args) )[identifier];

    functionname = !lexeme[keywords >> !(alnum | '')] >> &lexeme[f_args [phx::ref(n_args) = 1] >> !(alnum | '')] >> raw[lexeme[(alpha | '') >> *(alnum | '' | '-')]];

La seule question à laquelle cette réponse ne répond pas est la dernière. Espérons que quelqu'un avec plus d'expérience dans ce domaine l'expliquera.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X