summaryrefslogtreecommitdiff
path: root/cpp/src/FreezeScript/Scanner.l
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/FreezeScript/Scanner.l')
-rw-r--r--cpp/src/FreezeScript/Scanner.l376
1 files changed, 376 insertions, 0 deletions
diff --git a/cpp/src/FreezeScript/Scanner.l b/cpp/src/FreezeScript/Scanner.l
new file mode 100644
index 00000000000..75643e79423
--- /dev/null
+++ b/cpp/src/FreezeScript/Scanner.l
@@ -0,0 +1,376 @@
+%{
+
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/GrammarUtil.h> // Before Grammar.h, so that YYSTYPE is defined
+#include <FreezeScript/Grammar.h>
+#include <IceUtil/InputUtil.h>
+
+#include <stdlib.h>
+#include <math.h>
+
+#include <map>
+
+#ifdef _WIN32
+ // I get these warnings from some flex versions:
+ // warning C4003: not enough actual parameters for macro 'yywrap'
+# pragma warning( disable : 4003 )
+#endif
+
+using namespace std;
+using namespace FreezeScript;
+
+namespace FreezeScript
+{
+
+typedef map<string, int> KeywordMap;
+static KeywordMap keywordMap;
+
+void initScanner();
+int checkKeyword(const string&);
+StringTokPtr parseString(char);
+
+}
+
+#define YY_USER_INIT initScanner();
+
+#define YY_INPUT(buf, result, max_size) { result = getInput(buf, max_size); }
+%}
+
+%option noyywrap
+%option never-interactive
+%option prefix="freeze_script_"
+%option outfile="lex.yy.c"
+
+identifier [[:alpha:]_][[:alnum:]_]*
+integer_constant (\+|-)?((0[0-7]+)|(0x[[:xdigit:]]+)|([[:digit:]]+))
+fractional_constant (\+|-)?(([[:digit:]]*\.[[:digit:]]+)|([[:digit:]]+\.))
+exponent_part (e|E)(\+|-)?[[:digit:]]+
+floating_literal (({fractional_constant}{exponent_part}?)|((\+|-)?[[:digit:]]+{exponent_part}))[fF]?
+
+%%
+
+"//" {
+ // C++-style comment
+ int c;
+ do
+ {
+ c = yyinput();
+ if(c == '\n')
+ {
+ parseLine++;
+ }
+ }
+ while(c != '\n' && c != EOF);
+}
+
+"/*" {
+ // C-style comment
+ while(true)
+ {
+ int c = yyinput();
+ if(c == '\n')
+ {
+ parseLine++;
+ }
+ else if(c == '*')
+ {
+ int next = yyinput();
+ if(next == '/')
+ {
+ break;
+ }
+ else
+ {
+ unput(next);
+ }
+ }
+ else if(c == EOF)
+ {
+ parseErrorReporter->expressionSyntaxError("EOF in comment");
+ break;
+ }
+ }
+}
+
+{identifier} {
+ StringTokPtr ident = new StringTok;
+ ident->v = yytext;
+ *yylvalp = ident;
+ return checkKeyword(ident->v);
+}
+
+\" {
+ StringTokPtr str = parseString('"');
+ *yylvalp = str;
+ return TOK_STRING_LITERAL;
+}
+
+\' {
+ StringTokPtr str = parseString('\'');
+ *yylvalp = str;
+ return TOK_STRING_LITERAL;
+}
+
+{integer_constant} {
+ IntegerTokPtr itp = new IntegerTok;
+ *yylvalp = itp;
+ errno = 0;
+ itp->v = IceUtil::strToInt64(yytext, 0, 0);
+ if(errno == ERANGE && (itp->v == IceUtil::Int64Min || itp->v == IceUtil::Int64Max))
+ {
+ string msg = "integer constant `";
+ msg += yytext;
+ msg += "' out of range";
+ parseErrorReporter->expressionSyntaxError(msg);
+ }
+ return TOK_INTEGER_LITERAL;
+}
+
+{floating_literal} {
+ errno = 0;
+ FloatingTokPtr ftp = new FloatingTok;
+ *yylvalp = ftp;
+ string literal(yytext);
+ char lastChar = literal[literal.size() - 1];
+ if(lastChar == 'f' || lastChar == 'F')
+ {
+ literal = literal.substr(0, literal.size() - 1); // Clobber trailing 'f' or 'F' suffix
+ }
+ ftp->v = strtod(literal.c_str(), 0);
+ if((ftp->v == HUGE_VAL || ftp->v == -HUGE_VAL) && errno == ERANGE)
+ {
+ string msg = "floating-point constant `";
+ msg += yytext;
+ msg += "' too large (overflow)";
+ parseErrorReporter->expressionSyntaxError(msg);
+ }
+ else if(ftp->v == 0 && errno == ERANGE)
+ {
+ string msg = "floating-point constant `";
+ msg += yytext;
+ msg += "' too small (underflow)";
+ parseErrorReporter->expressionSyntaxError(msg);
+ }
+ return TOK_FLOATING_POINT_LITERAL;
+}
+
+[[:space:]] {
+ // Igore white-space
+
+ if(yytext[0] == '\n')
+ {
+ parseLine++;
+ }
+}
+
+"<" return TOK_LESS_THAN;
+">" return TOK_GREATER_THAN;
+"<=" return TOK_LESS_EQUAL;
+">=" return TOK_GREATER_EQUAL;
+"==" return TOK_EQUAL;
+"!=" return TOK_NEQ;
+"+" return TOK_ADD;
+"-" return TOK_SUB;
+"*" return TOK_MUL;
+"/" return TOK_DIV;
+"%" return TOK_MOD;
+"(" return TOK_LPAREN;
+")" return TOK_RPAREN;
+"[" return TOK_LBRACKET;
+"]" return TOK_RBRACKET;
+"::" return TOK_SCOPE_DELIMITER;
+
+. {
+ return yytext[0];
+}
+
+%%
+
+namespace FreezeScript
+{
+
+void
+initScanner()
+{
+ keywordMap["true"] = TOK_TRUE;
+ keywordMap["false"] = TOK_FALSE;
+ keywordMap["and"] = TOK_AND;
+ keywordMap["or"] = TOK_OR;
+ keywordMap["not"] = TOK_NOT;
+ keywordMap["nil"] = TOK_NIL;
+}
+
+int
+checkKeyword(const string& id)
+{
+ KeywordMap::const_iterator pos = keywordMap.find(id);
+ if(pos != keywordMap.end())
+ {
+ return pos->second;
+ }
+ return TOK_IDENTIFIER;
+}
+
+StringTokPtr
+parseString(char start)
+{
+ StringTokPtr str = new StringTok;
+ while(true)
+ {
+ char c = static_cast<char>(yyinput());
+ if(c == start)
+ {
+ break;
+ }
+ else if(c == EOF)
+ {
+ parseErrorReporter->expressionSyntaxError("EOF in string");
+ break;
+ }
+ else if(c == '\n')
+ {
+ parseErrorReporter->expressionSyntaxError("newline in string");
+ }
+ else if(c == '\\')
+ {
+ char next = static_cast<char>(yyinput());
+ switch(next)
+ {
+ case '\\':
+ case '"':
+ case '\'':
+ {
+ str->v += next;
+ break;
+ }
+
+ case 'n':
+ {
+ str->v += '\n';
+ break;
+ }
+
+ case 'r':
+ {
+ str->v += '\r';
+ break;
+ }
+
+ case 't':
+ {
+ str->v += '\t';
+ break;
+ }
+
+ case 'v':
+ {
+ str->v += '\v';
+ break;
+ }
+
+ case 'f':
+ {
+ str->v += '\f';
+ break;
+ }
+
+ case 'a':
+ {
+ str->v += '\a';
+ break;
+ }
+
+ case 'b':
+ {
+ str->v += '\b';
+ break;
+ }
+
+ case '?':
+ {
+ str->v += '\?';
+ break;
+ }
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ {
+ static string octalDigits = "01234567";
+ unsigned short us = next - '0';
+ if(octalDigits.find_first_of(next = static_cast<char>(yyinput())) != string::npos)
+ {
+ us = us * 8 + next - '0';
+ if(octalDigits.find_first_of(next = static_cast<char>(yyinput())) != string::npos)
+ {
+ us = us * 8 + next - '0';
+ }
+ else
+ {
+ unput(next);
+ }
+ }
+ else
+ {
+ unput(next);
+ }
+ str->v += static_cast<char>(us);
+ break;
+ }
+ case 'x':
+ {
+ IceUtil::Int64 ull = 0;
+ while(isxdigit(next = static_cast<char>(yyinput())))
+ {
+ ull *= 16;
+ if(isdigit(next))
+ {
+ ull += next - '0';
+ }
+ else if(islower(next))
+ {
+ ull += next - 'a' + 10;
+ }
+ else
+ {
+ ull += next - 'A' + 10;
+ }
+ }
+ unput(next);
+ str->v += static_cast<char>(ull);
+ break;
+ }
+
+ // TODO: add universal character names
+
+ default:
+ {
+ str->v += c;
+ unput(next);
+ }
+ }
+ }
+ else
+ {
+ str->v += c;
+ }
+ }
+
+ return str;
+}
+
+} // End of namespace FreezeScript