So I have a .txt file (Excellon) which I want to interpret.
Example file:
M48
FMAT,2
ICI,OFF
METRIC,TZ,000.000
T1C1.016
%
G90
M71
T1
X36551Y-569519
X17780Y-589280
When I scan the file I seperate the statement (e.g. METRIC) and save this in a string. After this I want to execute code based on the value of this string.
What would be the best practice to execute commands on statement detection.
if(String == "METRIC")
{
execute code;
}
else if (String == "M48")
{
execute code;
}
etc.
Or something like this:
switch(String)
{
case: "M48"
execute code;
break;
case: "METRIC"
execute code;
break;
etc.
}
Or are both of these methods wrong and should I use a different method?
I found this: Switch or if statements in writing an interpreter in java they are talking about using a map should I also try this? If so could you provide a simple example because I don't really understand this method.
The proper answer will depend on many factors, but reading between the lines of your post, I am 98% sure that what you want is a simple tokenizer to enum:
enum class Token {
AAA,
BBB,
CCC
};
// Trivially implementable as a if() {} else if {} sequence,
// or as a trie search if you want to get fancy.
Token token_from_string(const std::string& str);
// and in the code.
Token tok = token_from_string(String);
switch(tok) {
case Token::AAA:
break;
case Token::BBB:
break;
case Token::CCC:
break;
}
And then, a good practice is to tokenize the string as soon as it comes out of the stream, and then operate on the token itself.
Q: What would be the best practice to execute commands on statement detection.
You want to change control flow, when a certain string is found.
A switch is saying "pick one of commands based on this variables value". You could also use if/else.
Q: If so could you provide a simple example because I don't really understand this method.
The Excellon file format isn't far away from CNC g-code.
This is an example for a switch from an EXCELLON to GCODE converter.
The trick would be to modify the output method generateFile, to not generate the G-code file using fprint's, but call your commands instead (probably move, lift, wait, etc.).
You could also start with a g-code parser and modify it to handle the excellon format.
Related
I am making a small system and I want to be able to toggle "verbose" text output in the whole system.
I have made a file called globals.h:
namespace REBr{
extern bool console_verbose = false;
}
If this is true I want all my classes to print a message to the console when they are constructing, destructing, copying or doing pretty much anything.
For example:
window(string title="",int width=1280,int height=720):
Width(width),Height(height),title(title)
{
if(console_verbose){
std::cout<<"Generating window #"<<this->instanceCounter;
std::cout<<"-";
}
this->window=SDL_CreateWindow(title.c_str(),0,0,width,height,SDL_WINDOW_OPENGL);
if(console_verbose)
std::cout<<"-";
if(this->window)
{
this->glcontext = SDL_GL_CreateContext(window);
if(console_verbose)
std::cout<<".";
if(this->glcontext==NULL)
{
std::cout<<"FATAL ERROR IN REBr::WINDOW::CONSTR_OPENGLCONTEXT: "<<SDL_GetError()<<std::endl;
}
}
else std::cout<<"FATAL ERROR IN REBr::WINDOW::CONSTR_WINDOW: "<<SDL_GetError()<<std::endl;
if(console_verbose)
std::cout<<">done!"<<endl;
}
Now as you can see I have a lot of ifs in that constructor. And I REALLY dont want that since that will slow down my application. I need this to be as fast as possible without removing the "loading bar" (this helps me determine at which function the program stopped functioning).
What is the best/fastest way to accomplish this?
Everying in my system is under the namespace REBr
Some variants to achieve that:
Use some logger library. It is the best option as it gives you maximum flexibility and some useful experience ;) And you haven't to devise something. For example, look at Google GLOG.
Define some macro, allowing you to turn on/off all these logs by changing only the macro. But it isn't so easy to write such marco correctly.
Mark your conditional flag as constexpr. That way you may switch the flag and, depending on its value, compiler will optimise ifs in compiled program. But ifs will still be in code, so it looks kinda bulky.
Anyway, all these options require program recompilation. W/o recompilation it is impossible to achieve the maximum speed.
I often use a Logger class that supports debug levels. A call might look like:
logger->Log(debugLevel, "%s %s %d %d", timestamp, msg, value1, value2);
The Logger class supports multiple debug levels so that I can fine tune the debug output. This can be set at any time through the command line or with a debugger. The Log statement uses a variable length argument list much like printf.
Google's logging module is widely used in the industry and supports logging levels that you can set from the command line. For example (taken from their documentation)
VLOG(1) << "I'm printed when you run the program with --v=1 or higher";
VLOG(2) << "I'm printed when you run the program with --v=2 or higher";
You can find the code here https://github.com/google/glog and the documentation in the doc/ folder.
I am working on a parser to handle hundreds of possible commands, some with their own subcommands. I've got a tokenizer pulling out the commands into an object, but from there I just have a very very long list of if statements checking for each individual case.
Is there a better or more efficient way to check for each individual case rather than 100+ specified if statements?
For example, a command could be : A,CONFIG,SET,GARBLE,5. This would launch into setting the config for garble to 5. But that varies from A,CONFIG,SET,JAM,5 or another command like P,DO,ACTION which is itself another command entirely.
Right now my program covers all of these cases with individual if statements, but I feel like it's really inefficient. If you're the last command, you're taking the longest no matter what. Is there a better, more practical way to do this?
If you want code examples, it's really as simple as it sounds. After getting the object full of tokenized commands, I have an absolutely huge check where it individual looks for stuff like if (command == "P") launch into the command handler for P commands.
Depending on how complex your commands are this might be a job for a 'real' parser, either a hand rolled recursive descent parser or one built using tools like lexx and yacc.
Alternatively, if that is overkill for your use case you could use a hash table of function pointers or command objects, look up the command in the table and call the function or a method on the object to process it. That would be more maintainable than a bunch of if statements in my opinion.
Arrange your commands alphabetically, then use nested case statements dealing with one letter at a time.
switch( command[0] ) {
case 'A': ...( code to handle commands starting with A ) ... break;
case 'B':
switch( command[1] ) {
case 'A': ... ( code to handle commands BA... ) ... break;
}
...
}
The switch statement optimizes the jump to the correct case.
You can use configuration-like functionalities.
I think it's better. You would basically have to create a configuration file with a dictionary containing all of the commands and their actions, and the program would just grab the command related to the keyword.
Pseudocode:
{
"COMMAND_1": function_1,
"COMMAND_2": function_2
}
This is JSON-like but you can do it however you like obviously.
The functions would be basically void pointers to functions executing the related code.
Your code would basically become something like:
token = get_token();
if (void* command = token_in_dictionary(token, dictionary)){
command(get_params());
}else{
printf("Invalid token");
}
I am working with Perl embedded in our application. We have installed quite a few C++ functions that are called from within Perl. One of them is a logging function. I would like to add the file name and line number of the Perl file that called this function to the log message.
I know on the Perl side I can use the "caller()" function to get this information, but this function is already used in hundreds of locations, so I would prefer to modify the C++ side, is this information passed to the C++ XSUB functions and if so how would I get at it?
Thanks.
This should work:
char *file;
I32 line;
file = OutCopFILE(PL_curcop);
line = CopLINE(PL_curcop);
Control ops (cops) are one of the two ops OP_NEXTSTATE and op_DBSTATE,
that (loosely speaking) are separate statements.
They hold information important for lexical state and error reporting.
At run time, PL_curcop is set to point to the most recently executed cop,
and thus can be used to determine our current state.
— cop.h
Can't you call perl builtins from XS? I confess I don't know.
If not, you could always do something like this:
sub logger { _real_logger(caller, #_) }
assuming logger is what your function is called (and you rename your C++ XS function to _real_logger. You could also do this, presumably, if you need to hide yourself in the call tree:
sub logger {
unshift #_, caller;
goto &_real_logger;
}
which is of course the normal form of goto used in AUTOLOAD.
These will add overhead, of course, but probably not a big deal for a logging function.
In one of my projects, I need to be able to provide a very simple variable find-and-replace parser (mostly for use in paths). Variables are used primarily during startup and occasionally to access files (not the program's primary function, just loading resources), so the parser need not be high-performance. I would greatly prefer it to be thread-safe, however.
The parser needs to be able to store a set of variables (map<string, string> at the moment) and be able to replace tokens with the corresponding value in strings. Variable values may contain other variables, which will be resolved when the variable is used (not when it is added, as variables may be added over time).
The current variable grammar looks something like:
$basepath$/resources/file.txt
/$drive$/$folder$/path/file
My current parser uses a pair of stringstreams ("output" and "varname"), writes to the "output" stream until it finds the first $, the "varname" stream until the second $, then looks up the variable (using the contents of varname.str()). It's very simple and works nicely, even when recursing over variable values.
String Parse(String input)
{
stringstream output, varname;
bool dest = false;
size_t total = input.length();
size_t pos = 0;
while ( pos < total )
{
char inchar = input[pos];
if ( inchar != '$' )
{
if ( dest ) output << inchar;
else varname << inchar;
} else {
// Is a varname start/end
if ( !dest )
{
varname.clear();
dest = true;
} else {
// Is an end
Variable = mVariables.find(varname.str());
output << Parse(Variable.value());
dest = false;
}
}
++pos;
}
return output.str();
}
(error checking and such removed)
However, that method fails me when I try to apply it to my desired grammar. I would like something similar to what Visual Studio uses for project variables:
$(basepath)/resources/file.txt
/$(drive)/$(folder)/path/file
I would also like to be able to do:
$(base$(path))/subdir/file
Recursing in the variable name has run me into a wall, and I'm not sure the best way to proceed.
I have, at the moment, two possible concepts:
Iterate over the input string until I find a $, look for a ( as the next character, then find the matching ) (counting levels in and out until the proper close paran is reached). Send that bit off to be parsed, then use the returned value as the variable name. This seems like it will be messy and cause a lot of copying, however.
The second concept is to use a char *, or perhaps char * &, and move that forward until I reach a terminating null. The parser function can use the pointer in recursive calls to itself while parsing variable names. I'm not sure how best to implement this technique, besides having each call keep track of the name it's parsed out, and append the returned value of any calls it makes.
The project need only compile in VS2010, so STL streams and strings, the supported bits of C++0x, and Microsoft-specific features are all fair game (a generic solution is preferable in case those reqs change, but it's not necessary at this point). Using other libraries is no good, though, especially not Boost.
Both my ideas seem like they're more complicated and messier than is needed, so I'm looking for a nice clean way of handling this. Code, ideas or documents discussing how best to do it are all very much welcome.
Simple solution is to search for the first ')' in the string, then move backwards to see if there's an identifier preceeded by "$(". If so, replace it and restart your scanning. If you don't find "$(" identifier, then find the next ')' - when there isn't one you're finished.
To explain: by searching for a ) you can be sure that you're finding a complete identifier for your substitution, which then has the chance to contribute to some other identifier used in a subsequent substitution.
EXAMPLE
Had a great time on $($(day)$(month)), did you?
Dictionary: "day" -> "1", "month" -> "April", "1April" -> "April Fools Day"
Had a great time on $($(day)$(month)), did you?
^ find this
Had a great time on $($(day)$(month)), did you?
^^^^^^ back up to match this complete substitution
Had a great time on $(1$(month)), did you?
^ substitution made, restart entire process...
Had a great time on $(1$(month)), did you?
^ find this
etc.
Im trying to parse a file using Bison/Yacc but i want to pause the parsing for a while. The reason i want to do this is that i want to process a huge file sequentially and simulate a java iterator using hasNext() and next() methods.
A trivial example would be, splitting a file by line using yacc so i could call:
while(myYaccObj.hasNext())
{
std::string line = myYaccObj.next()
}
I cant find how to "pause" the file scanning. Is there a way to do that?
The easiest way is just to do the pause directly in you action code. For example, you could have a rule:
rule: whatever { Pause(); }
;
This would call your Pause function which could pause and/or do whatever you want. When you want to continue parsing, simply have the Pause function return.
In fact pausing for me means "keep the state and finish the yyparse" call. For example in my gramar I would do:
rule:
SaveLine;
Pause;
And then the control is returned to my code. I do what i have to do and then I call:
yyparse_resume();
and the parsing continues until another pause or EOF.