view Bison-Flex/Compiler-StackBase/script-scanner.ll @ 0:db40c85cad7a default tip

upload sample source
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Mon, 09 May 2011 03:11:59 +0900
parents
children
line wrap: on
line source

%{
#include <cstdlib>
#include <cerrno>
#include <climits>
#include <string>
#include "compiler.h"
#include "script-parser.hh"

#ifdef	_MSC_VER
#pragma warning(disable:4018)
#pragma warning(disable:4102)
#pragma warning(disable:4244)
#pragma warning(disable:4267)
#endif

#undef yywrap
#define yywrap() 1

#define yyterminate()	return token::END_OF_FILE
%}

%option noyywrap nounput batch
%option never-interactive
%option noyy_scan_buffer
%option noyy_scan_bytes
%option noyy_scan_string
%option 8bit
%option nounistd

id    [a-zA-Z_][a-zA-Z_0-9]*
int   [1-9][0-9]*
blank [ \t]

%x C_COMMENT
%x CPP_COMMENT
%x STRING

%{
#define YY_USER_ACTION  yylloc->columns(yyleng);
%}
%%
%{
	typedef yy::script_parser::token token;

	yylloc->step();

	std::string string_buffer;
%}
<INITIAL>{
	\n				{ yylloc->lines(); }
	"^#"			{ yylloc->step(); BEGIN(CPP_COMMENT); }
	"//"			{ yylloc->step(); BEGIN(CPP_COMMENT); }
	"/*"			{ yylloc->step(); BEGIN(C_COMMENT); }

	"if"			return token::TK_IF;
	"else"			return token::TK_ELSE;
	"for"			return token::TK_FOR;
	"while"			return token::TK_WHILE;
	"switch"		return token::TK_SWITCH;
	"case"			return token::TK_CASE;
	"default"		return token::TK_DEFAULT;
	"break"			return token::TK_BREAK;

	"string"		return token::TK_STRING;
	"int"			return token::TK_INTEGER;
	"void"			return token::TK_VOID;

	"return"		return token::TK_RETURN;

	\\\n			yylloc->lines();

	[-+*/=%&|(){}<>\[\],:;&]	return yy::script_parser::token_type(yytext[0]);

	"&&"			return token::TK_LOGAND;
	"||"			return token::TK_LOGOR;
	"=="			return token::TK_EQ;
	"!="			return token::TK_NE;
	">="			return token::TK_GE;
	"<="			return token::TK_LE;
	"<<"			return token::TK_LSHIFT;
	">>"			return token::TK_RSHIFT;

	"+="			return token::TK_ADD_ASSIGN;
	"-="			return token::TK_SUB_ASSIGN;
	"*="			return token::TK_MUL_ASSIGN;
	"/="			return token::TK_DIV_ASSIGN;
	"%="			return token::TK_MOD_ASSIGN;

	{blank}+		yylloc->step();
	\"				{
						yylloc->step();
						string_buffer.clear();
						BEGIN(STRING);
					}
	{int}			{
						errno = 0;
						long n = strtol(yytext, NULL, 10);
						if (n < LONG_MIN || n > LONG_MAX || errno == ERANGE)
							driver.error(*yylloc, "整数が範囲外です。");
						yylval->ival = n;
						return token::TK_IVAL;
					}
	"0"				{
						yylval->ival = 0;
						return token::TK_IVAL;
					}
	{id}			{
						yylval->sval = new std::string(yytext);
						return token::TK_IDENTIFIER;
					}
	.				driver.error(*yylloc, "この文字を識別子で使用することはできません。");
}
<STRING>{
	\n				{
						yylloc->lines();
						driver.error(*yylloc, "文字列がとじられていません");
						string_buffer.clear();
						BEGIN(INITIAL);
					}
	<<EOF>>			{
						driver.error(*yylloc, "文字列の途中でファイルが終了しました");
						string_buffer.clear();
						BEGIN(INITIAL);
					}
	([\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc])+	{
						string_buffer += yytext;
					}
	[^\\\n"]+		{ string_buffer += yytext; }
	\\\n			yylloc->lines();
	\\[^\n]			{
						switch (yytext[yyleng-1]) {
						  case 'n':
							string_buffer += '\n';
							break;

						  default:
							string_buffer += yytext[yyleng-1];
							break;
						}
					}
	\"				{
						BEGIN(INITIAL);
						yylval->sval = new std::string(string_buffer);
						return token::TK_SVAL;
					}
}
<CPP_COMMENT>{
	[^\n]*
	\n				{
						yylloc->lines();
						yylloc->step();
						BEGIN(INITIAL);
					}
}
<C_COMMENT>{
	[^*\n]*
	[^*\n]*\n		{ yylloc->lines(); }
	"*"+[^*/\n]*	/* 余分な*を探す */
	"*"+[^*/\n]*\n	{ yylloc->lines(); }
	<<EOF>>			driver.error(*yylloc, "コメントの途中でファイルが終了しました");
	"*"+"/"			BEGIN(INITIAL);
}
%%

void compiler::scan_begin()
{
	if ((yyin = fopen(file.c_str(), "r")) == 0)
		error(file + " がオープンできません。");
}

void compiler::scan_end()
{
	fclose(yyin);
	yylex_destroy();
}