/** @file ginsh_lexer.ll * * Lexical analyzer definition for ginsh. * This file must be processed with flex. */ /* * GiNaC Copyright (C) 1999-2008 Johannes Gutenberg University Mainz, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Definitions */ %pointer %{ #include "config.h" #include "ginsh.h" #include "ginsh_parser.h" #define YY_INPUT(buf, result, max_size) (result = ginsh_input(buf, max_size)) // Table of all used symbols sym_tab syms; // Type of symbols to generate (real or complex) unsigned symboltype = domain::complex; // lex input function static int ginsh_input(char *buf, int max_size); %} /* Abbreviations */ D [0-9] E [elEL][-+]?{D}+ A [a-zA-Z_] AN [0-9a-zA-Z_] /* * Lexical rules */ %% [ \t\n]+ /* skip whitespace */ \\$ /* skip line continuations */ "//".* /* skip comments starting with "//" */ ^"#".* /* skip lines starting with "#" */ ^"!".* system(yytext + 1); /* execute shell command */ /* special values */ Pi yylval = Pi; return T_LITERAL; Euler yylval = Euler; return T_LITERAL; Catalan yylval = Catalan; return T_LITERAL; FAIL yylval = *new fail(); return T_LITERAL; I yylval = I; return T_NUMBER; Digits yylval = (long)Digits; return T_DIGITS; /* keywords */ quit|exit return T_QUIT; warranty return T_WARRANTY; print return T_PRINT; iprint return T_IPRINT; print_latex return T_PRINTLATEX; print_csrc return T_PRINTCSRC; time return T_TIME; xyzzy return T_XYZZY; inventory return T_INVENTORY; look return T_LOOK; score return T_SCORE; complex_symbols return T_COMPLEX_SYMBOLS; real_symbols return T_REAL_SYMBOLS; /* comparison */ "==" return T_EQUAL; "!=" return T_NOTEQ; "<=" return T_LESSEQ; ">=" return T_GREATEREQ; /* last 1..3 expressions */ \% return T_QUOTE; \%\% return T_QUOTE2; \%\%\% return T_QUOTE3; /* numbers */ {D}+ | "#"{D}+"R"{AN}+ | "#b"([01])+ | "#o"[0-7]+ | "#x"[0-9a-fA-F]+ | {D}+"."{D}*({E})? | {D}*"."{D}+({E})? | {D}+{E} yylval = numeric(yytext); return T_NUMBER; /* symbols */ {A}{AN}* { sym_tab::const_iterator i = syms.find(yytext); if (i == syms.end()) { if (symboltype == domain::complex) { yylval = syms[yytext] = *(new symbol(yytext)); } else { yylval = syms[yytext] = *(new symbol(yytext, domain::real)); } } else yylval = i->second; return T_SYMBOL; } /* wildcards */ \${D}+ yylval = wild(atoi(yytext + 1)); return T_LITERAL; /* everything else */ . return *yytext; %% /* * Routines */ static int line_length = 0; static char *line_read = NULL; static char *line_ptr; // Input function that uses libreadline for interactive input static int ginsh_input(char *buf, int max_size) { int result; #if defined(YY_CURRENT_BUFFER) if (YY_CURRENT_BUFFER->yy_is_interactive) { #else if (yy_current_buffer->yy_is_interactive) { #endif #ifdef HAVE_LIBREADLINE // Do we need to read a new line? int actual; if (line_length == 0) { // Free old line if (line_read) free(line_read); // Read new line, prompt "> " line_read = line_ptr = readline("> "); // EOF? if (!line_read) { line_length = 0; return YY_NULL; } // Add non-empty lines to history line_length = strlen(line_read) + 1; if (line_length > 1) add_history(line_read); // Reappend trailing '\n' which is stripped by readline() line_read[line_length - 1] = '\n'; } // Copy data to lex buffer actual = line_length > max_size ? max_size : line_length; memcpy(buf, line_ptr, actual); line_length -= actual; line_ptr += actual; result = actual; #else printf("> "); fflush(stdout); int c = '*', n; for (n = 0; n < max_size && (c = getc(yyin)) != EOF && c != '\n'; ++n) buf[n] = (char)c; if (c == '\n') buf[n++] = (char)c; if (c == EOF && ferror(yyin)) YY_FATAL_ERROR("input in flex scanner failed"); result = n; #endif } else if (((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin)) YY_FATAL_ERROR("input in flex scanner failed"); return result; } // List of input files to be processed int num_files = 0; char **file_list = NULL; // EOF encountered, connect to next file. If this was the last file, // connect to stdin. If this was stdin, terminate the scanner. int yywrap() { if (yyin == stdin) return 1; fclose(yyin); if (num_files) { yyin = fopen(*file_list, "r"); if (yyin == NULL) { cerr << "Can't open " << *file_list << endl; return 1; } num_files--; file_list++; } else yyin = stdin; return 0; }