Blame view

Giac_maj/epsilon-giac/poincare/src/expression_lexer.l 8.93 KB
6663b6c9   adorian   projet complet av...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  /* Normally, Flex will call yywrap when reaching an end-of-file. We don't want
   * to deal with files anyway, so let's just disable this. */
  %option noyywrap
  
  /* WARNING:
   * If you think about using the bison-bridge option, note that this assumes
   * that the bison parser is reentrant (pure-parser option).
   *
   * Note also that bison and flex (when not reentrant) communicate with each
   * other by using global variables such as yylval or yylineno, these variables
   * will also be prefixed (here we have poicare_expression_yylval).
   *
   * When using a reentrant parser, these variables become pointers and are
   * not prefixed (this is probably a bug in bison, or at least is a bug in my
   * opinion).
   *
   * Using reentrant parsers and lexer is not useful for us as we neither use
   * multiple inputs, different threads calling the lexer-parser nor do we read
   * nested files.
   */
  
  /* Normally, on each new input file the scanner calls isatty() in an attempt to
   * determine whether the scanner's input source is interactive and thus should
   * be read a character at a time.
   * We obviously do *not* provide isatty(), and we know we're never going to use
   * an interactive input source. */
  %option never-interactive
  
  %{
  /* Flex generate a lexer, a function that outputs tokens.
   * 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
   * 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,
   * which is not installed by default on MacOS, we thus made the choice to prefer
   * compatibility with MacOS's default version (2.3) instead of using the code
   * requires feature. */
  #include <cmath>
  #include <poincare.h>
  #include "expression_parser.hpp"
  using namespace Poincare;
  
  /* Flex has provision for reading files. We'll never use this, so we're defining
   * YY_INPUT which effectively disables taking input from a file. */
  #define YY_INPUT
  
  /* Flex can print to stdout what token it matches by calling the ECHO function.
   * We don't want that feature : we don't even have printf ! */
  #define ECHO
  
  /* This defines the size of the flex buffer size.
   * By default this buffer is of 16k, but we don't have the luxury to use so much
   * memory on a microcontroller.
   * The choice of 256 Bytes is the size of the input buffer given to flex in the
   * current implementation (the app takes a maximum of 256).
   */
  #undef YY_BUF_SIZE
  #define YY_BUF_SIZE 256
  
  #define fprintf(...) ((void)0)
  #define exit(...) abort()
  
  %}
  
  %%
  
   /* If two patterns can match the same input, flex resolves the ambiguity:
    * - By matching the longest possible string
    * - In a tie, by using the pattern that appears first
    *
    * Also note that yytext is guaranteed to be null-terminated when the token is
    * being built, (i.e. when flex calls our code snippet), but this is achieved
    * by flex temporarily swapping the last character. Afterwards the pointer is
    * still valid but the string isn't null-terminated anymore.
    */
    /* We designed our own extended-ASCII to include requiered symbols in less
     * than 255 glyphs. The file ion/include/ion/charset.h lists all added
     * non-ASCII symbols with their char associated. For example, the char \x89
     * refered to Pi symbols. This artefact leads to the following lexer rules
     * starting with \x. */
  
  [0-9]+ { poincare_expression_yylval.string.address = yytext; poincare_expression_yylval.string.length = yyleng; return DIGITS; }
  [A-Zxn] { poincare_expression_yylval.character = yytext[0]; return SYMBOL; }
  [a-z;:"_=<>?] { return UNDEFINED_SYMBOL; }
  M[0-9] { poincare_expression_yylval.character = Symbol::matrixSymbol(yytext[1]); return SYMBOL; }
  u\(n\) { poincare_expression_yylval.character = Symbol::SpecialSymbols::un; return SYMBOL; }
  u\(n\+1\) { poincare_expression_yylval.character = Symbol::SpecialSymbols::un1; return SYMBOL; }
  v\(n\) { poincare_expression_yylval.character = Symbol::SpecialSymbols::vn; return SYMBOL; }
  v\(n\+1\) { poincare_expression_yylval.character = Symbol::SpecialSymbols::vn1; return SYMBOL; }
  w\(n\) { poincare_expression_yylval.character = Symbol::SpecialSymbols::wn; return SYMBOL; }
  w\(n\+1\) { poincare_expression_yylval.character = Symbol::SpecialSymbols::wn1; return SYMBOL; }
  acos { poincare_expression_yylval.expression = new ArcCosine(); return FUNCTION; }
  acosh { poincare_expression_yylval.expression = new HyperbolicArcCosine(); return FUNCTION; }
  abs { poincare_expression_yylval.expression = new AbsoluteValue(); return FUNCTION; }
  ans { poincare_expression_yylval.character = Symbol::SpecialSymbols::Ans; return SYMBOL; }
  arg { poincare_expression_yylval.expression = new ComplexArgument(); return FUNCTION; }
  asin { poincare_expression_yylval.expression = new ArcSine(); return FUNCTION; }
  asinh { poincare_expression_yylval.expression = new HyperbolicArcSine(); return FUNCTION; }
  atan { poincare_expression_yylval.expression = new ArcTangent(); return FUNCTION; }
  atanh { poincare_expression_yylval.expression = new HyperbolicArcTangent(); return FUNCTION; }
  binomial { poincare_expression_yylval.expression = new BinomialCoefficient(); return FUNCTION; }
  ceil { poincare_expression_yylval.expression = new Ceiling(); return FUNCTION; }
  confidence { poincare_expression_yylval.expression = new ConfidenceInterval(); return FUNCTION; }
  diff { poincare_expression_yylval.expression = new Derivative(); return FUNCTION; }
  dim { poincare_expression_yylval.expression = new MatrixDimension(); return FUNCTION; }
  det { poincare_expression_yylval.expression = new Determinant(); return FUNCTION; }
  conj { poincare_expression_yylval.expression = new Conjugate(); return FUNCTION; }
  cos { poincare_expression_yylval.expression = new Cosine(); return FUNCTION; }
  cosh { poincare_expression_yylval.expression = new HyperbolicCosine(); return FUNCTION; }
  floor { poincare_expression_yylval.expression = new Floor(); return FUNCTION; }
  frac { poincare_expression_yylval.expression = new FracPart(); return FUNCTION; }
  gcd { poincare_expression_yylval.expression = new GreatCommonDivisor(); return FUNCTION; }
  im { poincare_expression_yylval.expression = new ImaginaryPart(); return FUNCTION; }
  int { poincare_expression_yylval.expression = new Integral(); return FUNCTION; }
  inverse { poincare_expression_yylval.expression = new MatrixInverse(); return FUNCTION; }
  lcm { poincare_expression_yylval.expression = new LeastCommonMultiple(); return FUNCTION; }
  ln { poincare_expression_yylval.expression = new NaperianLogarithm(); return FUNCTION; }
  log { poincare_expression_yylval.expression = new Logarithm(); return FUNCTION; }
  permute { poincare_expression_yylval.expression = new PermuteCoefficient(); return FUNCTION; }
  prediction95 { poincare_expression_yylval.expression = new PredictionInterval(); return FUNCTION; }
  prediction { poincare_expression_yylval.expression = new ConfidenceInterval(); return FUNCTION; }
  product { poincare_expression_yylval.expression = new Product(); return FUNCTION; }
  quo { poincare_expression_yylval.expression = new DivisionQuotient(); return FUNCTION; }
  re { poincare_expression_yylval.expression = new ReelPart(); return FUNCTION; }
  rem { poincare_expression_yylval.expression = new DivisionRemainder(); return FUNCTION; }
  root { poincare_expression_yylval.expression = new NthRoot(); return FUNCTION; }
  round { poincare_expression_yylval.expression = new Round(); return FUNCTION; }
  sin { poincare_expression_yylval.expression = new Sine(); return FUNCTION; }
  sinh { poincare_expression_yylval.expression = new HyperbolicSine(); return FUNCTION; }
  sum { poincare_expression_yylval.expression = new Sum(); return FUNCTION; }
  tan { poincare_expression_yylval.expression = new Tangent(); return FUNCTION; }
  tanh { poincare_expression_yylval.expression = new HyperbolicTangent(); return FUNCTION; }
  trace { poincare_expression_yylval.expression = new MatrixTrace(); return FUNCTION; }
  transpose { poincare_expression_yylval.expression = new MatrixTranspose(); return FUNCTION; }
  undef { poincare_expression_yylval.expression = new Complex<double>(Complex<double>::Float(NAN)); return UNDEFINED; }
  inf { poincare_expression_yylval.expression = new Complex<double>(Complex<double>::Float(INFINITY)); return UNDEFINED; }
  \x89 { poincare_expression_yylval.character = yytext[0]; return SYMBOL; }
  \x8c { return EE; }
  \x90 { poincare_expression_yylval.expression = new SquareRoot(); return FUNCTION; }
  \x8b { return ICOMPLEX; }
  \x8e { poincare_expression_yylval.character = yytext[0]; return SYMBOL; }
  \x8f { return STO; }
  \+ { return PLUS; }
  \- { return MINUS; }
  \* { return MULTIPLY; }
  \/ { return DIVIDE; }
  \^ { return POW; }
  \! { return BANG; }
  \( { return LEFT_PARENTHESIS; }
  \) { return RIGHT_PARENTHESIS; }
  \{ { return LEFT_BRACE; }
  \} { return RIGHT_BRACE; }
  \[ { return LEFT_BRACKET; }
  \] { return RIGHT_BRACKET; }
  \, { return COMMA; }
  \. { return DOT; }
  
  %%