#!/usr/bin/env python ## ## This file is part of Mipsy, a tiny MIPS simulator ## Copyright (C) 2003 Benoit Perrot ## ## Mipsy 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. ## ## Mipsy 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## import sys import string, re import mipsy from mipsy import license, depth, define_id parser = mipsy.InstructionSetParser() instructions = parser.parse(sys.stdin) #### Mipsy Flex scanner generator -------------------------- ## Prologue ---------------------------- print "%{ /* -*- C++ -*- */" print license print """ #include #include \"common.hh\" #include \"misc/escape.hh\" #include \"vm/cpu.hh\" #include \"parse/asm-scan.hh\" #define YY_NEVER_INTERACTIVE 1 #define YY_USER_INIT \\ do { \\ yylloc->begin.filename = current_file; \\ yylloc->end.filename = current_file; \\ } while (0) #define YY_USER_ACTION \\ yylloc->columns (yyleng); static std::string current_file; using inst::Register; using vm::Cpu; %} %option noyywrap %option nounput %option debug %x STATE_STRING eol \\n|\\r|\\n\\r|\\r\\n dec_int [0-9]+ hex_int 0x[0-9A-Fa-f]+ label [a-zA-Z_][a-zA-Z_0-9]* %% %{ yylloc->step (); %} [ \\t]+ yylloc->step (); [#;][^\\n\\r]* yylloc->step (); {eol} yylloc->lines (yyleng); yylloc->step (); \"(\" return LPAREN; \")\" return RPAREN; \",\" return COMMA; \"+\" return EXP_ADD; \"-\" return EXP_SUB; \"*\" return EXP_MUL; \"/\" return EXP_DIV; \".text\" return DIR_TEXT; \".data\" return DIR_DATA; \".word\" return DIR_WORD; \".asciiz\" return DIR_ASCIIZ; \".space\" return DIR_SPACE; """ ## Body -------------------------------- for inst in instructions: print '"' + inst.opcode + '"\t\t\treturn ' + define_id(inst.opcode) + ";" ## Epilogue ---------------------------- print """ \"$zero\" { yylval->reg = new Register(Register::general, Cpu::zero); return REGISTER; }""" for k, r in [("v", range(2)), ("a", range(4)), ("t", range(10)), ("s", range(8))]: for i in r: print "\"$" + k + str(i) + "\" {" print " yylval->reg = new Register(Register::general, " + \ "Cpu::" + k + str(i)+ ");" print " return REGISTER;\n}" print """ \"$sp\" { yylval->reg = new Register(Register::general, Cpu::sp); return REGISTER; } \"$fp\" { yylval->reg = new Register(Register::general, Cpu::fp); return REGISTER; } \"$ra\" { yylval->reg = new Register(Register::general, Cpu::ra); return REGISTER; } \"$x\"{dec_int} { if (!parse::unlimited_regs_p) { std::cerr << *yylloc << \": unlimited registers prohibited\" << std::endl; exit_set (exit_scan); } yylval->reg = new Register(Register::unlimited, atoi(yytext +2)); return REGISTER; } {label} { yylval->label = new inst::Label (yytext); return LABEL; } {label}\":\" { std::string label = yytext; label.resize(yyleng - 1); yylval->label = new inst::Label (label); return LABEL_DEF; } -?{dec_int} yylval->i = atoi (yytext); return INTEGER; -?{hex_int} yylval->i = strtoll (yytext, 0, 16); return INTEGER; '\\\\a' yylval->i = '\\a'; return INTEGER; '\\\\b' yylval->i = '\\b'; return INTEGER; '\\\\f' yylval->i = '\\f'; return INTEGER; '\\\\n' yylval->i = '\\n'; return INTEGER; '\\\\r' yylval->i = '\\r'; return INTEGER; '\\\\t' yylval->i = '\\t'; return INTEGER; '\\\\v' yylval->i = '\\v'; return INTEGER; '\\\\[\\\\\\']' yylval->i = yytext[1]; return INTEGER; '\\\\.' { std::cerr << *yylloc << \": unrecognized escape: \" << escape (yytext) << std::endl; exit_set (exit_scan); } '[^\\'\\n\\r\\\\]' yylval->i = yytext[1]; return INTEGER; \\\" yylval->s = new std::string; BEGIN STATE_STRING; { \\\" { BEGIN INITIAL; return STRING; } \\\\[0-7]{3} { long c = strtol (yytext + 1, 0, 8); if (c > 255) { std::cerr << *yylloc << \": invalid escape: \" << escape (yytext) << std::endl; exit_set (exit_scan); } else *(yylval->s) += c; } \\\\x[0-9a-fA-F]{2} { *(yylval->s) += strtol (yytext + 2, 0, 16); } \\\\a *(yylval->s) += '\\a'; \\\\b *(yylval->s) += '\\b'; \\\\f *(yylval->s) += '\\f'; \\\\n *(yylval->s) += '\\n'; \\\\r *(yylval->s) += '\\r'; \\\\t *(yylval->s) += '\\t'; \\\\v *(yylval->s) += '\\v'; \\\\[\\\\\"\"] *(yylval->s) += yytext[1]; \\\\. { std::cerr << *yylloc << \": unrecognized escape: \" << escape (yytext) << std::endl; exit_set (exit_scan); } [^\\\"\\n\\r\\\\]+ yylval->s->append (yytext, yyleng); {eol}+ { yylloc->lines (yyleng); yylval->s->append (yyleng, '\\n'); } <> { std::cerr << *yylloc << \": unexpected end of file in a string\" << std::endl; exit_set (exit_scan); BEGIN INITIAL; return STRING; } } . { std::cerr << *yylloc << \": invalid character: `\" << escape (yytext) << \"'\" << std::endl; exit_set (exit_scan); } %% namespace parse { void scan_open (const std::string &name) { yy_flex_debug = trace_scan_p; if (name == \"-\") { yyin = stdin; current_file = \"standard input\"; } else { yyin = fopen (name.c_str (), \"r\"); current_file = name; if (!yyin) { std::cerr << program_name << \": cannot open `\" << name << \"': \" << strerror (errno) << std::endl; exit (1); } } } void scan_close (void) { fclose (yyin); } } """