/***************************************************************************** * Date: Thu Oct 25 11:45:22 CDT 2007 * Author: John Quigley * Revision: $Id$ * * The White Programming Language * Copyright (C) 2007 John Quigley * * 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 3 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, see . ****************************************************************************** ****************************************************************************** lexical structure reference ****************************************************************************** -> | | | | | ( | ) | [ | ] | ; === IDENTIFIERS === identifier ::= (letter | special) (letter | special| digit)* letter ::= lowercase | uppercase lowercase ::= "a" ... "z" uppercase ::= "A" ... "Z" digit ::= "0" ... "9" special ::= "!" | "*" | "+" | "-" | "?" | "_" === KEYWORDS === true false lambda === STRING LITERALS === stringliteral ::= [stringprefix] (shortstring | longstring) stringprefix ::= shortstring ::= '"' shortstringitem* '"' longstring ::= '"""' longstringitem* '"""' shortstringitem ::= shortstringchar | escapeseq longstringitem ::= longstringitem | escapeseq shortstringchar ::= longstringchar ::= escapeseq ::= "\" === INTEGER AND LONG INTEGER LITERALS === longinteger ::= integer "L" integer ::= decimalinteger | octinteger | hexinteger decimalinteger ::= digit+ hexinteger ::= "0" "x" hexdigit+ hexdigit ::= digit | "a" ... "f" | "A" ... "F" === FLOATING POINT LITERALS === floatnumber ::= pointfloat | exponentfloat pointfloat ::= [intpart] fraction | intpart "." exponentfloat ::= (intpart | pointfloat) exponent intpart ::= digit+ fraction ::= "." digit+ exponent ::= "e" ["+" | "-"] digit+ === COMPLEX LITERALS === imagnumber ::= (floatnumber | intpart) "J" === OPERATORS === + - * ** / // % << >> & | ^ ~ < > <= >= == != ! === DELIMETERS === ( ) [ ] { } @ , : . ` = ; += -= *= /= //= %= &= |= ^= >>= <<= **= ******************************************************************************/ %{ #include #include #include #include "frontend/parse.h" #include "core/util.h" #include "core/gc.h" extern YYSTYPE yylval_param; extern YYSTYPE yylval; extern YYLTYPE yylloc_param; extern yyscan_t yyscanner; extern int fileno(FILE *stream); extern long double strtold(const char *nptr, char **endptr); extern long long atoll(const char *nptr); %} %option 8bit yylineno bison-bridge bison-locations reentrant DIGIT [0-9] LETTER [a-zA-Z] SIGN [:!@$%^&*+=/~<>|?_-] DELIM [()\[\];] WS [ \t\n\r] %% /* ---------- literal keyword tokens ---------- */ true | false | null | self | super { LOGGER_DEBUG("scanner found keyword '%s'", yytext); yylval->strval = WGC_strdup(yytext); return KEYWORD; } /* ---------- punctuation ---------- */ {DELIM} { LOGGER_DEBUG("scanner found delimeter '%s'", yytext); return yytext[0]; } /* ---------- numbers ---------- */ /* decimal integer */ [+-]?{DIGIT}+ { LOGGER_DEBUG("scanner found (base:dec, format:std) integer '%s'", yytext); yylval->llval = atoll(yytext); return INTEGER; } /* decimal rational */ {DIGIT}+"."{DIGIT}* | "."{DIGIT}+ { LOGGER_DEBUG("scanner found (base:dec, format:std) rational '%s'", yytext); yylval->ldval = strtold(yytext, (char **)NULL); return RATIONAL; } /* decimal scientific rational */ [+-]?{DIGIT}+[eE][-+]?{DIGIT}+ | {DIGIT}+"."{DIGIT}*[eE][+-]?{DIGIT}+ | "."{DIGIT}*[eE][+-]?{DIGIT}+ { LOGGER_DEBUG("scanner found (base:dec, format:sci) rational '%s'", yytext); yylval->ldval = strtold(yytext, (char **)NULL); return SCIENTIFIC; } /* hexidecimal integer */ 0[xX][0-9a-fA-F]+ { LOGGER_DEBUG("scanner found (base:hex) integer '%s'", yytext + 2); yylval->lval = strtol(yytext, (char **)NULL, 16); return HEX; } /* octadecimal integer */ 0[cC][0-8]+ { LOGGER_DEBUG("scanner found (base:oct) integer '%s'", yytext); yytext[0] = ' '; yytext[1] = '0'; yylval->lval = strtol(yytext, (char **)NULL, 8); return OCTAL; } /* complex */ [+-]?{DIGIT}+i { LOGGER_DEBUG("scanner found (base:dec) complex '%s'", yytext); yytext[sizeof(yytext) - 1] = ' '; yylval->lval = strtol(yytext, (char **)NULL, 10); return COMPLEX; } /* ---------- string ---------- */ \"[^"]*\" { LOGGER_DEBUG("scanner found string '%s'", yytext); yylval->strval = WGC_strdup(yytext); return STRING; } /* ---------- comment ---------- */ "//".*$ { LOGGER_DEBUG("scanner found comment (disgarding) '%s'", yytext); } "/*" { /* TODO: we may want to buffer this for future usage */ register int c; for ( ; ; ) { /* eat up text of comment */ while ( (c = input(yyscanner)) != '*' && c != EOF ); if ( c == '*' ) { while ( (c = input(yyscanner)) == '*' ); if ( c == '/' ) break; /* found the end */ } if ( c == EOF ) { error_at_line(1, 0, __FILE__, __LINE__, "EOF in comment"); break; } } LOGGER_DEBUG("scanner found comment (disregarding) '%s'", yytext); } /* ---------- names ---------- */ "#"({LETTER}|{DIGIT}|{SIGN})+ { LOGGER_DEBUG("scanner found symbol %s", (yytext + 1)); yylval->strval = WGC_strdup(yytext + 1); return SYMBOL; } ({LETTER}|{DIGIT}|{SIGN})+ { LOGGER_DEBUG("scanner found identifier '%s'", yytext); yylval->strval = WGC_strdup(yytext); return IDENTIFIER; } /* ---------- whitespace ---------- */ {WS}+ ; /* ---------- eat the rest ---------- */ . { LOGGER_ERROR("unexpected character '%s'\n", yytext); } %% /* EOF */