2017-01-09 1 views
1

Supposons qu'une langue définisse la contiguïté de deux symboles alphanumériques mathématiques unicodes en tant qu'opérateur. Say, +1 signifie% adj + 1, où% adj représente n'importe quelle adjacence d'opérateur, la multiplication dans ce cas. Je me demandais, est-ce que n'importe quel outil d'analyse lexicale existant peut gérer cela?adjacence en tant qu'opérateur - est-ce que n'importe quel lexer peut le gérer?

+0

-vous en supposant que tous les noms de variables sont constitués d'une seule lettre ou voulez-vous le lexer désambiguïser basé sur les variables sont défini (comme si 'xy' est défini comme une variable,' xy' devrait être un seul jeton, sinon il devrait être deux)? – sepp2k

+0

Cette question a été traitée en profondeur dans un [document] (http://www.stroustrup.com/whitespace98.pdf) qui a peut-être été oublié maintenant (avec le grain de sel proverbiale.) – shinobi

+0

@shinobi: That paper est encore un plaisir à lire après presque deux décennies, mais les lecteurs occasionnels devraient être avertis que sa date de publication était [1 avril] (http://www.stroustrup.com/whitespace.html), 1998 – rici

Répondre

1

Les opérateurs invisibles ne peuvent pas être reconnus avec une analyse lexicale, pour des raisons qui devraient être plus ou moins évidentes. Vous pouvez seulement déduire la présence d'un opérateur invisible en analysant le contexte syntaxique, qui est le rôle d'un analyseur. Bien sûr, la plupart des outils d'analyse lexicale permettent l'exécution de code arbitraire pour chaque jeton reconnu, donc rien ne vous empêche de construire une machine d'état, ou même un analyseur complet, dans l'analyseur lexical. C'est rarement un bon design.

Si votre langage n'est pas ambigu, il n'y a pas de problème pour gérer la contiguïté dans votre grammaire. Mais il faut faire attention. Par exemple, vous voulez rarement x-4 à analyser comme une multiplication des x et -4, mais une grammaire naïve qui comprenait, par exemple.,

expr -> term | expr '-' term 
term -> factor | term factor | term '*' factor 
factor -> ID | NUMBER | '(' expr ')' | '-' factor 

comprendrait cette ambiguïté. Pour le résoudre, vous devez interdire la production de contiguïté avec un second opérande commençant par un opérateur unaire:

expr -> term | expr '-' term 
term -> factor | term item | term '*' factor 
factor -> item | '-' factor 
item -> ID | NUMBER | '(' expr ')' 

Notez la différence entre term -> term '*' factor, qui permet x * - y et term -> term base, qui ne permet pas x - y (expr -> expr '-' term reconnaît x - y comme une soustraction).

Pour des exemples de grammaires sans contexte qui permettent l'adjacence en tant qu'opérateur, voir, par exemple, Awk, dans lequel adjacence représente la concaténation de chaîne, et Haskell, dans lequel il représente l'application de fonction.


Puisque cette question se présente de temps en temps, il y a déjà un certain nombre de réponses pertinentes sur SO. En voici quelques-unes:

0

Voici un exemple en utilisant pyparsing en Python:

import pyparsing as pp 

integer = pp.pyparsing_common.integer() 
variable = pp.oneOf(list("abcdefghijklmnopqrstuvwxyz")) 

base_operand = integer | variable 

implied_multiplication = pp.Empty().addParseAction(lambda: "*") 
expr = pp.infixNotation(base_operand, 
       [ 
        ("**", 2, pp.opAssoc.LEFT), 
        (implied_multiplication, 2, pp.opAssoc.LEFT), 
        (pp.oneOf("+ -"), 1, pp.opAssoc.RIGHT), 
        (pp.oneOf("* /"), 2, pp.opAssoc.LEFT), 
        (pp.oneOf("+ -"), 2, pp.opAssoc.LEFT), 
       ]) 

Cela suppose que les variables ne sont que des caractères uniques. Il y a aussi un peu de falsification de la préséance des opérations pour faire fonctionner la contiguïté, l'exponentiation et les signes avant-coureurs. L'action d'analyse ajoutée à l'expression implied_multiplication est là pour montrer l'insertion de l'opérateur de multiplication.

Voici quelques sortie de test:

tests = """ 
    x-4 
    ax**2 + bx +c 
    ax**2-bx+c 
    mx+b 
    """ 
expr.runTests(tests, fullDump=False) 

impressions:

x-4 
[['x', '-', 4]] 

ax**2 + bx +c 
[[['a', '*', ['x', '**', 2]], '+', ['b', '*', 'x'], '+', 'c']] 

ax**2-bx+c 
[[['a', '*', ['x', '**', 2]], '-', ['b', '*', 'x'], '+', 'c']] 

mx+b 
[[['m', '*', 'x'], '+', 'b']]