yhirose / cpp-peglib

A single file C++ header-only PEG (Parsing Expression Grammars) library
MIT License
894 stars 112 forks source link

if enable PackratParsing ,program crash #33

Closed lingzhp closed 6 years ago

lingzhp commented 6 years ago

i set enablePackratParsing=1 and my peg is auto syntax = R"xyz(decl<-decl_specs init_declarator_list ';'

    decl_specs<-'char' / 'short' / 'int' / 'long' / 'float'

    init_declarator_list<-direct_declarator
    / direct_declarator '=' initializer

    direct_declarator<-id

    initializer<-additive

    additive<-left:multiplicative "+" right : additive
    / multiplicative

    multiplicative<-left : primary "*" right : multiplicative
    / primary

    primary<-primary_exp
    / "(" additive : additive ")"

    primary_exp<-id
    / const)xyz";
  parser parser(syntax);

when I debug ,i set breakpoint after "parser parser(syntax);",but it crashed

yhirose commented 6 years ago

@lingzhp, thank you for the feedback. I checked your PEG grammar, but this is not valid PEG grammar for cpp-peglib. For example, left:, right:, additive: are reported as errors with the peglint tool. Also the grammar is missing id and const rules. Could you fix the errors and try it again?

I have a question about enablePackratParsing=1. What does it mean? In order to enable packrat parsing, we have to make a valid parser object first, then call parser.enable_packrat_parsing(). You can see the "How to use" example.

lingzhp commented 6 years ago

thanks for your suggestion,i modifed my PEG grammar,the issue still exist. enablePackratParsing is in Context class.This PackratParsing occur during paserGenerating. I want to fast paserGenerating

yhirose commented 6 years ago

@lingzhp, could you show me the modified code? I'll try to reproduce it on my machine. Thanks!

lingzhp commented 6 years ago

class Context { public: const char* path; ... --const bool enablePackratParsing; ++++ bool enablePackratParsing; ...

Context( const char a_path, const char a_s, size_t a_l, size_t a_def_count, std::shared_ptr a_whitespaceOpe, bool a_enablePackratParsing, Tracer a_tracer) : path(a_path) , s(a_s) , l(a_l) , error_pos(nullptr) , message_pos(nullptr) , value_stack_size(0) , nest_level(0) , in_token(false) , whitespaceOpe(a_whitespaceOpe) , in_whitespace(false) , def_count(a_def_count) , enablePackratParsing(a_enablePackratParsing) , cache_registered(enablePackratParsing ? def_count (l + 1) : 0) , cache_success(enablePackratParsing ? def_count (l + 1) : 0) , tracer(a_tracer) {

yhirose commented 6 years ago

@lingzhp, since Context is an internal class, the above change is not allowed. Here is a simple sample to enable the packrat parsing mode.

auto syntax = R"(
        # Grammar for Calculator...
        Additive    <- Multitive '+' Additive / Multitive
        Multitive   <- Primary '*' Multitive / Primary
        Primary     <- '(' Additive ')' / Number
        Number      <- < [0-9]+ >
        %whitespace <- [ \t]*
    )";

parser parser(syntax);

parser.enable_packrat_parsing(); // Enable packrat parsing.

auto ret = parser.parse(" (1 + 2) * 3 ");

I am also concerned with the crash that you reported. Could you give me you modified PEG rules, so that I could try to reproduce the problem.

Thank you,

lingzhp commented 6 years ago
auto syntax = R"xyz(decl<-decl_specs init_declarator_list ';'

    decl_specs<-'char' / 'short' / 'int' / 'long' / 'float'

    init_declarator_list<-direct_declarator / direct_declarator '=' initializer

    direct_declarator<-id
    initializer<-additive

    additive<-Multitive '+' Additive / Multitive

    multiplicative<-Primary '*' Multitive / Primary

    primary<-'(' Additive ')' / primary_exp

    primary_exp<-id / const
    id<-[A-Za-z0-9?]+
    const->< [0-9]+ >

)xyz"; I means: can it enable packrat when “parser parser(syntax);” ? I want to accelerate generator parser

yhirose commented 6 years ago

Unfortunately, the above grammar is not a valid PEG. It has still errors.

First of all, const->< [0-9]+ > should be const <-< [0-9] >

Even after the adjustment, the grammar has the following errors with peglint:

12:41 'Primary' is not defined.
12:29 'Multitive' is not defined.
14:14 'Additive' is not defined.
10:36 'Multitive' is not defined.
10:25 'Additive' is not defined.

When it comes to enabling packrat parsing, you must call enable_packrat_parsing() method:

std::string text;
...

peg::parser parser(syntax); // 'syntax' must be a valid PEG
if (parser) {
    // The 'syntax' is valid PEG
    parser. enable_packrat_parsing(); // Enable packrat parsing
    auto ret = parser.parse(text.data(), text.length()); // Parse source text with packrat mode
} else {
    // The 'syntax' has error(s)
}