Puede encontrar reglas estándar para la aritmética en la sintaxis de muchos lenguajes de programación. Por ejemplo, el manual de bison Bison 3.0.4 tiene la siguiente definición de regla
exp: NUM {$$ = $ 1; }
El | exp ‘+’ exp {$$ = $ 1 + $ 3; }
El | exp ‘-‘ exp {$$ = $ 1 – $ 3; }
El | exp ‘*’ exp {$$ = $ 1 * $ 3; }
El | exp ‘/’ exp {$$ = $ 1 / $ 3; }
El | ‘-‘ exp% prec NEG {$$ = – $ 2; }
El | exp ‘^’ exp {$$ = pow ($ 1, $ 3); }
El | ‘(‘ exp ‘)’ {$$ = $ 2; }
;
que incluyen las reglas estándar más la acción de análisis. Las expresiones matemáticas son un poco complicadas en su interpretación, ya que debe considerar el concepto de precedencia y la asociatividad del operador. Con prioridad, la multiplicación y la división deben evaluarse antes de la suma y la resta, por lo que 2 + 3 * 4 se evalúa como 2+ (3 * 4) no (2 + 3) * 4. Con asociatividad especifica si 2-3-4 se evalúa como (2-3) -4, asociativo a la izquierda, o 2- (3-4), asociativo a la derecha. +, -, *, / son todos asociativos a la izquierda pero la exponenciación es asociativa a la derecha y en C asignación = es asociativa a la derecha, por lo que a = b = c se interpreta como a = (b = c).
- ¿Cuál es la circunferencia de la tierra a 45 grados norte?
- ¿Por qué las matemáticas son tan geniales?
- ¿Qué significa cuando a = b en ax + by + c = 0. ¿Cómo indica el número de líneas en esa familia de líneas?
- ¿Por qué no podemos encontrar el símbolo correspondiente para la pregunta "¿Qué es 1 dividido por 0", si el número i fue desarrollado como respuesta a la pregunta que antes no tenía respuesta "¿Cuál es la raíz cuadrada de -1"?
- Considere S (k) -8S (k-1) -33S (k-2) = 28-80k con S (0) = 5, S (1) = 13. Encuentra (k)?
Bison agrega algunos bits de sintaxis especiales que no son BNF para permitir esto
% token NUM
Queda% ‘-‘ ‘+’
%izquierda ‘*’ ‘/’
% de precedencia NEG / * negación – unario menos * /
% correcto ‘^’ / * exponenciación * /
Para agregar variables y funciones necesita un par de bits adicionales.
% define api.value.type union / * Genera YYSTYPE a partir de estos tipos: * /
% token NUM / * Número simple de doble precisión. * /
% token VAR FNCT / * Puntero de la tabla de símbolos: variable y función. * /
% type exp
y las reglas gramaticales.
Exp:
NUM {$$ = $ 1; }
El | VAR {$$ = $ 1-> value.var; }
El | VAR ‘=’ exp {$$ = $ 3; $ 1-> value.var = $ 3; }
El | FNCT ‘(‘ exp ‘)’ {$$ = (* ($ 1-> value.fnctptr)) ($ 3); }
El | exp ‘+’ exp {$$ = $ 1 + $ 3; }
…
Muchos autores dividen la regla individual en varios pasos; consulte, por ejemplo, yacc java Grammar, cuyo segmento modificado es
Expresión multiplicativa
: UnaryExpression
El | MultiplicativeExpression ‘*’ UnaryExpression
El | MultiplicativeExpression ‘/’ UnaryExpression
El | MultiplicativeExpression ‘%’ UnaryExpression
;
Expresión aditiva
: Expresión Multiplicativa
El | AdditiveExpression ‘+’ MultiplicativeExpression
El | AdditiveExpression ‘-‘ Expresión multiplicativa
;
Si realmente quiere profundizar en esto, puede ver la especificación real de las expresiones en Java Capítulo 15. Expresiones.
Una página bastante bonita es http://math.purduecal.edu/~rlkra… que tiene diez gramáticas diferentes para analizar la aritmética.
Analizar la aritmética es un trabajo bastante complicado, debe preocuparse por los diferentes operadores asociativos izquierdo y derecho, y la prioridad. En mi código ya no confío en el uso de generadores de analizadores que funcionan desde la sintaxis BNF o EBNF. En cambio, escribo mi propio analizador de precedencia de operadores construido sobre el algoritmo Shunting-yard. He encontrado que esto es más fácil de controlar y extender.