[poincare] Clean parser

This commit is contained in:
Émilie Feral
2018-09-13 15:30:48 +02:00
parent 0c602459ca
commit b66cc754ed
3 changed files with 84 additions and 182 deletions

View File

@@ -23,7 +23,7 @@
* Those tokens (and the optional value that they can be attached) are defined
* in the Bison grammar. To use those token definitions, we need to include the
* header generated by Bison.
* Also, since some tokens can have an "Expression *" value attached, we'll
* Also, since some tokens can have an "Expression" value attached, we'll
* need "Expression" to be defined before including that header.
* We could use the '%code requires{}' directive to make sure that Expression is
* well defined in the parser header, but this directive only comes in bison 3,
@@ -80,82 +80,82 @@ using namespace Poincare;
* refered to Pi symbols. This artefact leads to the following lexer rules
* starting with \x. */
(([0-9]*[.]?[0-9]+)|([0-9]+[.]?[0-9]*))(\x8d\-?[0-9]+)? { yylval->expression = Poincare::Number::ParseDigits(yytext, yyleng); return DIGITS; }
[A-Za-z] { yylval->expression = Poincare::Symbol(yytext[0]); return SYMBOL; }
M[0-9] { yylval->expression = Poincare::Symbol(Symbol::matrixSymbol(yytext[1])); return SYMBOL; }
u\(n\) { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::un); return SYMBOL; }
u\(n\+1\) { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::un1); return SYMBOL; }
v\(n\) { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::vn); return SYMBOL; }
v\(n\+1\) { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::vn1); return SYMBOL; }
u\_\{n\} { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::un); return SYMBOL; }
u\_\{n\+1\} { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::un1); return SYMBOL; }
v\_\{n\} { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::vn); return SYMBOL; }
v\_\{n\+1\} { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::vn1); return SYMBOL; }
V1 { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::V1); return SYMBOL; }
N1 { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::N1); return SYMBOL; }
V2 { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::V2); return SYMBOL; }
N2 { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::N2); return SYMBOL; }
V3 { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::V3); return SYMBOL; }
N3 { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::N3); return SYMBOL; }
X1 { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::X1); return SYMBOL; }
Y1 { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::Y1); return SYMBOL; }
X2 { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::X2); return SYMBOL; }
Y2 { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::Y2); return SYMBOL; }
X3 { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::X3); return SYMBOL; }
Y3 { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::Y3); return SYMBOL; }
acos { yylval->expression = ArcCosine(); return FUNCTION; }
acosh { yylval->expression = HyperbolicArcCosine(); return FUNCTION; }
abs { yylval->expression = AbsoluteValue(); return FUNCTION; }
ans { yylval->expression = Poincare::Symbol(Symbol::SpecialSymbols::Ans); return SYMBOL; }
arg { yylval->expression = ComplexArgument(); return FUNCTION; }
asin { yylval->expression = ArcSine(); return FUNCTION; }
asinh { yylval->expression = HyperbolicArcSine(); return FUNCTION; }
atan { yylval->expression = ArcTangent(); return FUNCTION; }
atanh { yylval->expression = HyperbolicArcTangent(); return FUNCTION; }
binomial { yylval->expression = BinomialCoefficient(); return FUNCTION; }
ceil { yylval->expression = Ceiling(); return FUNCTION; }
confidence { yylval->expression = ConfidenceInterval(); return FUNCTION; }
diff { yylval->expression = Derivative(); return FUNCTION; }
dim { yylval->expression = MatrixDimension(); return FUNCTION; }
conj { yylval->expression = Conjugate(); return FUNCTION; }
det { yylval->expression = Determinant(); return FUNCTION; }
cos { yylval->expression = Cosine(); return FUNCTION; }
cosh { yylval->expression = HyperbolicCosine(); return FUNCTION; }
factor { yylval->expression = Factor(); return FUNCTION; }
floor { yylval->expression = Floor(); return FUNCTION; }
frac { yylval->expression = FracPart(); return FUNCTION; }
gcd { yylval->expression = GreatCommonDivisor(); return FUNCTION; }
im { yylval->expression = ImaginaryPart(); return FUNCTION; }
int { yylval->expression = Integral(); return FUNCTION; }
inverse { yylval->expression = MatrixInverse(); return FUNCTION; }
lcm { yylval->expression = LeastCommonMultiple(); return FUNCTION; }
ln { yylval->expression = NaperianLogarithm(); return FUNCTION; }
(([0-9]*[.]?[0-9]+)|([0-9]+[.]?[0-9]*))(\x8d\-?[0-9]+)? { *yylval = Poincare::Number::ParseDigits(yytext, yyleng); return DIGITS; }
[A-Za-z] { *yylval = Poincare::Symbol(yytext[0]); return SYMBOL; }
M[0-9] { *yylval = Poincare::Symbol(Symbol::matrixSymbol(yytext[1])); return SYMBOL; }
u\(n\) { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::un); return SYMBOL; }
u\(n\+1\) { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::un1); return SYMBOL; }
v\(n\) { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::vn); return SYMBOL; }
v\(n\+1\) { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::vn1); return SYMBOL; }
u\_\{n\} { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::un); return SYMBOL; }
u\_\{n\+1\} { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::un1); return SYMBOL; }
v\_\{n\} { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::vn); return SYMBOL; }
v\_\{n\+1\} { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::vn1); return SYMBOL; }
V1 { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::V1); return SYMBOL; }
N1 { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::N1); return SYMBOL; }
V2 { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::V2); return SYMBOL; }
N2 { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::N2); return SYMBOL; }
V3 { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::V3); return SYMBOL; }
N3 { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::N3); return SYMBOL; }
X1 { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::X1); return SYMBOL; }
Y1 { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::Y1); return SYMBOL; }
X2 { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::X2); return SYMBOL; }
Y2 { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::Y2); return SYMBOL; }
X3 { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::X3); return SYMBOL; }
Y3 { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::Y3); return SYMBOL; }
acos { *yylval = ArcCosine(); return FUNCTION; }
acosh { *yylval = HyperbolicArcCosine(); return FUNCTION; }
abs { *yylval = AbsoluteValue(); return FUNCTION; }
ans { *yylval = Poincare::Symbol(Symbol::SpecialSymbols::Ans); return SYMBOL; }
arg { *yylval = ComplexArgument(); return FUNCTION; }
asin { *yylval = ArcSine(); return FUNCTION; }
asinh { *yylval = HyperbolicArcSine(); return FUNCTION; }
atan { *yylval = ArcTangent(); return FUNCTION; }
atanh { *yylval = HyperbolicArcTangent(); return FUNCTION; }
binomial { *yylval = BinomialCoefficient(); return FUNCTION; }
ceil { *yylval = Ceiling(); return FUNCTION; }
confidence { *yylval = ConfidenceInterval(); return FUNCTION; }
diff { *yylval = Derivative(); return FUNCTION; }
dim { *yylval = MatrixDimension(); return FUNCTION; }
conj { *yylval = Conjugate(); return FUNCTION; }
det { *yylval = Determinant(); return FUNCTION; }
cos { *yylval = Cosine(); return FUNCTION; }
cosh { *yylval = HyperbolicCosine(); return FUNCTION; }
factor { *yylval = Factor(); return FUNCTION; }
floor { *yylval = Floor(); return FUNCTION; }
frac { *yylval = FracPart(); return FUNCTION; }
gcd { *yylval = GreatCommonDivisor(); return FUNCTION; }
im { *yylval = ImaginaryPart(); return FUNCTION; }
int { *yylval = Integral(); return FUNCTION; }
inverse { *yylval = MatrixInverse(); return FUNCTION; }
lcm { *yylval = LeastCommonMultiple(); return FUNCTION; }
ln { *yylval = NaperianLogarithm(); return FUNCTION; }
log { return LOGFUNCTION; }
permute { yylval->expression = PermuteCoefficient(); return FUNCTION; }
prediction95 { yylval->expression = PredictionInterval(); return FUNCTION; }
prediction { yylval->expression = SimplePredictionInterval(); return FUNCTION; }
product { yylval->expression = Product(); return FUNCTION; }
quo { yylval->expression = DivisionQuotient(); return FUNCTION; }
random { yylval->expression = Random(); return FUNCTION; }
randint { yylval->expression = Randint(); return FUNCTION; }
re { yylval->expression = RealPart(); return FUNCTION; }
rem { yylval->expression = DivisionRemainder(); return FUNCTION; }
root { yylval->expression = NthRoot(); return FUNCTION; }
round { yylval->expression = Round(); return FUNCTION; }
sin { yylval->expression = Sine(); return FUNCTION; }
sinh { yylval->expression = HyperbolicSine(); return FUNCTION; }
sum { yylval->expression = Sum(); return FUNCTION; }
tan { yylval->expression = Tangent(); return FUNCTION; }
tanh { yylval->expression = HyperbolicTangent(); return FUNCTION; }
trace { yylval->expression = MatrixTrace(); return FUNCTION; }
transpose { yylval->expression = MatrixTranspose(); return FUNCTION; }
undef { yylval->expression = Undefined(); return UNDEFINED; }
inf { yylval->expression = Undefined(); return UNDEFINED; }
\x8a { yylval->expression = Poincare::Symbol(yytext[0]); return SYMBOL; }
\x8c { yylval->expression = Poincare::Symbol(yytext[0]); return SYMBOL; }
\x8f { yylval->expression = Poincare::Symbol(yytext[0]); return SYMBOL; }
permute { *yylval = PermuteCoefficient(); return FUNCTION; }
prediction95 { *yylval = PredictionInterval(); return FUNCTION; }
prediction { *yylval = SimplePredictionInterval(); return FUNCTION; }
product { *yylval = Product(); return FUNCTION; }
quo { *yylval = DivisionQuotient(); return FUNCTION; }
random { *yylval = Random(); return FUNCTION; }
randint { *yylval = Randint(); return FUNCTION; }
re { *yylval = RealPart(); return FUNCTION; }
rem { *yylval = DivisionRemainder(); return FUNCTION; }
root { *yylval = NthRoot(); return FUNCTION; }
round { *yylval = Round(); return FUNCTION; }
sin { *yylval = Sine(); return FUNCTION; }
sinh { *yylval = HyperbolicSine(); return FUNCTION; }
sum { *yylval = Sum(); return FUNCTION; }
tan { *yylval = Tangent(); return FUNCTION; }
tanh { *yylval = HyperbolicTangent(); return FUNCTION; }
trace { *yylval = MatrixTrace(); return FUNCTION; }
transpose { *yylval = MatrixTranspose(); return FUNCTION; }
undef { *yylval = Undefined(); return UNDEFINED; }
inf { *yylval = Undefined(); return UNDEFINED; }
\x8a { *yylval = Poincare::Symbol(yytext[0]); return SYMBOL; }
\x8c { *yylval = Poincare::Symbol(yytext[0]); return SYMBOL; }
\x8f { *yylval = Poincare::Symbol(yytext[0]); return SYMBOL; }
\x90 { return STO; }
\x91 { yylval->expression = SquareRoot(); return FUNCTION; }
\x91 { *yylval = SquareRoot(); return FUNCTION; }
= { return EQUAL; }
\+ { return PLUS; }
\- { return MINUS; }
@@ -173,7 +173,7 @@ inf { yylval->expression = Undefined(); return UNDEFINED; }
\] { return RIGHT_BRACKET; }
\, { return COMMA; }
\_ { return UNDERSCORE; }
\x97 { yylval->expression = EmptyExpression(); return EMPTY; }
\x97 { *yylval = EmptyExpression(); return EMPTY; }
[ ]+ /* Ignore whitespaces */
. { return UNDEFINED_SYMBOL; }

View File

@@ -1,12 +1,7 @@
#include <poincare.h>
/* Usually, YYSTYPE is defined as the union of the objects it might be. Here,
* some of these objects are non-trivial (specific copy-constructors and
* destructors), so they cannot be part of a union. We must use a struct to
* define YYSTYPE. */
* Expression is non-trivial (specific copy-constructors and destructors), so
* it cannot be part of a union. */
struct OurNodeValue{
Poincare::Expression expression;
};
#define YYSTYPE OurNodeValue
#define YYSTYPE Poincare::Expression

View File

@@ -38,65 +38,11 @@ void poincare_expression_yyerror(Poincare::Expression * expressionOutput, char c
#define YYCOPY(To, From, Count) memcpy(To, From, (Count)*sizeof(*(From)))
using namespace Poincare;
#if 0
//TODO move comments
/* All symbols (both terminals and non-terminals) may have a value associated
* with them. In our case, it's going to be either an Expression (for example,
* when parsing (a/b) we want to create a new Division), or a string (this will
* be useful to retrieve the value of Integers for example). */
%union {
Poincare::Expression expression;
Poincare::Symbol symbol;
/*
Poincare::ListData * listData;
Poincare::MatrixData * matrixData;
Poincare::StaticHierarchy<0> * function;
*/
/* Caution: all the const char * are NOT guaranteed to be NULL-terminated!
* While Flex guarantees that yytext is NULL-terminated when building tokens,
* it does so by temporarily swapping in a NULL terminated in the input text.
* Of course that hack has vanished by the time the pointer is fed into Bison.
* We thus record the length of the char fed into Flex in a structure and give
* it to the object constructor called by Bison along with the char *. */
struct {
char * address;
int length;
} string;
char character;
}
#endif
%}
/* The INTEGER token uses the "string" part of the union to store its value */
%token <expression> DIGITS
%token <expression> SYMBOL
%token <expression> FUNCTION
%token <expression> LOGFUNCTION
%token <expression> UNDEFINED
%token <expression> EMPTY
/* Operator tokens */
%token PLUS
%token MINUS
%token MULTIPLY
%token DIVIDE
%token POW
%token BANG
%token LEFT_PARENTHESIS
%token RIGHT_PARENTHESIS
%token LEFT_BRACE
%token RIGHT_BRACE
%token LEFT_BRACKET
%token RIGHT_BRACKET
%token COMMA
%token UNDERSCORE
%token STO
%token EQUAL
%token UNDEFINED_SYMBOL
/* Make the operators left associative.
* This makes 1 - 2 - 5 be (1 - 2) - 5 instead of 1 - (2 - 5).
@@ -115,8 +61,7 @@ using namespace Poincare;
/* Note that in bison, precedence of parsing depend on the order they are defined in here, the last
* one has the highest precedence. */
%nonassoc EQUAL
%nonassoc STO
%nonassoc EQUAL STO
%left PLUS
%left MINUS
%left MULTIPLY
@@ -138,36 +83,11 @@ using namespace Poincare;
%nonassoc UNDEFINED
%nonassoc SYMBOL
%nonassoc EMPTY
%nonassoc UNDEFINED_SYMBOL
/* The "exp" symbol uses the "expression" part of the union. */
%type <expression> final_exp;
%type <expression> term;
%type <expression> bang;
%type <expression> factor;
%type <expression> pow;
%type <expression> exp;
%type <expression> number;
%type <expression> symb;
%type <expression> lstData;
/* MATRICES_ARE_DEFINED */
%type <expression> mtxData;
/* FIXME: no destructors, Expressions are GCed */
/* During error recovery, some symbols need to be discarded. We need to tell
* Bison how to get rid of them. Depending on the type of the symbol, it may
* have some heap-allocated data that need to be discarded. */
/*
%destructor { delete $$; } FUNCTION
%destructor { delete $$; } UNDEFINED final_exp exp pow factor bang term number EMPTY
%destructor { delete $$; } lstData
*/
/* MATRICES_ARE_DEFINED */
/*
%destructor { delete $$; } mtxData
%destructor { delete $$; } symb
*/
/* During error recovery, some symbols need to be discarded. No destructor need
* to be specified to Bison because all symbols are Poincare::Expression that
* are garbage collected. */
%%
@@ -197,18 +117,6 @@ mtxData: LEFT_BRACKET lstData RIGHT_BRACKET { $$ = Matrix::EmptyMatrix(); static
* an int32_t). */
number : DIGITS { $$ = $1; }
/*
| DOT DIGITS { $$ = Decimal(Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), Decimal::exponent(nullptr, 0, $2.address, $2.length, nullptr, 0, false)); }
| DIGITS DOT DIGITS { $$ = Decimal(Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), Decimal::exponent($1.address, $1.length, $3.address, $3.length, nullptr, 0, false)); }
| DOT DIGITS EE DIGITS { if ($4.length > 4) { YYERROR; }; int exponent = Decimal::exponent(nullptr, 0, $2.address, $2.length, $4.address, $4.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = Decimal(Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), exponent); }
| DIGITS DOT DIGITS EE DIGITS { if ($5.length > 4) { YYERROR; }; int exponent = Decimal::exponent($1.address, $1.length, $3.address, $3.length, $5.address, $5.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = Decimal(Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), exponent); }
| DIGITS EE DIGITS { if ($3.length > 4) { YYERROR; }; int exponent = Decimal::exponent($1.address, $1.length, nullptr, 0, $3.address, $3.length, false); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = Decimal(Decimal::mantissa($1.address, $1.length, nullptr, 0, false), exponent); }
| DOT DIGITS EE MINUS DIGITS { if ($5.length > 4) { YYERROR; }; int exponent = Decimal::exponent(nullptr, 0, $2.address, $2.length, $5.address, $5.length, true); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = Decimal(Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), exponent); }
| DIGITS DOT DIGITS EE MINUS DIGITS { if ($6.length > 4) { YYERROR; }; int exponent = Decimal::exponent($1.address, $1.length, $3.address, $3.length, $6.address, $6.length, true); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Decimal(Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), exponent); }
| DIGITS EE MINUS DIGITS { if ($4.length > 4) { YYERROR; }; int exponent = Decimal::exponent($1.address, $1.length, nullptr, 0, $4.address, $4.length, true); if (exponent > 1000 || exponent < -1000 ) { YYERROR; }; $$ = new Decimal(Decimal::mantissa($1.address, $1.length, nullptr, 0, false), exponent); }
;
*/
symb : SYMBOL { $$ = $1; }
;
@@ -224,7 +132,6 @@ term : EMPTY { $$ = $1; }
| FUNCTION LEFT_PARENTHESIS RIGHT_PARENTHESIS { if ($1.numberOfChildren() != 0) { YYERROR; } $$ = $1; }
| LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = Parenthesis($2); }
/* MATRICES_ARE_DEFINED */
| LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = $2; }
;