Skip to content

The debug information output by nimbleparse may contain errors. #599

@paomian

Description

@paomian

I have a yacc file syntax_debug.y

%start root
%left "OR"
%left "AND" "UNLESS"
%left "CMP_EQ" "NEQ" "LT" "LTE" "GT" "GTE"
%left "ADD" "SUB"
%left "MUL" "DIV" "MOD"
%right "POW"

//%token "OPEN_BRACKET" "CLOSE_BRACKET" "DOT"

%%

root -> Result<Expr, ()>:
      expr { Ok($1?) }
    ;

expr -> Result<Expr, ()>:
      log_expr { Ok(Expr::LogSelector($1?)) }
    ;

log_expr -> Result<LogSelectorExpr, ()>:
      selector { 
        Ok(LogSelectorExpr::new($1?))
      }
    | selector pipeline_expr { 
        Ok(PipelineExpr::new(LogSelectorExpr::new($1?), $2?))
      }
    | "OPEN_PARENTHESIS" log_expr "CLOSE_PARENTHESIS" { Ok($2?) }
    ;

selector -> Result<Vec<Matcher>, ()>:
    "OPEN_BRACE" matchers "CLOSE_BRACE" { Ok($2?) }
    | "OPEN_BRACE" "CLOSE_BRACE" { Ok(vec![]) }
    ;

matchers -> Result<Vec<Matcher>, ()>:
      matcher { Ok(vec![$1?]) }
    | matchers "COMMA" matcher { 
        let mut matchers = $1?;
        matchers.push($3?);
        Ok(matchers)
      }
    ;

matcher -> Result<Matcher, ()>:
      "IDENTIFIER" "EQ" "STRING" {
        let name = $lexer.span_str($1?.span()).to_string();
        let value = $lexer.span_str($3?.span()).trim_matches('"').to_string();
        Ok(Matcher::new(MatchOp::Equal, name, value))
      }
    | "IDENTIFIER" "NEQ" "STRING" {
        let name = $lexer.span_str($1?.span()).to_string();
        let value = $lexer.span_str($3?.span()).trim_matches('"').to_string();
        Ok(Matcher::new(MatchOp::NotEqual, name, value))
      }
    | "IDENTIFIER" "RE" "STRING" {
        let name = $lexer.span_str($1?.span()).to_string();
        let value = $lexer.span_str($3?.span()).trim_matches('"').to_string();
        Ok(Matcher::new(MatchOp::RegexMatch, name, value))
      }
    | "IDENTIFIER" "NRE" "STRING" {
        let name = $lexer.span_str($1?.span()).to_string();
        let value = $lexer.span_str($3?.span()).trim_matches('"').to_string();
        Ok(Matcher::new(MatchOp::RegexNotMatch, name, value))
      }
    ;

pipeline_expr -> Result<Vec<StageExpr>, ()>:
      pipeline_stage { Ok(vec![$1?]) }
    | pipeline_expr pipeline_stage { 
        let mut stages = $1?;
        stages.push($2?);
        Ok(stages)
      }
    ;

pipeline_stage -> Result<StageExpr, ()>:
      line_filters { Ok(StageExpr::LineFilter($1?)) }
    ;


line_filters -> Result<LineFiltersExpr, ()>:
      line_filter { 
        let mut filters = LineFiltersExpr::new();
        filters.add($1?);
        Ok(filters)
      }
    | line_filters line_filter { 
        let mut filters = $1?;
        filters.add($2?);
        Ok(filters)
      }
    ;

line_filter -> Result<LineFilterExpr, ()>:
    filter "STRING" {
        let value = $lexer.span_str($2?.span()).trim_matches('"').to_string();
        Ok(LineFilterExpr::new(value, $1?, None))
      }
    ;

filter -> Result<FilterExpr, ()>:
    "PIPE_MATCH" {
        Ok(FilterExpr::Match)
      }
    | "PIPE_EXACT" {
        Ok(FilterExpr::Exact)
      }
    | "PIPE_PATTERN" {
        Ok(FilterExpr::Pattern)
      }
    | "NRE" {
        Ok(FilterExpr::NRE)
      }
    | "NEQ" {
        Ok(FilterExpr::NotEqual)
      }
    | "NPA" {
        Ok(FilterExpr::NPA)
      }
    ;
%%

syntax.l

%%
%%
nimbleparse -y grmtools syntax.l  syntax_debug.y "empty_file"

I got error

Shift/Reduce conflicts:
   State 16: Shift("NEQ") / Reduce(pipeline_stage: "line_filters")
   State 16: Shift("NPA") / Reduce(pipeline_stage: "line_filters")
   State 16: Shift("PIPE_EXACT") / Reduce(pipeline_stage: "line_filters")
   State 16: Shift("NRE") / Reduce(pipeline_stage: "line_filters")
   State 16: Shift("PIPE_PATTERN") / Reduce(pipeline_stage: "line_filters")
   State 16: Shift("PIPE_MATCH") / Reduce(pipeline_stage: "line_filters")

Stategraph:
0:  [^ -> . root, {'$'}]
    'OPEN_BRACE' -> 1
    'OPEN_PARENTHESIS' -> 2
    log_expr -> 3
    expr -> 4
    selector -> 5
    root -> 6
1:  [selector -> 'OPEN_BRACE' . matchers 'CLOSE_BRACE', {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
    [selector -> 'OPEN_BRACE' . 'CLOSE_BRACE', {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
    matchers -> 7
    'CLOSE_BRACE' -> 8
    matcher -> 9
    'IDENTIFIER' -> 10
2:  [log_expr -> 'OPEN_PARENTHESIS' . log_expr 'CLOSE_PARENTHESIS', {'CLOSE_PARENTHESIS', '$'}]
    'OPEN_BRACE' -> 1
    'OPEN_PARENTHESIS' -> 2
    selector -> 5
    log_expr -> 11
3:  [expr -> log_expr ., {'$'}]
4:  [root -> expr ., {'$'}]
5:  [log_expr -> selector ., {'CLOSE_PARENTHESIS', '$'}]
    [log_expr -> selector . pipeline_expr, {'CLOSE_PARENTHESIS', '$'}]
    'PIPE_PATTERN' -> 12
    'PIPE_EXACT' -> 13
    'NEQ' -> 14
    'NRE' -> 15
    line_filters -> 16
    line_filter -> 17
    pipeline_expr -> 18
    pipeline_stage -> 19
    filter -> 20
    'PIPE_MATCH' -> 21
    'NPA' -> 22
6:  [^ -> root ., {'$'}]
7:  [matchers -> matchers . 'COMMA' matcher, {'CLOSE_BRACE', 'COMMA'}]
    [selector -> 'OPEN_BRACE' matchers . 'CLOSE_BRACE', {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
    'COMMA' -> 23
    'CLOSE_BRACE' -> 24
8:  [selector -> 'OPEN_BRACE' 'CLOSE_BRACE' ., {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
9:  [matchers -> matcher ., {'CLOSE_BRACE', 'COMMA'}]
10: [matcher -> 'IDENTIFIER' . 'NRE' 'STRING', {'CLOSE_BRACE', 'COMMA'}]
    [matcher -> 'IDENTIFIER' . 'EQ' 'STRING', {'CLOSE_BRACE', 'COMMA'}]
    [matcher -> 'IDENTIFIER' . 'NEQ' 'STRING', {'CLOSE_BRACE', 'COMMA'}]
    [matcher -> 'IDENTIFIER' . 'RE' 'STRING', {'CLOSE_BRACE', 'COMMA'}]
    'NRE' -> 25
    'EQ' -> 26
    'NEQ' -> 27
    'RE' -> 28
11: [log_expr -> 'OPEN_PARENTHESIS' log_expr . 'CLOSE_PARENTHESIS', {'CLOSE_PARENTHESIS', '$'}]
    'CLOSE_PARENTHESIS' -> 29
12: [filter -> 'PIPE_PATTERN' ., {'STRING'}]
13: [filter -> 'PIPE_EXACT' ., {'STRING'}]
14: [filter -> 'NEQ' ., {'STRING'}]
15: [filter -> 'NRE' ., {'STRING'}]
16: [line_filters -> line_filters . line_filter, {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
    [pipeline_stage -> line_filters ., {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
    'PIPE_PATTERN' -> 12
    'PIPE_EXACT' -> 13
    'NEQ' -> 14
    'NRE' -> 15
    filter -> 20
    'PIPE_MATCH' -> 21
    'NPA' -> 22
    line_filter -> 30
17: [line_filters -> line_filter ., {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
18: [log_expr -> selector pipeline_expr ., {'CLOSE_PARENTHESIS', '$'}]
    [pipeline_expr -> pipeline_expr . pipeline_stage, {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
    'PIPE_PATTERN' -> 12
    'PIPE_EXACT' -> 13
    'NEQ' -> 14
    'NRE' -> 15
    line_filters -> 16
    line_filter -> 17
    filter -> 20
    'PIPE_MATCH' -> 21
    'NPA' -> 22
    pipeline_stage -> 31
19: [pipeline_expr -> pipeline_stage ., {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
20: [line_filter -> filter . 'STRING', {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
    'STRING' -> 32
21: [filter -> 'PIPE_MATCH' ., {'STRING'}]
22: [filter -> 'NPA' ., {'STRING'}]
23: [matchers -> matchers 'COMMA' . matcher, {'CLOSE_BRACE', 'COMMA'}]
    'IDENTIFIER' -> 10
    matcher -> 33
24: [selector -> 'OPEN_BRACE' matchers 'CLOSE_BRACE' ., {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
25: [matcher -> 'IDENTIFIER' 'NRE' . 'STRING', {'CLOSE_BRACE', 'COMMA'}]
    'STRING' -> 34
26: [matcher -> 'IDENTIFIER' 'EQ' . 'STRING', {'CLOSE_BRACE', 'COMMA'}]
    'STRING' -> 35
27: [matcher -> 'IDENTIFIER' 'NEQ' . 'STRING', {'CLOSE_BRACE', 'COMMA'}]
    'STRING' -> 36
28: [matcher -> 'IDENTIFIER' 'RE' . 'STRING', {'CLOSE_BRACE', 'COMMA'}]
    'STRING' -> 37
29: [log_expr -> 'OPEN_PARENTHESIS' log_expr 'CLOSE_PARENTHESIS' ., {'CLOSE_PARENTHESIS', '$'}]
30: [line_filters -> line_filters line_filter ., {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
31: [pipeline_expr -> pipeline_expr pipeline_stage ., {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
32: [line_filter -> filter 'STRING' ., {'CLOSE_PARENTHESIS', 'NEQ', 'NRE', 'PIPE_MATCH', 'PIPE_EXACT', 'PIPE_PATTERN', 'NPA', '$'}]
33: [matchers -> matchers 'COMMA' matcher ., {'CLOSE_BRACE', 'COMMA'}]
34: [matcher -> 'IDENTIFIER' 'NRE' 'STRING' ., {'CLOSE_BRACE', 'COMMA'}]
35: [matcher -> 'IDENTIFIER' 'EQ' 'STRING' ., {'CLOSE_BRACE', 'COMMA'}]
36: [matcher -> 'IDENTIFIER' 'NEQ' 'STRING' ., {'CLOSE_BRACE', 'COMMA'}]
37: [matcher -> 'IDENTIFIER' 'RE' 'STRING' ., {'CLOSE_BRACE', 'COMMA'}]

Shift/Reduce conflict, can shift 'NEQ' or reduce 'pipeline_stage' at src/syntax/syntax_debug.y:77:1
51|     | "IDENTIFIER" "NEQ" "STRING" {
                        ^^^ Shift
77| pipeline_stage -> Result<StageExpr, ()>:
    ++++++++++++++ Reduced rule
78|       line_filters { Ok(StageExpr::LineFilter($1?)) }
          ------------ Reduced productions

Shift/Reduce conflict, can shift 'NPA' or reduce 'pipeline_stage' at src/syntax/syntax_debug.y:77:1
118|     | "NPA" {
            ^^^ Shift
77| pipeline_stage -> Result<StageExpr, ()>:
    ++++++++++++++ Reduced rule
78|       line_filters { Ok(StageExpr::LineFilter($1?)) }
          ------------ Reduced productions

Shift/Reduce conflict, can shift 'PIPE_EXACT' or reduce 'pipeline_stage' at src/syntax/syntax_debug.y:77:1
106|     | "PIPE_EXACT" {
            ^^^^^^^^^^ Shift
77| pipeline_stage -> Result<StageExpr, ()>:
    ++++++++++++++ Reduced rule
78|       line_filters { Ok(StageExpr::LineFilter($1?)) }
          ------------ Reduced productions

Shift/Reduce conflict, can shift 'NRE' or reduce 'pipeline_stage' at src/syntax/syntax_debug.y:77:1
61|     | "IDENTIFIER" "NRE" "STRING" {
                        ^^^ Shift
77| pipeline_stage -> Result<StageExpr, ()>:
    ++++++++++++++ Reduced rule
78|       line_filters { Ok(StageExpr::LineFilter($1?)) }
          ------------ Reduced productions

Shift/Reduce conflict, can shift 'PIPE_PATTERN' or reduce 'pipeline_stage' at src/syntax/syntax_debug.y:77:1
109|     | "PIPE_PATTERN" {
            ^^^^^^^^^^^^ Shift
77| pipeline_stage -> Result<StageExpr, ()>:
    ++++++++++++++ Reduced rule
78|       line_filters { Ok(StageExpr::LineFilter($1?)) }
          ------------ Reduced productions

Shift/Reduce conflict, can shift 'PIPE_MATCH' or reduce 'pipeline_stage' at src/syntax/syntax_debug.y:77:1
103|     "PIPE_MATCH" {
          ^^^^^^^^^^ Shift
77| pipeline_stage -> Result<StageExpr, ()>:
    ++++++++++++++ Reduced rule
78|       line_filters { Ok(StageExpr::LineFilter($1?)) }
          ------------ Reduced productions

The error contains this message.

Shift/Reduce conflict, can shift 'NEQ' or reduce 'pipeline_stage' at src/syntax/syntax_debug.y:77:1
51|     | "IDENTIFIER" "NEQ" "STRING" {
                        ^^^ Shift
77| pipeline_stage -> Result<StageExpr, ()>:
    ++++++++++++++ Reduced rule
78|       line_filters { Ok(StageExpr::LineFilter($1?)) }
          ------------ Reduced productions

I'm not sure if it's a misunderstanding on my part or something else, but based on the syntax definition, this shift/reduce error should stem from queries like {app=“abc”} != "x". The preceding part {app="abc"} might be treated as a selector reducing to log_expr, or it might continue reading NEQ to match the selector pipeline_expr. This seems unrelated to “IDENTIFIER” “NEQ” “STRING”. Yet the error indicates it's related.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions