coal
if you have any questions i'll be glad to answer
coal
also, there's a lot of resources online, you can just google it and you'll certainly find an answer, probably from stackoverflow
Anonymous
That's inspiring
Anonymous
I will go for it
Anonymous
coal
i see
coal
are you using a state machine
Anonymous
and the source is in a seperate string, not a mmapped file or similar
Anonymous
coal
state machines traverse through the input one character at a time
Anonymous
that is what i’m doing
coal
and whenever it finds a valuable character, it changes its state, which allows it to expect different kind of tokens
Anonymous
then yes i am
coal
so you have a state/context class instance which holds all of the valuable information, right
coal
coal
how are you doing recursiveness in a state machine
coal
i mean, for a parser its understandable because of the nested nodes
coal
but for a state machine i dont find the need to use recursiveness
Anonymous
the way my parser currently works is as a parser combinator
eg, Char, String, Any, Sequence, Or, OneOrMore, ZeroOrMore, Range, Stack, and so on
it also does basic backtracking and input modification
coal
are you writing a parser for a language
Anonymous
if you like, this is my Rules.h for the parser https://gist.github.com/abba506dd2083e4909f0e522f4981c41
coal
what is the usage of this
coal
i mean, what does it do (your project)
Anonymous
it’s current usage is as a preprocessor
coal
for what kind of input
coal
cpp?
Anonymous
more or less
this is what i currently have
https://gist.github.com/788d44482d202d0a1388f08d86b1842f
coal
oh my god you use new so many times it kinda unnerves me
coal
but i see what you're doing
coal
by any chance does it work in top of patterns?
coal
or is it a drop-in replacement of the original preprocessor that the compiler has
Anonymous
i’m not sure what you mean
coal
does it work like a compiler preprocessor
coal
also do you have a general repo for all of these different files
coal
i see
coal
i found the repo in your github
Anonymous
https://github.com/mgood7123/CPP
coal
i see
coal
very cool
Anonymous
if you want, the is the current tests (output) i am running for it https://gist.github.com/mgood7123/db1150767b6065521c432962ca61d02d
(most of the tests are in different files, eg the iterator tests are in Iterator.h, Rule tests are in General.cpp (because IDE doesnt like #ifdef GTEST_API_ being in Rules.h for some reason), basic iterator match tests are in IteratorMatcher.h, CPP tests (a few, not a lot) are in General.h )
coal
coal
have you considered following the factory pattern
coal
i think it would make your code a little cleaner
coal
for example, you could make a factory for rules and then derive different kind of rules from it
coal
some (very important) parsers, such as the one for V8 engine, use this pattern
Anonymous
i’m currently experementing with a stack based rule https://gist.github.com/2ae9b3090f80a472d0df0f702466aba9 as i am trying to implement https://gist.github.com/mgood7123/168c4b17dd814fd977a2db88af5d9f5f in order to correctly recursively expand function macro’s
Anonymous
Anonymous
but i do not understand this enough to be able to implement it https://gist.github.com/mgood7123/168c4b17dd814fd977a2db88af5d9f5f
Anonymous
coal
very verbose explanation, but basically it means:
traverse all characters after the #define ...
read the first parameter
if you encounter a ( token, this means the first parameter is a function macro
set the context to parse function-like arguments, generate a function macro rule, insert function parameters to the rule context
continue reading and save the rest of the macro arguments into an arguments vector
save the rule object into a stack
Anonymous
looks complicated
for me, using class inheritence and overloading is much easier to implement
struct OneOrMore : RuleHolder {
OneOrMore(Rule * rule, Action action = NO_ACTION) : RuleHolder(rule, action) {}
using Rule::match;
virtual IteratorMatcher::MatchData match(Iterator<std::string> &iterator, bool doAction = true) override {
IteratorMatcher::MatchData match = rule->match(iterator, doAction);
if (match) {
while (true) {
IteratorMatcher::MatchData tmp = rule->match(iterator, doAction);
if (!tmp) break;
match.end = tmp.end;
match.matches += tmp.matches;
}
if (doAction) action(Input(iterator, match, match.matches));
}
return match;
}
};
coal
if you do that you end with verbose dependencies to other classes
Anonymous
Anonymous
coal
how so?
you're forced to initialize a RuleHolder within your derived Rule class, which makes you depend of the RuleHolder object for accessing properties of your class. Imagine you wanted to access some property x, which both your current class and RuleHolder has. Under this context, you'd need to forcefully use this-> to specify that you want to access this object property (aka, accessing members of dependent base classes)
coal
Anonymous
coal
but i meant the parameters for the definition macro
Anonymous
another one is
struct Char : Rule {
char character;
Char(char character, Action action = NO_ACTION) : character(character), Rule(action) {}
using Rule::match;
virtual IteratorMatcher::MatchData match(Iterator<std::string> &iterator, bool doAction = true) override {
auto match = IteratorMatcher::match(iterator, character);
if (match && doAction) {
action(Input(iterator, match, match.matches));
}
return match;
}
};
coal
whats char for
coal
when i read your code, i think of Rule as a class that defines the macro itself, rather than individual segments of it
Anonymous
RuleHolder is basically a RAII-like class for holding mulitple Rule instances so the same rule instance can be used in multiple rule declerations
for example
auto x = new Char(‘x’);
auto seq1 = new Sequence({x, x}); // match xx
auto or1 = new Or({ seq1, x, new Any() }); // match xx, x, otherwise anything except EOF
Anonymous
when i read your code, i think of Rule as a class that defines the macro itself, rather than individual segments of it
Rule is the base class which basically tells the user that this class is a Rule object and as such can be added to a collection of other Rule objects without having to worry about managing rules of different object types
eg trying to add a Foo object to a collection of Bar objects cannot be done unless Foo extends Bar, or unless you use std::pair or similar which would then get very complicated as you do not know which rules you may encounter
eg someone may create a new type of rule and then your class is broken because it does not accept this new type of rule because it does not extend Rule
coal
ahhhhhhhhhhhhhhhhhhhhh
coal
i see now
coal
i did something like this before
coal
but with wildcards, and rules didnt have unique classes, instead they set a state and as long as the string continued matching, it would be compliant with the pattern
coal
Anonymous
cool
coal
also, why do you use new so much
coal
is there a special advantage in it rather than allocating all of these objects in the stack
coal
do you use them in many other scopes, why dont you use smart pointers if so
Anonymous
because class inheritence does not work without new
eg
Rule obj = Char(‘x’);
a.match(“x”); // calls Rule::Match instead of Char::Match
Anonymous
and referneces would just complicate the grammar (eg every rule would have to be pre-defined before use and you cannot just construct the grammar on the fly)
coal
i see
coal
have you considered using templates instead
coal
so a.match calls Rule::Match which calls DerivedRule::match