lpeter1997 / cppcmb Goto Github PK
View Code? Open in Web Editor NEWA generic C++17 parser-combinator library with a natural grammar notation.
License: MIT License
A generic C++17 parser-combinator library with a natural grammar notation.
License: MIT License
I am trying to write a parser using CppCmb that will match N characters. I see that there are operators for matching zero or many (*) and one or many (+). I did not see the equivalent {N} operator that many grep languages afford.
My use case is to actually match up to N characters or the first null '\0' character from an input stream. E.g. if N is 3 and "\0" is the null character escape code, matching strings would be:
INPUT | NOTES |
---|---|
"123" | "123" is captured |
"ABCD" | "ABC" is captured, "D" remains and may be used for a different match |
"12\0" | "12" or "12\0" as captures are fine, as long as the "\0" is consumed |
"\0" | "" or "\0" are acceptable captures, as long as the "\0" is consumed |
Examples of not matching strings would be:
INPUT | NOTES |
---|---|
"12" | where there is no "\0" following the "2" |
"" | an empty stream with no "\0" |
I tried to see if I could use a template with a non type parameter to recursively apply a match where N is decremented each call, but It didn't seem to work correctly with your cppcmb_decl / def macro system.
Here is a function that will match up to N characters or the first NULL character given a filter predicate and a begin and end iterator. It returns a pair containing a boolean of the match outcome and the iterator pointing to the furthest character in the stream that was parsed.
template <size_t N, typename F, typename I>
constexpr auto parseNor0(F&& filter, I begin, I end) {
if constexpr (N == 0) {
return std::make_pair(false, begin);
}
if (*begin == '\0') {
return std::make_pair(true, begin);
}
if (filter(*begin)) {
if constexpr (N == 1) {
return std::make_pair(true, begin);
}
if constexpr (N > 1) {
if (++begin != end) {
//call recursively
return parseNor0<N-1>(filter, begin, end);
}
}
}
return std::make_pair(false, begin);
}
Do you have any suggestions on how to match N times?
If I have a code like below
cppcmb_decl(expr, pc::product<>);
cppcmb_def(expr) = pc::pass
| (num & match<'+'> & num)// [pc::select<1,0,2>]
;
std::string to_num(std::vector<char> const& chs) {//just for conversion from vector<char>->string
const std::string str(chs.begin(), chs.end());
return str;
}
cppcmb_def(num) = (+digit)[to_string];
cppcmb_def(digit) = pc::one[pc::filter(isdigit)];
I get an error like
error: no viable conversion from returned value of type 'result<product<std::__1::vector<char, std::__1::allocator<char> >, char, std::__1::vector<char, std::__1::allocator<char> >>>' to function return type 'result<product<(no argument), (no argument), (no argument)>>'
if I specify a return type to template arguments of pc::product
cppcmb_decl(expr, pc::product<std::string,char,std::string>);
The compiltion succeeds.
When can we use pc::product<>
without template arguments?
Sorry for the long time no activity, it's time to pick this project back up where I left off!
The first thing being, this project needs proper error-types to report more precise errors in case of a parse failure.
Hi, this library is nice! Good work! Though it has many advanced C++ template code which is a bit hard for me.
Back to my question, I mean in my application, I have my own lexer(mainly the C-preprocessor) implemented myself, so my question is: can the library support parsing rules for custom lexer.
For example, the lexer has some kinds of std::vector<Token>
supplied, the Token
class may have definition like:
class Token
{
TokenKind kind;
std::string lexeme;
}
So, I would like this library to parse the Token
stream not the char
stream.
Any suggestions?
Thanks.
The documentation says that CppCmb works on an InputIterator for tokens, but I'm wondering, don't you actually require a ForwardIterator (that allows you to perform backtracking)?
For example consider something with a structure like alt< seq< one, one, one >, one >
with an input of two tokens, where you are effectively backtracking to let the second branch of the alt
start at the same position as the first...
Hi,
I don't know if its possible but maybe this can be somehow handled better:
If I have a grammar rule like so:
cppcmb_def(expr) = pc::pass
| (expr & match<Token::PLUS> & primary) [BinaryExpr::make]
| (expr & match<Token::MINUS> & primary) [BinaryExpr::make]
| primary
%= pc::as_memo_d;
And the method looks like this:
class BinaryExpr: public Expr {
static ExprPtr make(ExprPtr left_ ,ExprPtr right_ , Token op_ )
}
Can we have better error messages, that indicate what was wrong?
The README doesn't do justice to the library and it's overall awful. Should be rewritten to something like the other libraries.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.