<commit_before>// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

%{
/*
emtail is a metric exporting, modular tail.

This file describes a parser for the emtail language.
*/
package main

import (
    "io"
    "fmt"
    "regexp"
)

%}


%union
{
    text string
    n node
}


%type <n> stmt_list stmt cond expr_list opt_expr_list
%type <n> expr primary_expr additive_expr postfix_expr

// Tokens and types are defined here.
// Invalid input
%token <text> INVALID
// Builtins
%token <text> BUILTIN
// Literals: re2 syntax regular expression, quoted strings, regex capture group
// references, and identifiers
%token <text> REGEX
%token <text> STRING
%token <text> CAPREF
%token <text> ID
// Punctuation
%token LCURLY RCURLY LPAREN RPAREN LSQUARE RSQUARE
%token COMMA
%token MINUS PLUS


%start start
%%

start
  : stmt_list
  {
      $1.(*stmtlistNode).s = Emtaillex.(*parser).s
      Emtaillex.(*parser).endScope()
      Emtaillex.(*parser).root = $1
  }
  ;

stmt_list
  : /* empty */
  {
      $$ = &stmtlistNode{}
      Emtaillex.(*parser).startScope()
  }
  | stmt_list stmt
  {
      $$ = $1
      $$.(*stmtlistNode).children = append($$.(*stmtlistNode).children, $2)
  }
  ;

stmt
  : cond LCURLY stmt_list RCURLY
  {
      $3.(*stmtlistNode).s = Emtaillex.(*parser).s
      Emtaillex.(*parser).endScope()
      if $1 != nil {
          $$ = &condNode{$1, []node{$3}}
      } else {
          $$ = $3
      }
  }
  | BUILTIN LPAREN opt_expr_list RPAREN
  {
    $$ = &builtinNode{$1, *$3.(*exprlistNode)}
  }
  ;

opt_expr_list
  : /* empty */
  {
      $$ = &exprlistNode{}
  }
  | expr_list
  {
      $$ = $1
  }
  ;

expr_list
  : expr_list COMMA expr
  {
      $$ = $1
      $$.(*exprlistNode).children = append($$.(*exprlistNode).children, $3)
  }
  | expr
  {
      $$ = &exprlistNode{[]node{$1}}
  }
  ;

primary_expr
  : ID
  {
      $$ = idNode{$1}
  }
  | CAPREF
  {
      if index, ok := Emtaillex.(*parser).s.lookupSym($1); ok {
          $$ = &caprefNode{$1, index}
      } else {
          Emtaillex.Error(fmt.Sprintf("Capture group $%s not defined by prior regular expression in " +
                                      "this or an outer scope",  $1))
          // TODO(jaq) force a parse error
      }
  }
  | STRING
  {
      $$ = &stringNode{$1}
  }
  ;

additive_expr
  : additive_expr PLUS primary_expr
  {
    $$ = nil
  }
  | additive_expr MINUS primary_expr
  {
    $$ = nil
  }
  ;

postfix_expr
  : primary_expr
  {
    $$ = $1
  }
  | postfix_expr LSQUARE expr RSQUARE
  {
    $$ = nil
  }
  ; 

expr
  : additive_expr
  {
     $$ = $1
  }
  ;

cond
  : /* empty */
  {
      /* Emtaillex.(*parser).startScope() */
      $$ = nil
  }
  | REGEX
  {
      /* Emtaillex.(*parser).startScope() */
      if re, err := regexp.Compile($1); err != nil {
          Emtaillex.(*parser).Error(fmt.Sprintf(err.Error()))
          // TODO(jaq): force a parse error
      } else {
          // We can reserve storage for these capturing groups, storing them in
          // the current scope, so that future CAPTUREGROUPs can retrieve their
          // value.  At parse time, we can warn about nonexistent names.
          for i := 1; i < re.NumSubexp() + 1; i++ {
              Emtaillex.(*parser).s.addSym(fmt.Sprintf("%d", i), i)
          }
          for i, capref := range re.SubexpNames() {
                if capref != "" {
                  Emtaillex.(*parser).s.addSym(capref, i)
              }
          }
          // TODO(jaq): when supported add named capturing groups<commit_msg>Make parser build with latest goyacc.<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

%{
/*
emtail is a metric exporting, modular tail.

This file describes a parser for the emtail language.
*/
package main

import (
    "io"
    "fmt"
    "regexp"
)

%}


%union
{
    text string
    n node
}


%type <n> stmt_list stmt cond expr_list opt_expr_list
%type <n> expr primary_expr additive_expr postfix_expr

// Tokens and types are defined here.
// Invalid input
%token <text> INVALID
// Builtins
%token <text> BUILTIN
// Literals: re2 syntax regular expression, quoted strings, regex capture group
// references, and identifiers
%token <text> REGEX
%token <text> STRING
%token <text> CAPREF
%token <text> ID
// Punctuation
%token LCURLY RCURLY LPAREN RPAREN LSQUARE RSQUARE
%token COMMA
%token MINUS PLUS


%start start
%%

start
  : stmt_list
  {
      $1.(*stmtlistNode).s = Emtaillex.(*parser).s
      Emtaillex.(*parser).endScope()
      Emtaillex.(*parser).root = $1
  }
  ;

stmt_list
  : /* empty */
  {
      $$ = &stmtlistNode{}
      Emtaillex.(*parser).startScope()
  }
  | stmt_list stmt
  {
      $$ = $1
      $$.(*stmtlistNode).children = append($$.(*stmtlistNode).children, $2)
  }
  ;

stmt
  : cond LCURLY stmt_list RCURLY
  {
      $3.(*stmtlistNode).s = Emtaillex.(*parser).s
      Emtaillex.(*parser).endScope()
      if $1 != nil {
          $$ = &condNode{$1, []node{$3}}
      } else {
          $$ = $3
      }
  }
  | BUILTIN LPAREN opt_expr_list RPAREN
  {
    $$ = &builtinNode{$1, *$3.(*exprlistNode)}
  }
  ;

opt_expr_list
  : /* empty */
  {
      $$ = &exprlistNode{}
  }
  | expr_list
  {
      $$ = $1
  }
  ;

expr_list
  : expr_list COMMA expr
  {
      $$ = $1
      $$.(*exprlistNode).children = append($$.(*exprlistNode).children, $3)
  }
  | expr
  {
      $$ = &exprlistNode{[]node{$1}}
  }
  ;

expr
  : additive_expr
  {
     $$ = $1
  }
  ;

additive_expr
  : postfix_expr
  {
    $$ = $1
  }
  | additive_expr PLUS postfix_expr
  {
    $$ = $1
  }
  | additive_expr MINUS postfix_expr
  {
    $$ = $1
  }
  ;

postfix_expr
  : primary_expr
  {
    $$ = $1
  }
  | postfix_expr LSQUARE expr RSQUARE
  {
    $$ = $1
  }
  ; 

primary_expr
  : ID
  {
      $$ = idNode{$1}
  }
  | CAPREF
  {
      if index, ok := Emtaillex.(*parser).s.lookupSym($1); ok {
          $$ = &caprefNode{$1, index}
      } else {
          Emtaillex.Error(fmt.Sprintf("Capture group $%s not defined by prior regular expression in " +
                                      "this or an outer scope",  $1))
          // TODO(jaq) force a parse error
      }
  }
  | STRING
  {
      $$ = &stringNode{$1}
  }
  | LPAREN expr RPAREN
  {
      $$ = $2
  }
  ;


cond
  : /* empty */
  {
      /* Emtaillex.(*parser).startScope() */
      $$ = nil
  }
  | REGEX
  {
      /* Emtaillex.(*parser).startScope() */
      if re, err := regexp.Compile($1); err != nil {
          Emtaillex.(*parser).Error(fmt.Sprintf(err.Error()))
          // TODO(jaq): force a parse error
      } else {
          // We can reserve storage for these capturing groups, storing them in
          // the current scope, so that future CAPTUREGROUPs can retrieve their
          // value.  At parse time, we can warn about nonexistent names.
          for i := 1; i < re.NumSubexp() + 1; i++ {
              Emtaillex.(*parser).s.addSym(fmt.Sprintf("%d", i), i)
          }
          for i, capref := range re.SubexpNames() {
                if capref != "" {
                  Emtaillex.(*parser).s.addSym(capref, i)
              }
          }
          // TODO(jaq): when supported add named capturing groups
{'fraction_non_alphanumeric': 0.14534401768444322, 'fraction_numerical': 0.008980381320806852, 'mean_word_length': 2.03904282115869, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6549220', 'n_tokens_mistral': 2660, 'n_tokens_neox': 2575, 'n_words': 600}