我正在编写一个小程序来解析Sony Cell SPU指令的输入文件,并将指令的二进制格式输出到文本。
基本理念是:
输入文本格式是指令rt / ra / rb
a r3,r2,r1
ah r6,r5,r4
输出文本格式为:opcode / rb / ra / rt
00011000000000000100000100000011
00011001000000010000001010000110
基本上,我正在解析命令语法(a,ah等等)并确定操作码。该信息还提供了指令的格式(寄存器格式)。一旦我知道正在访问的寄存器,我将这些值转换为7位值(r3 = 0000011等)。然后,我将32位转换的指令写入输出文本。
我遇到的问题是如何解析指令语法。
特别是,我想到的是将输入文本文件的每一行读入char array
并检查索引的低位并将其与每个指令的字符串进行比较,但是我认为这不是一个好方法。
执行此类解析和比较的好方法是什么?
答案 0 :(得分:0)
如果我理解你,你想避免一连串的
if(strcmp(array, "cmd1") == 0)
else if(strcmp(array, "cmd2") == 0)
//...
然后你可以尝试这样的事情:
switch(array[0])
{
case 'a':
switch(array[1])
{
case ' ':
// end of command!
break;
case 'a':
// ...
break;
default:
// unknown command
break;
}
break;
case 'b':
// analogously
break;
default:
// unknown command
break;
}
根据命令的数量及其长度,这很容易变得不可读,但是......
另一种方法:使用::std::unordered_map(或:: std :: tr1 :: unordered_map,如果使用旧的C ++标准)。如果更合适,将字符串映射到适当的处理函数(指向)或(多态!)类。确保通过find(而不是索引运算符[]检索处理程序,因为这会添加一个新元素)并简单地调用它...如果你有一个相当大的指令集,这种方法很有意思。
也许是这样的:
void a(char* cmd) {/*...*/}
void ah(char* cmd) {/*...*/}
/* ... */
typedef ::std::unordered_map<char const*, void(*)(char*)> Handlers
void main(int, char*[])
{
Handlers handlers;
handlers["a"] = &a;
handlers["ah"] = &ah;
/* open file */
char array[128];
char* arguments;
/* for each line: */
{
/*
*read into array;
* you need to separate the command from the
* parameters e. g. by setting the first space following
* to 0 ('\0'), and setting arguments to the first
* non-whitespace afterwards
*/
Handlers::iterator handler = handlers.find(array);
if(handler == handlers.end())
{
// unknown command
}
else
{
(*handler)(arguments);
}
}
return 0;
}