/* 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 #include #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-Za-z] { poincare_expression_yylval.character = yytext[0]; return 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; } 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; } V1 { poincare_expression_yylval.character = Symbol::SpecialSymbols::V1; return SYMBOL; } N1 { poincare_expression_yylval.character = Symbol::SpecialSymbols::N1; return SYMBOL; } V2 { poincare_expression_yylval.character = Symbol::SpecialSymbols::V2; return SYMBOL; } N2 { poincare_expression_yylval.character = Symbol::SpecialSymbols::N2; return SYMBOL; } V3 { poincare_expression_yylval.character = Symbol::SpecialSymbols::V3; return SYMBOL; } N3 { poincare_expression_yylval.character = Symbol::SpecialSymbols::N3; return SYMBOL; } X1 { poincare_expression_yylval.character = Symbol::SpecialSymbols::X1; return SYMBOL; } Y1 { poincare_expression_yylval.character = Symbol::SpecialSymbols::Y1; return SYMBOL; } X2 { poincare_expression_yylval.character = Symbol::SpecialSymbols::X2; return SYMBOL; } Y2 { poincare_expression_yylval.character = Symbol::SpecialSymbols::Y2; return SYMBOL; } X3 { poincare_expression_yylval.character = Symbol::SpecialSymbols::X3; return SYMBOL; } Y3 { poincare_expression_yylval.character = Symbol::SpecialSymbols::Y3; 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; } factor { poincare_expression_yylval.expression = new Factor(); 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 SimplePredictionInterval(); return FUNCTION; } product { poincare_expression_yylval.expression = new Product(); return FUNCTION; } quo { poincare_expression_yylval.expression = new DivisionQuotient(); return FUNCTION; } random { poincare_expression_yylval.expression = new Random(); return FUNCTION; } randint { poincare_expression_yylval.expression = new Randint(); return FUNCTION; } re { poincare_expression_yylval.expression = new RealPart(); 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 Undefined(); return UNDEFINED; } inf { poincare_expression_yylval.expression = new Undefined(); return UNDEFINED; } \x8a { poincare_expression_yylval.character = yytext[0]; return SYMBOL; } \x8d { return EE; } \x91 { poincare_expression_yylval.expression = new SquareRoot(); return FUNCTION; } \x8c { poincare_expression_yylval.character = yytext[0]; return SYMBOL; } \x8f { poincare_expression_yylval.character = yytext[0]; return SYMBOL; } \x90 { return STO; } = { return EQUAL; } \+ { return PLUS; } \- { return MINUS; } \x94 { return MULTIPLY; } \x95 { return MULTIPLY; } \* { 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; } \_ { return UNDERSCORE; } \x97 { poincare_expression_yylval.expression = new EmptyExpression(); return EMPTY; } [ ]+ /* Ignore whitespaces */ . { return UNDEFINED_SYMBOL; } %%