diff options
| author | Pascal Rigaux <pixel@mandriva.com> | 2003-04-13 10:33:18 +0000 | 
|---|---|---|
| committer | Pascal Rigaux <pixel@mandriva.com> | 2003-04-13 10:33:18 +0000 | 
| commit | f773f4ce3a5f6e5101e0d1483e53001391d18eb4 (patch) | |
| tree | ae403f4e3d8eb774cec30d0f9f3a3e8abe3696d7 | |
| parent | 74be597e2d920f8025d104c4e45e9de03c83062f (diff) | |
| download | perl_checker-f773f4ce3a5f6e5101e0d1483e53001391d18eb4.tar perl_checker-f773f4ce3a5f6e5101e0d1483e53001391d18eb4.tar.gz perl_checker-f773f4ce3a5f6e5101e0d1483e53001391d18eb4.tar.bz2 perl_checker-f773f4ce3a5f6e5101e0d1483e53001391d18eb4.tar.xz perl_checker-f773f4ce3a5f6e5101e0d1483e53001391d18eb4.zip  | |
use new types to have stricter type checking (prior to adding maybe_context)
| -rw-r--r-- | perl_checker.src/lexer.mll | 200 | ||||
| -rw-r--r-- | perl_checker.src/parser.mly | 557 | ||||
| -rw-r--r-- | perl_checker.src/parser_helper.ml | 338 | ||||
| -rw-r--r-- | perl_checker.src/parser_helper.mli | 163 | ||||
| -rw-r--r-- | perl_checker.src/types.mli | 16 | 
5 files changed, 662 insertions, 612 deletions
diff --git a/perl_checker.src/lexer.mll b/perl_checker.src/lexer.mll index d011ef1..47e0f7a 100644 --- a/perl_checker.src/lexer.mll +++ b/perl_checker.src/lexer.mll @@ -53,6 +53,8 @@ type raw_token =  and raw_interpolated_string = (string * raw_token list) list +let new_any any spaces pos = { any = any ; spaces = spaces ; pos = pos } +  let rec concat_bareword_paren accu = function    | PRINT(s, pos1) :: PAREN(pos2) :: l    | BAREWORD(s, pos1) :: PAREN(pos2) :: l -> @@ -63,105 +65,105 @@ let rec concat_bareword_paren accu = function    | e :: l -> concat_bareword_paren (e :: accu) l  let rec raw_token_to_pos_and_token spaces = function -  | NUM(s, pos) -> pos, Parser.NUM(s, (spaces, pos)) -  | RAW_STRING(s, pos) -> pos, Parser.RAW_STRING(s, (spaces, pos)) -  | RAW_HERE_DOC(r, pos) -> pos, Parser.RAW_HERE_DOC(!r, (spaces, pos)) -  | STRING(l, pos) -> pos, Parser.STRING(raw_interpolated_string_to_tokens l, (spaces, pos)) -  | COMMAND_STRING(l, pos) -> pos, Parser.COMMAND_STRING(raw_interpolated_string_to_tokens l, (spaces, pos)) -  | QR_PATTERN(s, opts, pos) -> pos, Parser.QR_PATTERN((raw_interpolated_string_to_tokens s, opts), (spaces, pos)) -  | PATTERN(s, opts, pos) -> pos, Parser.PATTERN((raw_interpolated_string_to_tokens s, opts), (spaces, pos)) -  | PATTERN_SUBST(from, to_, opts, pos) -> pos, Parser.PATTERN_SUBST((raw_interpolated_string_to_tokens from, raw_interpolated_string_to_tokens to_, opts), (spaces, pos)) -  | HERE_DOC(l, pos) -> pos, Parser.HERE_DOC((raw_interpolated_string_to_tokens (fst !l), snd !l), (spaces, pos)) -  | BAREWORD(s, pos) -> pos, Parser.BAREWORD(s, (spaces, pos)) -  | BAREWORD_PAREN(s, pos) -> pos, Parser.BAREWORD_PAREN(s, (spaces, pos)) -  | REVISION(s, pos) -> pos, Parser.REVISION(s, (spaces, pos)) -  | PERL_CHECKER_COMMENT(s, pos) -> pos, Parser.PERL_CHECKER_COMMENT(s, (spaces, pos)) -  | PO_COMMENT(s, pos) -> pos, Parser.PO_COMMENT(s, (spaces, pos)) -  | POD(s, pos) -> pos, Parser.POD(s, (spaces, pos)) -  | LABEL(s, pos) -> pos, Parser.LABEL(s, (spaces, pos)) -  | PRINT(s, pos) -> pos, Parser.PRINT(s, (spaces, pos)) -  | PRINT_TO_STAR(s, pos) -> pos, Parser.PRINT_TO_STAR(s, (spaces, pos)) -  | PRINT_TO_SCALAR(s, pos) -> pos, Parser.PRINT_TO_SCALAR(s, (spaces, pos)) -  | QUOTEWORDS(s, pos) -> pos, Parser.QUOTEWORDS(s, (spaces, pos)) -  | COMPACT_HASH_SUBSCRIPT(s, pos) -> pos, Parser.COMPACT_HASH_SUBSCRIPT(s, (spaces, pos)) -  | SCALAR_IDENT(kind, name, pos) -> pos, Parser.SCALAR_IDENT((kind, name), (spaces, pos)) -  | ARRAY_IDENT(kind, name, pos) -> pos, Parser.ARRAY_IDENT((kind, name), (spaces, pos)) -  | HASH_IDENT(kind, name, pos) -> pos, Parser.HASH_IDENT((kind, name), (spaces, pos)) -  | FUNC_IDENT(kind, name, pos) -> pos, Parser.FUNC_IDENT((kind, name), (spaces, pos)) -  | STAR_IDENT(kind, name, pos) -> pos, Parser.STAR_IDENT((kind, name), (spaces, pos)) -  | RAW_IDENT(kind, name, pos) -> pos, Parser.RAW_IDENT((kind, name), (spaces, pos)) -  | RAW_IDENT_PAREN(kind, name, pos) -> pos, Parser.RAW_IDENT_PAREN((kind, name), (spaces, pos)) -  | ARRAYLEN_IDENT(kind, name, pos) -> pos, Parser.ARRAYLEN_IDENT((kind, name), (spaces, pos)) -  | FUNC_DECL_WITH_PROTO(name, proto, pos) -> pos, Parser.FUNC_DECL_WITH_PROTO((name, proto), (spaces, pos)) - -  | NEW(pos) -> pos, Parser.NEW((), (spaces, pos)) -  | FORMAT(pos) -> pos, Parser.FORMAT((), (spaces, pos)) -  | COMPARE_OP(s, pos) -> pos, Parser.COMPARE_OP(s, (spaces, pos)) -  | EQ_OP(s, pos) -> pos, Parser.EQ_OP(s, (spaces, pos)) -  | ASSIGN(s, pos) -> pos, Parser.ASSIGN(s, (spaces, pos)) -  | FOR(s, pos) -> pos, Parser.FOR(s, (spaces, pos)) - -  | DOTDOT(s, pos) -> pos, Parser.DOTDOT(s, (spaces, pos)) -  | MULT(s, pos) -> pos, Parser.MULT(s, (spaces, pos)) -  | BIT_SHIFT(s, pos) -> pos, Parser.BIT_SHIFT(s, (spaces, pos)) -  | PLUS(s, pos) -> pos, Parser.PLUS(s, (spaces, pos)) -  | ONE_SCALAR_PARA(s, pos) -> pos, Parser.ONE_SCALAR_PARA(s, (spaces, pos)) -  | MY_OUR(s, pos) -> pos, Parser.MY_OUR(s, (spaces, pos)) - -  | EOF              (pos) -> pos, Parser.EOF              ((), (spaces, pos)) -  | IF               (pos) -> pos, Parser.IF               ((), (spaces, pos)) -  | ELSIF            (pos) -> pos, Parser.ELSIF            ((), (spaces, pos)) -  | ELSE             (pos) -> pos, Parser.ELSE             ((), (spaces, pos)) -  | UNLESS           (pos) -> pos, Parser.UNLESS           ((), (spaces, pos)) -  | DO               (pos) -> pos, Parser.DO               ((), (spaces, pos)) -  | WHILE            (pos) -> pos, Parser.WHILE            ((), (spaces, pos)) -  | UNTIL            (pos) -> pos, Parser.UNTIL            ((), (spaces, pos)) -  | CONTINUE         (pos) -> pos, Parser.CONTINUE         ((), (spaces, pos)) -  | SUB              (pos) -> pos, Parser.SUB              ((), (spaces, pos)) -  | LOCAL            (pos) -> pos, Parser.LOCAL            ((), (spaces, pos)) -  | USE              (pos) -> pos, Parser.USE              ((), (spaces, pos)) -  | PACKAGE          (pos) -> pos, Parser.PACKAGE          ((), (spaces, pos)) -  | BEGIN            (pos) -> pos, Parser.BEGIN            ((), (spaces, pos)) -  | END              (pos) -> pos, Parser.END              ((), (spaces, pos)) -  | AT               (pos) -> pos, Parser.AT               ((), (spaces, pos)) -  | DOLLAR           (pos) -> pos, Parser.DOLLAR           ((), (spaces, pos)) -  | PERCENT          (pos) -> pos, Parser.PERCENT          ((), (spaces, pos)) -  | AMPERSAND        (pos) -> pos, Parser.AMPERSAND        ((), (spaces, pos)) -  | STAR             (pos) -> pos, Parser.STAR             ((), (spaces, pos)) -  | ARRAYLEN         (pos) -> pos, Parser.ARRAYLEN         ((), (spaces, pos)) -  | SEMI_COLON       (pos) -> pos, Parser.SEMI_COLON       ((), (spaces, pos)) -  | PKG_SCOPE        (pos) -> pos, Parser.PKG_SCOPE        ((), (spaces, pos)) -  | PAREN            (pos) -> pos, Parser.PAREN            ((), (spaces, pos)) -  | PAREN_END        (pos) -> pos, Parser.PAREN_END        ((), (spaces, pos)) -  | BRACKET          (pos) -> pos, Parser.BRACKET          ((), (spaces, pos)) -  | BRACKET_END      (pos) -> pos, Parser.BRACKET_END      ((), (spaces, pos)) -  | BRACKET_HASHREF  (pos) -> pos, Parser.BRACKET_HASHREF  ((), (spaces, pos)) -  | ARRAYREF         (pos) -> pos, Parser.ARRAYREF         ((), (spaces, pos)) -  | ARRAYREF_END     (pos) -> pos, Parser.ARRAYREF_END     ((), (spaces, pos)) -  | ARROW            (pos) -> pos, Parser.ARROW            ((), (spaces, pos)) -  | INCR             (pos) -> pos, Parser.INCR             ((), (spaces, pos)) -  | DECR             (pos) -> pos, Parser.DECR             ((), (spaces, pos)) -  | POWER            (pos) -> pos, Parser.POWER            ((), (spaces, pos)) -  | TIGHT_NOT        (pos) -> pos, Parser.TIGHT_NOT        ((), (spaces, pos)) -  | BIT_NEG          (pos) -> pos, Parser.BIT_NEG          ((), (spaces, pos)) -  | REF              (pos) -> pos, Parser.REF              ((), (spaces, pos)) -  | PATTERN_MATCH    (pos) -> pos, Parser.PATTERN_MATCH    ((), (spaces, pos)) -  | PATTERN_MATCH_NOT(pos) -> pos, Parser.PATTERN_MATCH_NOT((), (spaces, pos)) -  | LT               (pos) -> pos, Parser.LT               ((), (spaces, pos)) -  | GT               (pos) -> pos, Parser.GT               ((), (spaces, pos)) -  | BIT_AND          (pos) -> pos, Parser.BIT_AND          ((), (spaces, pos)) -  | BIT_OR           (pos) -> pos, Parser.BIT_OR           ((), (spaces, pos)) -  | BIT_XOR          (pos) -> pos, Parser.BIT_XOR          ((), (spaces, pos)) -  | AND_TIGHT        (pos) -> pos, Parser.AND_TIGHT        ((), (spaces, pos)) -  | OR_TIGHT         (pos) -> pos, Parser.OR_TIGHT         ((), (spaces, pos)) -  | QUESTION_MARK    (pos) -> pos, Parser.QUESTION_MARK    ((), (spaces, pos)) -  | COLON            (pos) -> pos, Parser.COLON            ((), (spaces, pos)) -  | COMMA            (pos) -> pos, Parser.COMMA            ((), (spaces, pos)) -  | RIGHT_ARROW      (pos) -> pos, Parser.RIGHT_ARROW      ((), (spaces, pos)) -  | NOT              (pos) -> pos, Parser.NOT              ((), (spaces, pos)) -  | AND              (pos) -> pos, Parser.AND              ((), (spaces, pos)) -  | OR               (pos) -> pos, Parser.OR               ((), (spaces, pos)) -  | XOR              (pos) -> pos, Parser.XOR              ((), (spaces, pos)) +  | NUM(s, pos) -> pos, Parser.NUM(new_any s spaces pos) +  | RAW_STRING(s, pos) -> pos, Parser.RAW_STRING(new_any s spaces pos) +  | RAW_HERE_DOC(r, pos) -> pos, Parser.RAW_HERE_DOC(new_any !r spaces pos) +  | STRING(l, pos) -> pos, Parser.STRING(new_any (raw_interpolated_string_to_tokens l) spaces pos) +  | COMMAND_STRING(l, pos) -> pos, Parser.COMMAND_STRING(new_any (raw_interpolated_string_to_tokens l) spaces pos) +  | QR_PATTERN(s, opts, pos) -> pos, Parser.QR_PATTERN(new_any (raw_interpolated_string_to_tokens s, opts) spaces pos) +  | PATTERN(s, opts, pos) -> pos, Parser.PATTERN(new_any (raw_interpolated_string_to_tokens s, opts) spaces pos) +  | PATTERN_SUBST(from, to_, opts, pos) -> pos, Parser.PATTERN_SUBST(new_any (raw_interpolated_string_to_tokens from, raw_interpolated_string_to_tokens to_, opts) spaces pos) +  | HERE_DOC(l, pos) -> pos, Parser.HERE_DOC(new_any (raw_interpolated_string_to_tokens (fst !l), snd !l) spaces pos) +  | BAREWORD(s, pos) -> pos, Parser.BAREWORD(new_any s spaces pos) +  | BAREWORD_PAREN(s, pos) -> pos, Parser.BAREWORD_PAREN(new_any s spaces pos) +  | REVISION(s, pos) -> pos, Parser.REVISION(new_any s spaces pos) +  | PERL_CHECKER_COMMENT(s, pos) -> pos, Parser.PERL_CHECKER_COMMENT(new_any s spaces pos) +  | PO_COMMENT(s, pos) -> pos, Parser.PO_COMMENT(new_any s spaces pos) +  | POD(s, pos) -> pos, Parser.POD(new_any s spaces pos) +  | LABEL(s, pos) -> pos, Parser.LABEL(new_any s spaces pos) +  | PRINT(s, pos) -> pos, Parser.PRINT(new_any s spaces pos) +  | PRINT_TO_STAR(s, pos) -> pos, Parser.PRINT_TO_STAR(new_any s spaces pos) +  | PRINT_TO_SCALAR(s, pos) -> pos, Parser.PRINT_TO_SCALAR(new_any s spaces pos) +  | QUOTEWORDS(s, pos) -> pos, Parser.QUOTEWORDS(new_any s spaces pos) +  | COMPACT_HASH_SUBSCRIPT(s, pos) -> pos, Parser.COMPACT_HASH_SUBSCRIPT(new_any s spaces pos) +  | SCALAR_IDENT(kind, name, pos) -> pos, Parser.SCALAR_IDENT(new_any (kind, name) spaces pos) +  | ARRAY_IDENT(kind, name, pos) -> pos, Parser.ARRAY_IDENT(new_any (kind, name) spaces pos) +  | HASH_IDENT(kind, name, pos) -> pos, Parser.HASH_IDENT(new_any (kind, name) spaces pos) +  | FUNC_IDENT(kind, name, pos) -> pos, Parser.FUNC_IDENT(new_any (kind, name) spaces pos) +  | STAR_IDENT(kind, name, pos) -> pos, Parser.STAR_IDENT(new_any (kind, name) spaces pos) +  | RAW_IDENT(kind, name, pos) -> pos, Parser.RAW_IDENT(new_any (kind, name) spaces pos) +  | RAW_IDENT_PAREN(kind, name, pos) -> pos, Parser.RAW_IDENT_PAREN(new_any (kind, name) spaces pos) +  | ARRAYLEN_IDENT(kind, name, pos) -> pos, Parser.ARRAYLEN_IDENT(new_any (kind, name) spaces pos) +  | FUNC_DECL_WITH_PROTO(name, proto, pos) -> pos, Parser.FUNC_DECL_WITH_PROTO(new_any (name, proto) spaces pos) + +  | NEW(pos) -> pos, Parser.NEW(new_any () spaces pos) +  | FORMAT(pos) -> pos, Parser.FORMAT(new_any () spaces pos) +  | COMPARE_OP(s, pos) -> pos, Parser.COMPARE_OP(new_any s spaces pos) +  | EQ_OP(s, pos) -> pos, Parser.EQ_OP(new_any s spaces pos) +  | ASSIGN(s, pos) -> pos, Parser.ASSIGN(new_any s spaces pos) +  | FOR(s, pos) -> pos, Parser.FOR(new_any s spaces pos) + +  | DOTDOT(s, pos) -> pos, Parser.DOTDOT(new_any s spaces pos) +  | MULT(s, pos) -> pos, Parser.MULT(new_any s spaces pos) +  | BIT_SHIFT(s, pos) -> pos, Parser.BIT_SHIFT(new_any s spaces pos) +  | PLUS(s, pos) -> pos, Parser.PLUS(new_any s spaces pos) +  | ONE_SCALAR_PARA(s, pos) -> pos, Parser.ONE_SCALAR_PARA(new_any s spaces pos) +  | MY_OUR(s, pos) -> pos, Parser.MY_OUR(new_any s spaces pos) + +  | EOF              (pos) -> pos, Parser.EOF              (new_any () spaces pos) +  | IF               (pos) -> pos, Parser.IF               (new_any () spaces pos) +  | ELSIF            (pos) -> pos, Parser.ELSIF            (new_any () spaces pos) +  | ELSE             (pos) -> pos, Parser.ELSE             (new_any () spaces pos) +  | UNLESS           (pos) -> pos, Parser.UNLESS           (new_any () spaces pos) +  | DO               (pos) -> pos, Parser.DO               (new_any () spaces pos) +  | WHILE            (pos) -> pos, Parser.WHILE            (new_any () spaces pos) +  | UNTIL            (pos) -> pos, Parser.UNTIL            (new_any () spaces pos) +  | CONTINUE         (pos) -> pos, Parser.CONTINUE         (new_any () spaces pos) +  | SUB              (pos) -> pos, Parser.SUB              (new_any () spaces pos) +  | LOCAL            (pos) -> pos, Parser.LOCAL            (new_any () spaces pos) +  | USE              (pos) -> pos, Parser.USE              (new_any () spaces pos) +  | PACKAGE          (pos) -> pos, Parser.PACKAGE          (new_any () spaces pos) +  | BEGIN            (pos) -> pos, Parser.BEGIN            (new_any () spaces pos) +  | END              (pos) -> pos, Parser.END              (new_any () spaces pos) +  | AT               (pos) -> pos, Parser.AT               (new_any () spaces pos) +  | DOLLAR           (pos) -> pos, Parser.DOLLAR           (new_any () spaces pos) +  | PERCENT          (pos) -> pos, Parser.PERCENT          (new_any () spaces pos) +  | AMPERSAND        (pos) -> pos, Parser.AMPERSAND        (new_any () spaces pos) +  | STAR             (pos) -> pos, Parser.STAR             (new_any () spaces pos) +  | ARRAYLEN         (pos) -> pos, Parser.ARRAYLEN         (new_any () spaces pos) +  | SEMI_COLON       (pos) -> pos, Parser.SEMI_COLON       (new_any () spaces pos) +  | PKG_SCOPE        (pos) -> pos, Parser.PKG_SCOPE        (new_any () spaces pos) +  | PAREN            (pos) -> pos, Parser.PAREN            (new_any () spaces pos) +  | PAREN_END        (pos) -> pos, Parser.PAREN_END        (new_any () spaces pos) +  | BRACKET          (pos) -> pos, Parser.BRACKET          (new_any () spaces pos) +  | BRACKET_END      (pos) -> pos, Parser.BRACKET_END      (new_any () spaces pos) +  | BRACKET_HASHREF  (pos) -> pos, Parser.BRACKET_HASHREF  (new_any () spaces pos) +  | ARRAYREF         (pos) -> pos, Parser.ARRAYREF         (new_any () spaces pos) +  | ARRAYREF_END     (pos) -> pos, Parser.ARRAYREF_END     (new_any () spaces pos) +  | ARROW            (pos) -> pos, Parser.ARROW            (new_any () spaces pos) +  | INCR             (pos) -> pos, Parser.INCR             (new_any () spaces pos) +  | DECR             (pos) -> pos, Parser.DECR             (new_any () spaces pos) +  | POWER            (pos) -> pos, Parser.POWER            (new_any () spaces pos) +  | TIGHT_NOT        (pos) -> pos, Parser.TIGHT_NOT        (new_any () spaces pos) +  | BIT_NEG          (pos) -> pos, Parser.BIT_NEG          (new_any () spaces pos) +  | REF              (pos) -> pos, Parser.REF              (new_any () spaces pos) +  | PATTERN_MATCH    (pos) -> pos, Parser.PATTERN_MATCH    (new_any () spaces pos) +  | PATTERN_MATCH_NOT(pos) -> pos, Parser.PATTERN_MATCH_NOT(new_any () spaces pos) +  | LT               (pos) -> pos, Parser.LT               (new_any () spaces pos) +  | GT               (pos) -> pos, Parser.GT               (new_any () spaces pos) +  | BIT_AND          (pos) -> pos, Parser.BIT_AND          (new_any () spaces pos) +  | BIT_OR           (pos) -> pos, Parser.BIT_OR           (new_any () spaces pos) +  | BIT_XOR          (pos) -> pos, Parser.BIT_XOR          (new_any () spaces pos) +  | AND_TIGHT        (pos) -> pos, Parser.AND_TIGHT        (new_any () spaces pos) +  | OR_TIGHT         (pos) -> pos, Parser.OR_TIGHT         (new_any () spaces pos) +  | QUESTION_MARK    (pos) -> pos, Parser.QUESTION_MARK    (new_any () spaces pos) +  | COLON            (pos) -> pos, Parser.COLON            (new_any () spaces pos) +  | COMMA            (pos) -> pos, Parser.COMMA            (new_any () spaces pos) +  | RIGHT_ARROW      (pos) -> pos, Parser.RIGHT_ARROW      (new_any () spaces pos) +  | NOT              (pos) -> pos, Parser.NOT              (new_any () spaces pos) +  | AND              (pos) -> pos, Parser.AND              (new_any () spaces pos) +  | OR               (pos) -> pos, Parser.OR               (new_any () spaces pos) +  | XOR              (pos) -> pos, Parser.XOR              (new_any () spaces pos)    | SPACE _ | CR -> internal_error "raw_token_to_token" diff --git a/perl_checker.src/parser.mly b/perl_checker.src/parser.mly index 4ac58f1..3887e24 100644 --- a/perl_checker.src/parser.mly +++ b/perl_checker.src/parser.mly @@ -11,52 +11,52 @@  %} -%token <unit   * (Types.spaces * Types.raw_pos)> EOF -%token <string * (Types.spaces * Types.raw_pos)> NUM RAW_STRING BAREWORD BAREWORD_PAREN REVISION COMMENT POD LABEL PO_COMMENT PERL_CHECKER_COMMENT ONE_SCALAR_PARA -%token <(string * string) * (Types.spaces * Types.raw_pos)> PRINT_TO_STAR PRINT_TO_SCALAR -%token <string * (Types.spaces * Types.raw_pos)> QUOTEWORDS COMPACT_HASH_SUBSCRIPT -%token <(string * Types.raw_pos) * (Types.spaces * Types.raw_pos)> RAW_HERE_DOC -%token <(string * ((int * int) * token) list) list * (Types.spaces * Types.raw_pos)> STRING COMMAND_STRING -%token <((string * ((int * int) * token) list) list * Types.raw_pos) * (Types.spaces * Types.raw_pos)> HERE_DOC - -%token <((string * ((int * int) * token) list) list * string) * (Types.spaces * Types.raw_pos)> PATTERN QR_PATTERN -%token <((string * ((int * int) * token) list) list * (string * ((int * int) * token) list) list * string) * (Types.spaces * Types.raw_pos)> PATTERN_SUBST - -%token <(string option * string) * (Types.spaces * Types.raw_pos)> SCALAR_IDENT ARRAY_IDENT HASH_IDENT FUNC_IDENT STAR_IDENT RAW_IDENT RAW_IDENT_PAREN ARRAYLEN_IDENT -%token <(string * string) * (Types.spaces * Types.raw_pos)> FUNC_DECL_WITH_PROTO - -%token <string * (Types.spaces * Types.raw_pos)> FOR PRINT -%token <unit   * (Types.spaces * Types.raw_pos)> NEW FORMAT -%token <string * (Types.spaces * Types.raw_pos)> COMPARE_OP EQ_OP -%token <string * (Types.spaces * Types.raw_pos)> ASSIGN MY_OUR - -%token <unit   * (Types.spaces * Types.raw_pos)> IF ELSIF ELSE UNLESS DO WHILE UNTIL CONTINUE SUB LOCAL -%token <unit   * (Types.spaces * Types.raw_pos)> USE PACKAGE BEGIN END -%token <unit   * (Types.spaces * Types.raw_pos)> AT DOLLAR PERCENT AMPERSAND STAR ARRAYLEN -%token <unit   * (Types.spaces * Types.raw_pos)> SEMI_COLON PKG_SCOPE -%token <unit   * (Types.spaces * Types.raw_pos)> PAREN PAREN_END -%token <unit   * (Types.spaces * Types.raw_pos)> BRACKET BRACKET_END BRACKET_HASHREF -%token <unit   * (Types.spaces * Types.raw_pos)> ARRAYREF ARRAYREF_END - -%token <unit   * (Types.spaces * Types.raw_pos)> ARROW -%token <unit   * (Types.spaces * Types.raw_pos)> INCR DECR -%token <unit   * (Types.spaces * Types.raw_pos)> POWER -%token <unit   * (Types.spaces * Types.raw_pos)> TIGHT_NOT BIT_NEG REF -%token <unit   * (Types.spaces * Types.raw_pos)> PATTERN_MATCH PATTERN_MATCH_NOT -%token <string * (Types.spaces * Types.raw_pos)> MULT -%token <string * (Types.spaces * Types.raw_pos)> PLUS -%token <string * (Types.spaces * Types.raw_pos)> BIT_SHIFT -%token <unit   * (Types.spaces * Types.raw_pos)> LT GT -%token <unit   * (Types.spaces * Types.raw_pos)> BIT_AND -%token <unit   * (Types.spaces * Types.raw_pos)> BIT_OR BIT_XOR -%token <unit   * (Types.spaces * Types.raw_pos)> AND_TIGHT -%token <unit   * (Types.spaces * Types.raw_pos)> OR_TIGHT -%token <string * (Types.spaces * Types.raw_pos)> DOTDOT -%token <unit   * (Types.spaces * Types.raw_pos)> QUESTION_MARK COLON -%token <unit   * (Types.spaces * Types.raw_pos)> COMMA RIGHT_ARROW -%token <unit   * (Types.spaces * Types.raw_pos)> NOT -%token <unit   * (Types.spaces * Types.raw_pos)> AND -%token <unit   * (Types.spaces * Types.raw_pos)> OR XOR +%token <unit   Types.any_spaces_pos> EOF +%token <string Types.any_spaces_pos> NUM RAW_STRING BAREWORD BAREWORD_PAREN REVISION COMMENT POD LABEL PO_COMMENT PERL_CHECKER_COMMENT ONE_SCALAR_PARA +%token <(string * string) Types.any_spaces_pos> PRINT_TO_STAR PRINT_TO_SCALAR +%token <string Types.any_spaces_pos> QUOTEWORDS COMPACT_HASH_SUBSCRIPT +%token <(string * Types.raw_pos) Types.any_spaces_pos> RAW_HERE_DOC +%token <(string * ((int * int) * token) list) list Types.any_spaces_pos> STRING COMMAND_STRING +%token <((string * ((int * int) * token) list) list * Types.raw_pos) Types.any_spaces_pos> HERE_DOC + +%token <((string * ((int * int) * token) list) list * string) Types.any_spaces_pos> PATTERN QR_PATTERN +%token <((string * ((int * int) * token) list) list * (string * ((int * int) * token) list) list * string) Types.any_spaces_pos> PATTERN_SUBST + +%token <(string option * string) Types.any_spaces_pos> SCALAR_IDENT ARRAY_IDENT HASH_IDENT FUNC_IDENT STAR_IDENT RAW_IDENT RAW_IDENT_PAREN ARRAYLEN_IDENT +%token <(string * string) Types.any_spaces_pos> FUNC_DECL_WITH_PROTO + +%token <string Types.any_spaces_pos> FOR PRINT +%token <unit   Types.any_spaces_pos> NEW FORMAT +%token <string Types.any_spaces_pos> COMPARE_OP EQ_OP +%token <string Types.any_spaces_pos> ASSIGN MY_OUR + +%token <unit   Types.any_spaces_pos> IF ELSIF ELSE UNLESS DO WHILE UNTIL CONTINUE SUB LOCAL +%token <unit   Types.any_spaces_pos> USE PACKAGE BEGIN END +%token <unit   Types.any_spaces_pos> AT DOLLAR PERCENT AMPERSAND STAR ARRAYLEN +%token <unit   Types.any_spaces_pos> SEMI_COLON PKG_SCOPE +%token <unit   Types.any_spaces_pos> PAREN PAREN_END +%token <unit   Types.any_spaces_pos> BRACKET BRACKET_END BRACKET_HASHREF +%token <unit   Types.any_spaces_pos> ARRAYREF ARRAYREF_END + +%token <unit   Types.any_spaces_pos> ARROW +%token <unit   Types.any_spaces_pos> INCR DECR +%token <unit   Types.any_spaces_pos> POWER +%token <unit   Types.any_spaces_pos> TIGHT_NOT BIT_NEG REF +%token <unit   Types.any_spaces_pos> PATTERN_MATCH PATTERN_MATCH_NOT +%token <string Types.any_spaces_pos> MULT +%token <string Types.any_spaces_pos> PLUS +%token <string Types.any_spaces_pos> BIT_SHIFT +%token <unit   Types.any_spaces_pos> LT GT +%token <unit   Types.any_spaces_pos> BIT_AND +%token <unit   Types.any_spaces_pos> BIT_OR BIT_XOR +%token <unit   Types.any_spaces_pos> AND_TIGHT +%token <unit   Types.any_spaces_pos> OR_TIGHT +%token <string Types.any_spaces_pos> DOTDOT +%token <unit   Types.any_spaces_pos> QUESTION_MARK COLON +%token <unit   Types.any_spaces_pos> COMMA RIGHT_ARROW +%token <unit   Types.any_spaces_pos> NOT +%token <unit   Types.any_spaces_pos> AND +%token <unit   Types.any_spaces_pos> OR XOR  %nonassoc PREC_LOW  %nonassoc LOOPEX @@ -91,86 +91,87 @@  %left ARRAYREF BRACKET  %type <Types.fromparser list> prog -%type <(Types.priority * Types.fromparser) * (Types.spaces * Types.raw_pos)> expr term +%type <prio_expr_spaces_pos> expr term +%type <fromparser any_spaces_pos> scalar bracket_subscript variable restricted_subscripted  %start prog  %% -prog: lines EOF {fst $1} +prog: lines EOF {$1.any}  lines: /* A collection of "lines" in the program */ -| {[], (Space_none, bpos)} -| sideff {[fst $1], snd $1} -| line lines {fst $1 @ fst $2, sp_pos_range $1 $2} +| { default_esp [] } +| sideff { new_esp [$1.any] $1 $1 } +| line lines { new_esp ($1.any @ $2.any) $1 $2 }  line: -| decl {[fst $1], snd $1} -| if_then_else {[fst $1], snd $1} -| loop {[fst $1], snd $1} -| LABEL {sp_cr($1); [Label(fst $1)], snd $1} -| PERL_CHECKER_COMMENT {sp_p($1); [Perl_checker_comment(fst $1, get_pos $1)], snd $1} -| semi_colon {[Semi_colon], snd $1} -| sideff semi_colon {[fst $1 ; Semi_colon], snd $1} -| BRACKET lines BRACKET_END {check_block_sub $2 $3; [Block(fst $2)], sp_pos_range $1 $3} +| decl { new_esp [$1.any] $1 $1 } +| if_then_else { new_esp [$1.any] $1 $1 } +| loop { new_esp [$1.any] $1 $1 } +| LABEL { sp_cr($1); new_esp [Label $1.any] $1 $1 } +| PERL_CHECKER_COMMENT {sp_p($1); new_esp [Perl_checker_comment($1.any, get_pos $1)] $1 $1} +| semi_colon {new_esp [Semi_colon] $1 $1} +| sideff semi_colon {new_esp [$1.any ; Semi_colon] $1 $1} +| BRACKET lines BRACKET_END {check_block_sub $2 $3; new_esp [Block $2.any] $1 $3}  if_then_else: /* Real conditional expressions */ -| IF     PAREN expr PAREN_END BRACKET lines BRACKET_END elsif else_ {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); check_block_sub $6 $7; to_Call_op("if",     prio_lo P_loose $3 :: Block(fst $6) :: fst $8 @ fst $9) (sp_pos_range $1 $9)} -| UNLESS PAREN expr PAREN_END BRACKET lines BRACKET_END elsif else_ {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); check_block_sub $6 $7; to_Call_op("unless", prio_lo P_loose $3 :: Block(fst $6) :: fst $8 @ fst $9) (sp_pos_range $1 $9)} +| IF     PAREN expr PAREN_END BRACKET lines BRACKET_END elsif else_ {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); check_block_sub $6 $7; to_Call_op "if"     (prio_lo P_loose $3 :: Block $6.any :: $8.any @ $9.any) $1 $9} +| UNLESS PAREN expr PAREN_END BRACKET lines BRACKET_END elsif else_ {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); check_block_sub $6 $7; to_Call_op "unless" (prio_lo P_loose $3 :: Block $6.any :: $8.any @ $9.any) $1 $9}  elsif: -|  {[], (Space_none, bpos)} -| ELSIF PAREN expr PAREN_END BRACKET lines BRACKET_END elsif {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); check_block_sub $6 $7; prio_lo P_loose $3 :: Block(fst $6) :: fst $8, sp_pos_range $1 $8} +|  {default_esp []} +| ELSIF PAREN expr PAREN_END BRACKET lines BRACKET_END elsif {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); check_block_sub $6 $7; new_esp (prio_lo P_loose $3 :: Block $6.any :: $8.any) $1 $8}  else_:  -|            { [], (Space_none, bpos) } -| ELSE BRACKET lines BRACKET_END {sp_p($1); sp_n($2); check_block_sub $3 $4; [Block(fst $3)], sp_pos_range $1 $4} +|            { default_esp [] } +| ELSE BRACKET lines BRACKET_END {sp_p($1); sp_n($2); check_block_sub $3 $4; new_esp [Block $3.any] $1 $4}  loop: -| WHILE PAREN expr PAREN_END BRACKET lines BRACKET_END cont {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); check_block_sub $6 $7; to_Call_op("while", [ prio_lo P_loose $3; Block(fst $6) ]) (sp_pos_range $1 $8)} -| UNTIL PAREN expr PAREN_END BRACKET lines BRACKET_END cont {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); check_block_sub $6 $7; to_Call_op("until", [ prio_lo P_loose $3; Block(fst $6) ]) (sp_pos_range $1 $8)} -| FOR PAREN expr_or_empty semi_colon expr_or_empty semi_colon expr_or_empty PAREN_END BRACKET lines BRACKET_END {sp_p($1); check_for($1); sp_n($2); sp_0($3); sp_p($5); sp_p($7); sp_0($8); sp_n($9); check_block_sub $10 $11; to_Call_op("for", [ fst $3; fst $5; fst $7; Block(fst $10) ]) (sp_pos_range $1 $11)} +| WHILE PAREN expr PAREN_END BRACKET lines BRACKET_END cont {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); check_block_sub $6 $7; to_Call_op "while" [ prio_lo P_loose $3; Block $6.any ] $1 $8} +| UNTIL PAREN expr PAREN_END BRACKET lines BRACKET_END cont {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); check_block_sub $6 $7; to_Call_op "until" [ prio_lo P_loose $3; Block $6.any ] $1 $8} +| FOR PAREN expr_or_empty semi_colon expr_or_empty semi_colon expr_or_empty PAREN_END BRACKET lines BRACKET_END {sp_p($1); check_for($1); sp_n($2); sp_0($3); sp_p($5); sp_p($7); sp_0($8); sp_n($9); check_block_sub $10 $11; to_Call_op "for" [ $3.any; $5.any; $7.any; Block $10.any ] $1 $11}  | FOR SCALAR_IDENT PAREN expr PAREN_END BRACKET lines BRACKET_END cont { die_rule "don't use for without \"my\"ing the iteration variable" } -| FOR PAREN expr PAREN_END BRACKET lines BRACKET_END cont {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); check_block_sub $6 $7; check_for_foreach $1 $3; to_Call_op("foreach", [ prio_lo P_loose $3; Block(fst $6) ]) (sp_pos_range $1 $8)} -| for_my lines BRACKET_END cont {check_block_sub $2 $3; to_Call_op("foreach my", fst $1 @ [ Block(fst $2) ]) (sp_pos_range $1 $4)} +| FOR PAREN expr PAREN_END BRACKET lines BRACKET_END cont {sp_p($1); sp_n($2); sp_0($3); sp_0_or_cr($4); sp_p($5); check_block_sub $6 $7; check_for_foreach $1 $3; to_Call_op "foreach" [ prio_lo P_loose $3; Block $6.any ] $1 $8} +| for_my lines BRACKET_END cont {check_block_sub $2 $3; to_Call_op "foreach my" ($1.any @ [ Block $2.any ]) $1 $4}  for_my: -| FOR MY_OUR SCALAR_IDENT PAREN expr PAREN_END BRACKET {sp_p($1); check_my($2); check_foreach($1); sp_n($4); sp_0($5); sp_0_or_cr($6); sp_p($7); [ My_our(fst $2, [I_scalar, sndfst $3], get_pos $3); prio_lo P_loose $5 ], sp_pos_range $1 $7} +| FOR MY_OUR SCALAR_IDENT PAREN expr PAREN_END BRACKET {sp_p($1); check_my($2); check_foreach($1); sp_n($4); sp_0($5); sp_0_or_cr($6); sp_p($7); new_esp [ My_our($2.any, [I_scalar, snd $3.any], get_pos $3); prio_lo P_loose $5 ] $1 $7}  cont: /* Continue blocks */ -|  {(), (Space_none, bpos)} -| CONTINUE BRACKET lines BRACKET_END {sp_p($1); sp_n($2); check_block_sub $3 $4; (), sp_pos_range $1 $4} +|  {default_esp ()} +| CONTINUE BRACKET lines BRACKET_END {sp_p($1); sp_n($2); check_block_sub $3 $4; new_esp () $1 $4}  sideff: /* An expression which may have a side-effect */ -| expr  {sndfst $1, snd $1} -| expr   IF    expr {sp_p($2); sp_p($3);                    call_op_if_infix         (prio_lo P_loose $1) (prio_lo P_loose $3)   (sp_pos_range $1 $3)} -| expr UNLESS  expr {sp_p($2); sp_p($3);                    call_op_unless_infix     (prio_lo P_loose $1) (prio_lo P_loose $3)   (sp_pos_range $1 $3)} -| expr  WHILE  expr {sp_p($2); sp_p($3);                    to_Call_op("while infix" , [ prio_lo P_loose $1 ; prio_lo P_loose $3 ]) (sp_pos_range $1 $3)} -| expr  UNTIL  expr {sp_p($2); sp_p($3);                    to_Call_op("until infix" , [ prio_lo P_loose $1 ; prio_lo P_loose $3 ]) (sp_pos_range $1 $3)} -| expr  FOR    expr {sp_p($2); sp_p($3); check_foreach($2); to_Call_op("for infix"   , [ prio_lo P_loose $1 ; prio_lo P_loose $3 ]) (sp_pos_range $1 $3)} +| expr  {new_esp $1.any.expr $1 $1} +| expr   IF    expr {sp_p($2); sp_p($3);                    call_op_if_infix         (prio_lo P_loose $1) (prio_lo P_loose $3) $1 $3} +| expr UNLESS  expr {sp_p($2); sp_p($3);                    call_op_unless_infix     (prio_lo P_loose $1) (prio_lo P_loose $3) $1 $3} +| expr  WHILE  expr {sp_p($2); sp_p($3);                    to_Call_op "while infix" [ prio_lo P_loose $1 ; prio_lo P_loose $3 ] $1 $3} +| expr  UNTIL  expr {sp_p($2); sp_p($3);                    to_Call_op "until infix" [ prio_lo P_loose $1 ; prio_lo P_loose $3 ] $1 $3} +| expr  FOR    expr {sp_p($2); sp_p($3); check_foreach($2); to_Call_op "for infix"   [ prio_lo P_loose $1 ; prio_lo P_loose $3 ] $1 $3}  decl: -| FORMAT BAREWORD ASSIGN {Too_complex, sp_pos_range $1 $3} -| FORMAT ASSIGN {Too_complex, sp_pos_range $1 $2} -| func_decl semi_colon {if sndfst $1 = "" then die_rule "there is no need to pre-declare in Perl!" else (warn_rule "please don't use prototype pre-declaration" ; Too_complex, sp_pos_range $1 $2) } -| func_decl BRACKET BRACKET_END {sp_n($2); sp_0_or_cr($3); let name, proto = fst $1 in sub_declaration (name, proto) [], sp_pos_range $1 $3} -| func_decl BRACKET lines BRACKET_END {sp_n($2); check_block_sub $3 $4; sub_declaration (fst $1) (fst $3), sp_pos_range $1 $4} -| func_decl BRACKET BRACKET expr BRACKET_END            BRACKET_END {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sub_declaration (fst $1) [Ref(I_hash, prio_lo P_loose $4)], sp_pos_range $1 $6} -| func_decl BRACKET BRACKET expr BRACKET_END semi_colon BRACKET_END {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($7); sub_declaration (fst $1) [Ref(I_hash, prio_lo P_loose $4); Semi_colon], sp_pos_range $1 $7} -| PACKAGE word semi_colon {sp_0_or_cr($1); sp_1($2); Package(fst $2), sp_pos_range $1 $3} -| BEGIN BRACKET lines BRACKET_END {sp_0_or_cr($1); sp_1($2); check_block_sub $3 $4; Sub_declaration(Ident(None, "BEGIN", get_pos $1), "", Block(fst $3)), sp_pos_range $1 $4} -| END   BRACKET lines BRACKET_END {sp_0_or_cr($1); sp_1($2); check_block_sub $3 $4; Sub_declaration(Ident(None, "END",   get_pos $1), "", Block(fst $3)), sp_pos_range $1 $4} +| FORMAT BAREWORD ASSIGN {new_esp Too_complex $1 $3} +| FORMAT ASSIGN {new_esp Too_complex $1 $2} +| func_decl semi_colon {if snd $1.any = "" then die_rule "there is no need to pre-declare in Perl!" else (warn_rule "please don't use prototype pre-declaration" ; new_esp Too_complex $1 $2) } +| func_decl BRACKET BRACKET_END {sp_n($2); sp_0_or_cr($3); let name, proto = $1.any in new_esp (sub_declaration (name, proto) []) $1 $3} +| func_decl BRACKET lines BRACKET_END {sp_n($2); check_block_sub $3 $4; new_esp (sub_declaration $1.any $3.any) $1 $4} +| func_decl BRACKET BRACKET expr BRACKET_END            BRACKET_END {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); new_esp (sub_declaration $1.any [Ref(I_hash, prio_lo P_loose $4)]) $1 $6} +| func_decl BRACKET BRACKET expr BRACKET_END semi_colon BRACKET_END {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($7); new_esp (sub_declaration $1.any [Ref(I_hash, prio_lo P_loose $4); Semi_colon]) $1 $7} +| PACKAGE word semi_colon {sp_0_or_cr($1); sp_1($2); new_esp (Package $2.any) $1 $3} +| BEGIN BRACKET lines BRACKET_END {sp_0_or_cr($1); sp_1($2); check_block_sub $3 $4; new_esp (Sub_declaration(Ident(None, "BEGIN", get_pos $1), "", Block $3.any)) $1 $4} +| END   BRACKET lines BRACKET_END {sp_0_or_cr($1); sp_1($2); check_block_sub $3 $4; new_esp (Sub_declaration(Ident(None, "END",   get_pos $1), "", Block $3.any)) $1 $4}  | use {$1}  use: -| use_word listexpr semi_colon {sp_n($2); Use(fst $1, sndfst $2), sp_pos_range $1 $3} -| use_revision RAW_IDENT_PAREN PAREN PAREN_END {Use(to_Ident $2, []), sp_pos_range $1 $2} +| use_word listexpr semi_colon {sp_n($2); new_esp (Use($1.any, $2.any.expr)) $1 $3} +| use_revision RAW_IDENT_PAREN PAREN PAREN_END {new_esp (Use(to_Ident $2, [])) $1 $2}  use_word: -| use_revision word comma {fst $2, sp_pos_range $1 $3} -| use_revision word {fst $2, sp_pos_range $1 $2} -| use_revision {Ident(None, "", get_pos $1), snd $1} +| use_revision word comma {new_esp $2.any $1 $3} +| use_revision word {new_esp $2.any $1 $2} +| use_revision {new_esp (Ident(None, "", get_pos $1)) $1 $1}  use_revision:  | USE REVISION comma {$1} @@ -178,235 +179,235 @@ use_revision:  | USE {$1}  func_decl: -| SUB word {(fst $2, ""), sp_pos_range $1 $2} -| FUNC_DECL_WITH_PROTO {(Ident(None, fstfst $1, get_pos $1), sndfst $1), snd $1} +| SUB word { new_esp ($2.any, "") $1 $2} +| FUNC_DECL_WITH_PROTO {new_esp (Ident(None, fst $1.any, get_pos $1), snd $1.any) $1 $1}  listexpr: /* Basic list expressions */ -| %prec PREC_LOW {(P_tok, []), (Space_none, bpos)} +| %prec PREC_LOW { default_pesp P_tok []}  | argexpr %prec PREC_LOW {$1}  expr: /* Ordinary expressions; logical combinations */ -| expr AND expr {sp_p($2); sp_p($3); to_Call_op_(P_and, "and", [ prio_lo P_and $1; prio_lo_after P_and $3 ]) (sp_pos_range $1 $3)} -| expr OR  expr {sp_p($2); sp_p($3); to_Call_op_(P_or,  "or",  [ prio_lo P_or  $1; prio_lo_after P_or  $3 ]) (sp_pos_range $1 $3)} -| argexpr %prec PREC_LOW {(fstfst $1, List(sndfst $1)), snd $1} +| expr AND expr {sp_p($2); sp_p($3); to_Call_op_ P_and "and" [ prio_lo P_and $1; prio_lo_after P_and $3 ] $1 $3} +| expr OR  expr {sp_p($2); sp_p($3); to_Call_op_ P_or  "or"  [ prio_lo P_or  $1; prio_lo_after P_or  $3 ] $1 $3} +| argexpr %prec PREC_LOW { new_pesp $1.any.priority (List $1.any.expr) $1 $1 }  argexpr: /* Expressions are a list of terms joined by commas */ -| argexpr comma {(P_comma, sndfst $1), sp_pos_range $1 $2} -| argexpr comma term {if not_simple (sndfst $3) then sp_p($3); (P_comma, followed_by_comma $1 $2 @ [sndfst $3]), sp_pos_range $1 $3} -| argexpr comma BRACKET expr BRACKET_END {sp_p($3); sp_p($5); (P_comma, followed_by_comma $1 $2 @ [ Ref(I_hash, sndfst $4) ]), sp_pos_range $1 $5} -| term %prec PREC_LOW {(fstfst $1, [sndfst $1]), snd $1} +| argexpr comma { new_pesp P_comma $1.any.expr $1 $2} +| argexpr comma term {if not_simple ($3.any.expr) then sp_p($3); new_pesp P_comma (followed_by_comma $1 $2 @ [$3.any.expr]) $1 $3} +| argexpr comma BRACKET expr BRACKET_END {sp_p($3); sp_p($5); new_pesp P_comma (followed_by_comma $1 $2 @ [ Ref(I_hash, $4.any.expr) ]) $1 $5} +| term %prec PREC_LOW { new_pesp $1.any.priority [$1.any.expr] $1 $1 }  /********************************************************************************/  term: -| term ASSIGN     term {let pri = P_assign    in call_op_(op   pri (fst $2) $2, $3, [sndfst      $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term PLUS       term {let pri = P_add       in call_op_(op   pri (fst $2) $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term COMPARE_OP term {let pri = P_cmp       in call_op_(op_p pri (fst $2) $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term LT         term {let pri = P_cmp       in call_op_(op_p pri "<"      $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term GT         term {let pri = P_cmp       in call_op_(op_p pri ">"      $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term EQ_OP      term {let pri = P_eq        in call_op_(op_p pri (fst $2) $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term POWER      term {let pri = P_tight     in call_op_(op   pri "**"     $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term BIT_AND    term {let pri = P_bit       in call_op_(op_p pri "&"      $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term BIT_OR     term {let pri = P_bit       in call_op_(op   pri "|"      $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term BIT_XOR    term {let pri = P_bit       in call_op_(op_p pri "^"      $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term AND_TIGHT  term {let pri = P_tight_and in call_op_(op_p pri "&&"     $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term OR_TIGHT   term {let pri = P_tight_or  in call_op_(op_p pri "||"     $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term MULT       term {let pri = P_mul       in call_op_(op   pri (fst $2) $2, $3, [prio_lo_concat $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term DOTDOT     term {let pri = P_paren_wanted P_expr  in call_op_(op   pri (fst $2) $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term BIT_SHIFT  term {let pri = P_paren_wanted P_tight in call_op_(op   pri (fst $2) $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} -| term XOR        term {let pri = P_paren_wanted P_expr  in call_op_(op_p pri "xor"    $2, $3, [prio_lo pri $1; prio_lo_after pri $3]) (sp_pos_range $1 $3)} - -| term ASSIGN     BRACKET expr BRACKET_END {sp_p($3); sp_p($4); sp_p($5); call_op_(op_p P_assign (fst $2) $2, $3, [prio_lo P_assign    $1; Ref(I_hash, sndfst $4)]) (sp_pos_range $1 $5)} -| term AND_TIGHT  BRACKET expr BRACKET_END {sp_p($3); sp_p($4); sp_p($5); call_op_(op_p P_tight_and "&&"  $2, $3, [prio_lo P_assign    $1; Ref(I_hash, sndfst $4)]) (sp_pos_range $1 $5)} -| term OR_TIGHT   BRACKET expr BRACKET_END {sp_p($3); sp_p($4); sp_p($5); call_op_(op_p P_tight_or  "||"  $2, $3, [prio_lo P_assign    $1; Ref(I_hash, sndfst $4)]) (sp_pos_range $1 $5)} - - -| term PATTERN_MATCH     PATTERN   {sp_n($2); sp_p($3); check_unneeded_var_dollar_   ($1); let pattern = from_PATTERN $3 in check_simple_pattern pattern ; to_Call_op_(P_expr, "m//",  sndfst $1 :: pattern) (sp_pos_range $1 $3)} -| term PATTERN_MATCH_NOT PATTERN   {sp_n($2); sp_p($3); check_unneeded_var_dollar_not($1); let pattern = from_PATTERN $3 in check_simple_pattern pattern ; to_Call_op_(P_expr, "!m//", sndfst $1 :: pattern) (sp_pos_range $1 $3)} -| term PATTERN_MATCH PATTERN_SUBST {sp_n($2); sp_p($3); check_unneeded_var_dollar_s  ($1); to_Call_op_(P_expr, "s///", sndfst $1 :: from_PATTERN_SUBST $3) (sp_pos_range $1 $3)} -| term PATTERN_MATCH_NOT PATTERN_SUBST {die_with_rawpos (sndsnd $2) "use =~ instead of !~ and negate the return value"} - -| term PATTERN_MATCH     QR_PATTERN {sp_n($2); sp_p($3); to_Call_op_(P_expr, "m//",  sndfst $1 :: from_PATTERN $3) (sp_pos_range $1 $3)} -| term PATTERN_MATCH_NOT QR_PATTERN {sp_n($2); sp_p($3); to_Call_op_(P_expr, "!m//", sndfst $1 :: from_PATTERN $3) (sp_pos_range $1 $3)} -| term PATTERN_MATCH     scalar { (P_expr, Call(Too_complex, [sndfst $1 ; fst $3 ])), sp_pos_range $1 $3} -| term PATTERN_MATCH_NOT scalar { (P_expr, Call(Too_complex, [sndfst $1 ; fst $3 ])), sp_pos_range $1 $3} - -| term PATTERN_MATCH     RAW_STRING {die_with_rawpos (sndsnd $3) "use a regexp, not a string"} -| term PATTERN_MATCH_NOT RAW_STRING {die_with_rawpos (sndsnd $3) "use a regexp, not a string"} -| term PATTERN_MATCH     STRING {die_with_rawpos (sndsnd $3) "use a regexp, not a string"} -| term PATTERN_MATCH_NOT STRING {die_with_rawpos (sndsnd $3) "use a regexp, not a string"} - - -| term QUESTION_MARK term COLON term {sp_p($2); sp_p($3); sp_p($4); sp_p($5); to_Call_op_(P_ternary, "?:", check_ternary_paras(prio_lo P_ternary $1, prio_lo_after P_ternary $3, prio_lo_after P_ternary $5)) (sp_pos_range $1 $5)} -| term QUESTION_MARK term COLON BRACKET expr BRACKET_END {sp_p($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sp_p($7); to_Call_op_(P_ternary, "?:", check_ternary_paras(prio_lo P_ternary $1, prio_lo_after P_ternary $3, Ref(I_hash, sndfst $6))) (sp_pos_range $1 $7)} -| term QUESTION_MARK BRACKET expr BRACKET_END COLON term {sp_p($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sp_p($7); to_Call_op_(P_ternary, "?:", check_ternary_paras(prio_lo P_ternary $1, Ref(I_hash, sndfst $4), prio_lo_after P_ternary $7)) (sp_pos_range $1 $7)} -| term QUESTION_MARK BRACKET expr BRACKET_END COLON BRACKET expr BRACKET_END {sp_p($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sp_p($7); sp_p($8); sp_p($9); to_Call_op_(P_ternary, "?:", check_ternary_paras(prio_lo P_ternary $1, Ref(I_hash, sndfst $4), Ref(I_hash, sndfst $8))) (sp_pos_range $1 $9)} +| term ASSIGN     term {sp_same $2 $3;          let pri = P_assign    in to_Call_op_ pri $2.any [$1.any.expr   ; prio_lo_after pri $3] $1 $3} +| term PLUS       term {sp_same $2 $3;          let pri = P_add       in to_Call_op_ pri $2.any [prio_lo pri $1; prio_lo_after pri $3] $1 $3} +| term COMPARE_OP term {sp_same $2 $3; sp_p $2; let pri = P_cmp       in to_Call_op_ pri $2.any [prio_lo pri $1; prio_lo_after pri $3] $1 $3} +| term LT         term {sp_same $2 $3; sp_p $2; let pri = P_cmp       in to_Call_op_ pri "<"    [prio_lo pri $1; prio_lo_after pri $3] $1 $3} +| term GT         term {sp_same $2 $3; sp_p $2; let pri = P_cmp       in to_Call_op_ pri ">"    [prio_lo pri $1; prio_lo_after pri $3] $1 $3} +| term EQ_OP      term {sp_same $2 $3; sp_p $2; let pri = P_eq        in to_Call_op_ pri $2.any [prio_lo pri $1; prio_lo_after pri $3] $1 $3} +| term POWER      term {sp_same $2 $3;          let pri = P_tight     in to_Call_op_ pri "**"   [prio_lo pri $1; prio_lo_after pri $3] $1 $3} +| term BIT_AND    term {sp_same $2 $3; sp_p $2; let pri = P_bit       in to_Call_op_ pri "&"    [prio_lo pri $1; prio_lo_after pri $3] $1 $3} +| term BIT_OR     term {sp_same $2 $3;          let pri = P_bit       in to_Call_op_ pri "|"    [prio_lo pri $1; prio_lo_after pri $3] $1 $3} +| term BIT_XOR    term {sp_same $2 $3; sp_p $2; let pri = P_bit       in to_Call_op_ pri "^"    [prio_lo pri $1; prio_lo_after pri $3] $1 $3} +| term AND_TIGHT  term {sp_same $2 $3; sp_p $2; let pri = P_tight_and in to_Call_op_ pri "&&"   [prio_lo pri $1; prio_lo_after pri $3] $1 $3} +| term OR_TIGHT   term {sp_same $2 $3; sp_p $2; let pri = P_tight_or  in to_Call_op_ pri "||"   [prio_lo pri $1; prio_lo_after pri $3] $1 $3} +| term MULT       term {sp_same $2 $3;          let pri = P_mul       in to_Call_op_ pri $2.any [prio_lo_concat $1; prio_lo_after pri $3] $1 $3} +| term DOTDOT     term {sp_same $2 $3;          let pri = P_paren_wanted P_expr  in to_Call_op_ pri $2.any [prio_lo pri $1; prio_lo_after pri $3] $1 $3} +| term BIT_SHIFT  term {sp_same $2 $3;          let pri = P_paren_wanted P_tight in to_Call_op_ pri $2.any [prio_lo pri $1; prio_lo_after pri $3] $1 $3} +| term XOR        term {sp_same $2 $3; sp_p $2; let pri = P_paren_wanted P_expr  in to_Call_op_ pri "xor"  [prio_lo pri $1; prio_lo_after pri $3] $1 $3} + +| term ASSIGN     BRACKET expr BRACKET_END {sp_p($2); sp_p($3); sp_p($4); sp_p($5); to_Call_op_ P_assign    $2.any [prio_lo P_assign $1; Ref(I_hash, $4.any.expr)] $1 $5} +| term AND_TIGHT  BRACKET expr BRACKET_END {sp_p($2); sp_p($3); sp_p($4); sp_p($5); to_Call_op_ P_tight_and "&&"   [prio_lo P_assign $1; Ref(I_hash, $4.any.expr)] $1 $5} +| term OR_TIGHT   BRACKET expr BRACKET_END {sp_p($2); sp_p($3); sp_p($4); sp_p($5); to_Call_op_ P_tight_or  "||"   [prio_lo P_assign $1; Ref(I_hash, $4.any.expr)] $1 $5} + + +| term PATTERN_MATCH     PATTERN   {sp_n($2); sp_p($3); check_unneeded_var_dollar_   ($1); let pattern = from_PATTERN $3 in check_simple_pattern pattern ; to_Call_op_ P_expr "m//"  ($1.any.expr :: pattern) $1 $3} +| term PATTERN_MATCH_NOT PATTERN   {sp_n($2); sp_p($3); check_unneeded_var_dollar_not($1); let pattern = from_PATTERN $3 in check_simple_pattern pattern ; to_Call_op_ P_expr "!m//" ($1.any.expr :: pattern) $1 $3} +| term PATTERN_MATCH PATTERN_SUBST {sp_n($2); sp_p($3); check_unneeded_var_dollar_s  ($1); to_Call_op_ P_expr "s///" ($1.any.expr :: from_PATTERN_SUBST $3) $1 $3} +| term PATTERN_MATCH_NOT PATTERN_SUBST {die_with_rawpos $2.pos "use =~ instead of !~ and negate the return value"} + +| term PATTERN_MATCH     QR_PATTERN {sp_n($2); sp_p($3); to_Call_op_ P_expr "m//"  ($1.any.expr :: from_PATTERN $3) $1 $3} +| term PATTERN_MATCH_NOT QR_PATTERN {sp_n($2); sp_p($3); to_Call_op_ P_expr "!m//" ($1.any.expr :: from_PATTERN $3) $1 $3} +| term PATTERN_MATCH     scalar { new_pesp P_expr (Call(Too_complex, [$1.any.expr ; $3.any ])) $1 $3} +| term PATTERN_MATCH_NOT scalar { new_pesp P_expr (Call(Too_complex, [$1.any.expr ; $3.any ])) $1 $3} + +| term PATTERN_MATCH     RAW_STRING {die_with_rawpos $3.pos "use a regexp, not a string"} +| term PATTERN_MATCH_NOT RAW_STRING {die_with_rawpos $3.pos "use a regexp, not a string"} +| term PATTERN_MATCH     STRING {die_with_rawpos $3.pos "use a regexp, not a string"} +| term PATTERN_MATCH_NOT STRING {die_with_rawpos $3.pos "use a regexp, not a string"} + + +| term QUESTION_MARK term COLON term {sp_p($2); sp_p($3); sp_p($4); sp_p($5); to_Call_op_ P_ternary "?:" (check_ternary_paras(prio_lo P_ternary $1, prio_lo_after P_ternary $3, prio_lo_after P_ternary $5)) $1 $5} +| term QUESTION_MARK term COLON BRACKET expr BRACKET_END {sp_p($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sp_p($7); to_Call_op_ P_ternary "?:" (check_ternary_paras(prio_lo P_ternary $1, prio_lo_after P_ternary $3, Ref(I_hash, $6.any.expr))) $1 $7} +| term QUESTION_MARK BRACKET expr BRACKET_END COLON term {sp_p($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sp_p($7); to_Call_op_ P_ternary "?:" (check_ternary_paras(prio_lo P_ternary $1, Ref(I_hash, $4.any.expr), prio_lo_after P_ternary $7)) $1 $7} +| term QUESTION_MARK BRACKET expr BRACKET_END COLON BRACKET expr BRACKET_END {sp_p($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sp_p($7); sp_p($8); sp_p($9); to_Call_op_ P_ternary "?:" (check_ternary_paras(prio_lo P_ternary $1, Ref(I_hash, $4.any.expr), Ref(I_hash, $8.any.expr))) $1 $9}  /* Unary operators and terms */  | PLUS term %prec UNARY_MINUS {      sp_0($2);  -    match fst $1 with +    match $1.any with      | "+" ->  	warn_rule "don't use unary +" ; -	to_Call_op_(P_tight, "+ unary", [sndfst $2]) (sp_pos_range $1 $2) +	to_Call_op_ P_tight "+ unary" [$2.any.expr] $1 $2      | "-" -> -	to_Call_op_(P_tight, "- unary", [sndfst $2]) (sp_pos_range $1 $2) +	to_Call_op_ P_tight "- unary" [$2.any.expr] $1 $2      | _ -> die_rule "syntax error"  } -| TIGHT_NOT term {check_negatable_expr $2; to_Call_op_(P_tight, "not", [sndfst $2]) (sp_pos_range $1 $2)} -| BIT_NEG term {to_Call_op_(P_expr, "~", [sndfst $2]) (sp_pos_range $1 $2)} -| INCR term    {sp_0($2); to_Call_op_(P_tight, "++", [sndfst $2]) (sp_pos_range $1 $2)} -| DECR term    {sp_0($2); to_Call_op_(P_tight, "--", [sndfst $2]) (sp_pos_range $1 $2)} -| term INCR    {sp_0($2); to_Call_op_(P_tight, "++ post", [sndfst $1]) (sp_pos_range $1 $2)} -| term DECR    {sp_0($2); to_Call_op_(P_tight, "-- post", [sndfst $1]) (sp_pos_range $1 $2)} -| NOT argexpr  {warn_rule "don't use \"not\", use \"!\" instead"; to_Call_op_(P_and, "not", sndfst $2) (sp_pos_range $1 $2)} +| TIGHT_NOT term {check_negatable_expr $2; to_Call_op_ P_tight "not" [$2.any.expr] $1 $2} +| BIT_NEG term {to_Call_op_ P_expr "~" [$2.any.expr] $1 $2} +| INCR term    {sp_0($2); to_Call_op_ P_tight "++" [$2.any.expr] $1 $2} +| DECR term    {sp_0($2); to_Call_op_ P_tight "--" [$2.any.expr] $1 $2} +| term INCR    {sp_0($2); to_Call_op_ P_tight "++ post" [$1.any.expr] $1 $2} +| term DECR    {sp_0($2); to_Call_op_ P_tight "-- post" [$1.any.expr] $1 $2} +| NOT argexpr  {warn_rule "don't use \"not\", use \"!\" instead"; to_Call_op_ P_and "not" ($2.any.expr) $1 $2}  /* Constructors for anonymous data */ -| ARRAYREF ARRAYREF_END {sp_0($2); (P_expr, Ref(I_array, List[])), sp_pos_range $1 $2} -| arrayref_start ARRAYREF_END {(if fst $1 = [] then sp_0 else sp_p)($2) ; (P_expr, Ref(I_array, List(fst $1))), sp_pos_range $1 $2} -| arrayref_start expr ARRAYREF_END {sp_same $2 $3; (P_expr, Ref(I_array, List(fst $1 @ [sndfst $2]))), sp_pos_range $1 $3} -| arrayref_start BRACKET expr BRACKET_END ARRAYREF_END {sp_same $2 $5; (P_expr, Ref(I_array, List(fst $1 @ [Ref(I_hash, sndfst $3)]))), sp_pos_range $1 $5} +| ARRAYREF ARRAYREF_END {sp_0($2); new_pesp P_expr (Ref(I_array, List[])) $1 $2} +| arrayref_start ARRAYREF_END {(if $1.any = [] then sp_0 else sp_p)($2) ; new_pesp P_expr (Ref(I_array, List $1.any)) $1 $2} +| arrayref_start expr ARRAYREF_END {sp_same $2 $3; new_pesp P_expr (Ref(I_array, List($1.any @ [$2.any.expr]))) $1 $3} +| arrayref_start BRACKET expr BRACKET_END ARRAYREF_END {sp_same $2 $5; new_pesp P_expr (Ref(I_array, List($1.any @ [Ref(I_hash, $3.any.expr)]))) $1 $5} -| BRACKET BRACKET_END {(P_expr, Ref(I_hash, List [])), sp_pos_range $1 $2} /* empty hash */ -| BRACKET_HASHREF expr BRACKET_END %prec PREC_HIGH {sp_p($3); (P_expr, Ref(I_hash, sndfst $2)), sp_pos_range $1 $3} /* { foo => "Bar" } */ -| SUB BRACKET BRACKET_END %prec PREC_HIGH {sp_n($2); sp_0($3); (P_expr, anonymous_sub ([], snd $2)), sp_pos_range $1 $3} -| SUB BRACKET lines BRACKET_END %prec PREC_HIGH {sp_n($2); check_block_sub $3 $4; (P_expr, anonymous_sub $3), sp_pos_range $1 $4} +| BRACKET BRACKET_END {new_pesp P_expr (Ref(I_hash, List [])) $1 $2} /* empty hash */ +| BRACKET_HASHREF expr BRACKET_END %prec PREC_HIGH {sp_p($3); new_pesp P_expr (Ref(I_hash, $2.any.expr)) $1 $3} /* { foo => "Bar" } */ +| SUB BRACKET BRACKET_END %prec PREC_HIGH {sp_n($2); sp_0($3); new_pesp P_expr (anonymous_sub (new_esp [] $2 $2)) $1 $3} +| SUB BRACKET lines BRACKET_END %prec PREC_HIGH {sp_n($2); check_block_sub $3 $4; new_pesp P_expr (anonymous_sub $3) $1 $4} -| termdo {(P_tok, fst $1), snd $1} -| REF term {(P_expr, Ref(I_scalar, sndfst $2)), sp_pos_range $1 $2} /* \$x, \@y, \%z */ -| my_our %prec UNIOP {(P_expr, fst $1), snd $1} -| LOCAL term    %prec UNIOP {sp_n($2); (P_expr, to_Local $2), sp_pos_range $1 $2} +| termdo {new_pesp P_tok $1.any $1 $1} +| REF term {new_pesp P_expr (Ref(I_scalar, $2.any.expr)) $1 $2} /* \$x, \@y, \%z */ +| my_our %prec UNIOP {new_pesp P_expr $1.any $1 $1} +| LOCAL term    %prec UNIOP {sp_n($2); new_pesp P_expr (to_Local $2) $1 $2} -| parenthesized {(fstfst $1, List(sndfst $1)), snd $1} /* (1, 2) */ -| parenthesized arrayref {sp_0($2); (P_tok, to_Deref_with(I_array, (if is_only_one_in_List(fst $2) then I_scalar else I_array), List(sndfst $1), List(fst $2))), sp_pos_range $1 $2} /* list indexing or slicing */ +| parenthesized {new_pesp $1.any.priority (List $1.any.expr) $1 $1} /* (1, 2) */ +| parenthesized arrayref {sp_0($2); new_pesp P_tok (to_Deref_with(I_array, (if is_only_one_in_List $2.any then I_scalar else I_array), List $1.any.expr, List $2.any)) $1 $2} /* list indexing or slicing */ -| variable {(P_tok, fst $1), snd $1} +| variable {new_pesp P_tok $1.any $1 $1} -| subscripted {(P_tok, fst $1), snd $1} +| subscripted {new_pesp P_tok $1.any $1 $1} -| array arrayref {(P_expr, to_Deref_with(I_array, I_array, from_array $1, List(fst $2))), sp_pos_range $1 $2} /* array slice: @array[vals] */ -| array BRACKET expr BRACKET_END {sp_0($2); sp_0($3); sp_0($4); (P_expr, to_Deref_with(I_hash, I_array, from_array $1, sndfst $3)), sp_pos_range $1 $4} /* hash slice: @hash{@keys} */ +| array arrayref {new_pesp P_expr (to_Deref_with(I_array, I_array, from_array $1, List $2.any)) $1 $2} /* array slice: @array[vals] */ +| array BRACKET expr BRACKET_END {sp_0($2); sp_0($3); sp_0($4); new_pesp P_expr (to_Deref_with(I_hash, I_array, from_array $1, $3.any.expr)) $1 $4} /* hash slice: @hash{@keys} */  /* function_calls */ -| ONE_SCALAR_PARA RAW_STRING               {call_one_scalar_para $1 [to_Raw_string $2], sp_pos_range $1 $2} -| ONE_SCALAR_PARA STRING                   {call_one_scalar_para $1 [to_String true $2], sp_pos_range $1 $2} -| ONE_SCALAR_PARA variable                 {call_one_scalar_para $1 [fst $2], sp_pos_range $1 $2} -| ONE_SCALAR_PARA restricted_subscripted   {call_one_scalar_para $1 [fst $2], sp_pos_range $1 $2} -| ONE_SCALAR_PARA parenthesized            {call_one_scalar_para $1 (sndfst $2), sp_pos_range $1 $2} -| ONE_SCALAR_PARA word_paren parenthesized {call_one_scalar_para $1 [call(Deref(I_func, fst $2), sndfst $3)], sp_pos_range $1 $3} -| ONE_SCALAR_PARA {call_one_scalar_para $1 [], snd $1} -| ONE_SCALAR_PARA word argexpr {check_parenthesized_first_argexpr_with_Ident (fst $2) $3; call_one_scalar_para $1 [call(Deref(I_func, fst $2), sndfst $3)], sp_pos_range $1 $3} /* ref foo $a, $b */ -| ONE_SCALAR_PARA hash PKG_SCOPE {sp_0($3); call_one_scalar_para $1 [ Call(Too_complex, [fst $2]) ], sp_pos_range $1 $3} /* keys %main:: */ - -| func parenthesized {sp_0($2); (P_tok, call_func true (fst $1, sndfst $2)), sp_pos_range $1 $2} /* &foo(@args) */ -| word argexpr {check_parenthesized_first_argexpr_with_Ident (fst $1) $2; (P_call_no_paren, call(Deref(I_func, fst $1), sndfst $2)), sp_pos_range $1 $2} /* foo $a, $b */ -| word_paren parenthesized {sp_0($2); (P_tok, call(Deref(I_func, fst $1), sndfst $2)), sp_pos_range $1 $2} /* foo(@args) */ -| word BRACKET lines BRACKET_END listexpr %prec LSTOP {sp_n($2); check_block_sub $3 $4; ((if sndfst $5 = [] then P_tok else P_call_no_paren), call(Deref(I_func, fst $1), anonymous_sub $3 :: sndfst $5)), sp_pos_range $1 $5} /* map { foo } @bar */ -| word BRACKET BRACKET expr BRACKET_END            BRACKET_END listexpr %prec LSTOP {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); ((if sndfst $7 = [] then P_tok else P_call_no_paren), call(Deref(I_func, fst $1), anonymous_sub([ Ref(I_hash, sndfst $4) ], snd $4) :: sndfst $7)), sp_pos_range $1 $7} /* map { { foo } } @bar */ -| word BRACKET BRACKET expr BRACKET_END semi_colon BRACKET_END listexpr %prec LSTOP {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($7); ((if sndfst $8 = [] then P_tok else P_call_no_paren), call(Deref(I_func, fst $1), anonymous_sub([ Ref(I_hash, sndfst $4); Semi_colon ], snd $4) :: sndfst $8)), sp_pos_range $1 $8} /* map { { foo }; } @bar */ - -| term ARROW word_or_scalar parenthesized {sp_0($2); sp_0($3); sp_0($4); (P_tok, to_Method_call(sndfst $1, fst $3, sndfst $4)), sp_pos_range $1 $4} /* $foo->bar(list) */ -| term ARROW word_or_scalar {sp_0($2); sp_0($3); (P_tok, to_Method_call(sndfst $1, fst $3, [])), sp_pos_range $1 $3} /* $foo->bar */ -| term ARROW MULT parenthesized {check_MULT_is_x $3; sp_0($2); sp_0($3); sp_0($4); (P_tok, to_Method_call(sndfst $1, Ident(None, "x", get_pos $3), sndfst $4)), sp_pos_range $1 $4} /* $foo->bar(list) */ -| term ARROW MULT {check_MULT_is_x $3; sp_0($2); sp_0($3); (P_tok, to_Method_call(sndfst $1, Ident(None, "x", get_pos $3), [])), sp_pos_range $1 $3} /* $foo->bar */ -| term ARROW FOR  parenthesized {sp_0($2); sp_0($3); sp_0($4); (P_tok, to_Method_call(sndfst $1, Ident(None, fst $3, get_pos $3), sndfst $4)), sp_pos_range $1 $4} /* $foo->bar(list) */ -| term ARROW FOR  {sp_0($2); sp_0($3); (P_tok, to_Method_call(sndfst $1, Ident(None, fst $3, get_pos $3), [])), sp_pos_range $1 $3} /* $foo->bar */ - -| NEW word { sp_n($2); (P_call_no_paren, to_Method_call(fst $2, Ident(None, "new", get_pos $1), [])), sp_pos_range $1 $2} /* new Class */ -| NEW word_paren parenthesized { sp_n($2); sp_0($3); (P_call_no_paren, to_Method_call(fst $2, Ident(None, "new", get_pos $1), sndfst $3)), sp_pos_range $1 $3} /* new Class(...) */ +| ONE_SCALAR_PARA RAW_STRING               {call_one_scalar_para $1 [to_Raw_string $2] $1 $2} +| ONE_SCALAR_PARA STRING                   {call_one_scalar_para $1 [to_String true $2] $1 $2} +| ONE_SCALAR_PARA variable                 {call_one_scalar_para $1 [$2.any] $1 $2} +| ONE_SCALAR_PARA restricted_subscripted   {call_one_scalar_para $1 [$2.any] $1 $2} +| ONE_SCALAR_PARA parenthesized            {call_one_scalar_para $1 $2.any.expr $1 $2} +| ONE_SCALAR_PARA word_paren parenthesized {call_one_scalar_para $1 [call(Deref(I_func, $2.any), $3.any.expr)] $1 $3} +| ONE_SCALAR_PARA {call_one_scalar_para $1 [] $1 $1} +| ONE_SCALAR_PARA word argexpr {check_parenthesized_first_argexpr_with_Ident  $2.any $3; call_one_scalar_para $1 [call(Deref(I_func, $2.any), $3.any.expr)] $1 $3} /* ref foo $a, $b */ +| ONE_SCALAR_PARA hash PKG_SCOPE {sp_0($3); call_one_scalar_para $1 [ Call(Too_complex, [$2.any]) ] $1 $3} /* keys %main:: */ + +| func parenthesized {sp_0($2); new_pesp P_tok (call_func true ($1.any, $2.any.expr)) $1 $2} /* &foo(@args) */ +| word argexpr {check_parenthesized_first_argexpr_with_Ident  $1.any $2; new_pesp P_call_no_paren (call(Deref(I_func, $1.any), $2.any.expr)) $1 $2} /* foo $a, $b */ +| word_paren parenthesized {sp_0($2); new_pesp P_tok (call(Deref(I_func, $1.any), $2.any.expr)) $1 $2} /* foo(@args) */ +| word BRACKET lines BRACKET_END listexpr %prec LSTOP {sp_n($2); check_block_sub $3 $4; new_pesp (if $5.any.expr = [] then P_tok else P_call_no_paren) (call(Deref(I_func, $1.any), anonymous_sub $3 :: $5.any.expr)) $1 $5} /* map { foo } @bar */ +| word BRACKET BRACKET expr BRACKET_END            BRACKET_END listexpr %prec LSTOP {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); new_pesp (if $7.any.expr = [] then P_tok else P_call_no_paren) (call(Deref(I_func, $1.any), anonymous_sub(new_esp [ Ref(I_hash, $4.any.expr) ] $4 $4) :: $7.any.expr)) $1 $7} /* map { { foo } } @bar */ +| word BRACKET BRACKET expr BRACKET_END semi_colon BRACKET_END listexpr %prec LSTOP {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($7); new_pesp (if $8.any.expr = [] then P_tok else P_call_no_paren) (call(Deref(I_func, $1.any), anonymous_sub(new_esp [ Ref(I_hash, $4.any.expr); Semi_colon ] $4 $4) :: $8.any.expr)) $1 $8} /* map { { foo }; } @bar */ + +| term ARROW word_or_scalar parenthesized {sp_0($2); sp_0($3); sp_0($4); new_pesp P_tok (to_Method_call($1.any.expr, $3.any, $4.any.expr)) $1 $4} /* $foo->bar(list) */ +| term ARROW word_or_scalar {sp_0($2); sp_0($3); new_pesp P_tok (to_Method_call($1.any.expr, $3.any, [])) $1 $3} /* $foo->bar */ +| term ARROW MULT parenthesized {check_MULT_is_x $3; sp_0($2); sp_0($3); sp_0($4); new_pesp P_tok (to_Method_call($1.any.expr, Ident(None, "x", get_pos $3), $4.any.expr)) $1 $4} /* $foo->bar(list) */ +| term ARROW MULT {check_MULT_is_x $3; sp_0($2); sp_0($3); new_pesp P_tok (to_Method_call($1.any.expr, Ident(None, "x", get_pos $3), [])) $1 $3} /* $foo->bar */ +| term ARROW FOR  parenthesized {sp_0($2); sp_0($3); sp_0($4); new_pesp P_tok (to_Method_call($1.any.expr, Ident(None, $3.any, get_pos $3), $4.any.expr)) $1 $4} /* $foo->bar(list) */ +| term ARROW FOR  {sp_0($2); sp_0($3); new_pesp P_tok (to_Method_call($1.any.expr, Ident(None, $3.any, get_pos $3), [])) $1 $3} /* $foo->bar */ + +| NEW word { sp_n($2); new_pesp P_call_no_paren (to_Method_call ($2.any, Ident(None, "new", get_pos $1), [])) $1 $2} /* new Class */ +| NEW word_paren parenthesized { sp_n($2); sp_0($3); new_pesp P_call_no_paren (to_Method_call($2.any, Ident(None, "new", get_pos $1), $3.any.expr)) $1 $3} /* new Class(...) */  | NEW word terminal { die_rule "you must parenthesize parameters: \"new Class(...)\" instead of \"new Class ...\"" }  | NEW word variable { die_rule "you must parenthesize parameters: \"new Class(...)\" instead of \"new Class ...\"" } -| PRINT { to_Call_op_(P_call_no_paren, fst $1, var_STDOUT :: [ var_dollar_ (get_pos $1) ]) (snd $1)} -| PRINT argexpr {check_parenthesized_first_argexpr (fst $1) $2; to_Call_op_(P_call_no_paren, fst $1, var_STDOUT :: sndfst $2) (sp_pos_range $1 $2)} -| PRINT_TO_SCALAR         { to_Call_op_(P_call_no_paren, fstfst $1, var_STDOUT :: [ Deref(I_scalar, Ident(None, sndfst $1, get_pos $1)) ]) (snd $1)} -| PRINT_TO_SCALAR argexpr { to_Call_op_(P_call_no_paren, fstfst $1, Deref(I_scalar, Ident(None, sndfst $1, get_pos $1)) :: sndfst $2) (sp_pos_range $1 $2)} -| PRINT_TO_STAR           { to_Call_op_(P_call_no_paren, fstfst $1, Deref(I_star, Ident(None, sndfst $1, get_pos $1)) :: [ var_dollar_ (get_pos $1) ]) (snd $1)} -| PRINT_TO_STAR argexpr   { to_Call_op_(P_call_no_paren, fstfst $1, Deref(I_star, Ident(None, sndfst $1, get_pos $1)) :: sndfst $2) (sp_pos_range $1 $2)} +| PRINT { to_Call_op_ P_call_no_paren $1.any (var_STDOUT :: [ var_dollar_ (get_pos $1) ]) $1 $1} +| PRINT argexpr {check_parenthesized_first_argexpr  $1.any $2; to_Call_op_ P_call_no_paren $1.any (var_STDOUT :: $2.any.expr) $1 $2} +| PRINT_TO_SCALAR         { to_Call_op_ P_call_no_paren (fst $1.any) (var_STDOUT :: [ Deref(I_scalar, Ident(None, snd $1.any, get_pos $1)) ]) $1 $1} +| PRINT_TO_SCALAR argexpr { to_Call_op_ P_call_no_paren (fst $1.any) (Deref(I_scalar, Ident(None, snd $1.any, get_pos $1)) :: $2.any.expr) $1 $2} +| PRINT_TO_STAR           { to_Call_op_ P_call_no_paren (fst $1.any) (Deref(I_star, Ident(None, snd $1.any, get_pos $1)) :: [ var_dollar_ (get_pos $1) ]) $1 $1} +| PRINT_TO_STAR argexpr   { to_Call_op_ P_call_no_paren (fst $1.any) (Deref(I_star, Ident(None, snd $1.any, get_pos $1)) :: $2.any.expr) $1 $2} -| hash PKG_SCOPE {sp_0($2); (P_tok, Call(Too_complex, [fst $1])), sp_pos_range $1 $2} /* %main:: */ +| hash PKG_SCOPE {sp_0($2); new_pesp P_tok (Call(Too_complex, [$1.any])) $1 $2} /* %main:: */  | terminal {$1}  terminal: -| word {(P_tok, check_word_alone $1), snd $1} -| NUM {(P_tok, Num(fst $1, get_pos $1)), snd $1} -| STRING {(P_tok, to_String true $1), snd $1} -| RAW_STRING {(P_tok, to_Raw_string $1), snd $1} -| REVISION {(P_tok, to_Raw_string $1), snd $1} -| COMMAND_STRING {to_Call_op_(P_tok, "``", [to_String false $1]) (snd $1)} -| QUOTEWORDS {to_Call_op_(P_tok, "qw", [to_Raw_string $1]) (snd $1)} -| HERE_DOC {(P_tok, to_String false (fstfst $1, snd $1)), snd $1} -| RAW_HERE_DOC {(P_tok, Raw_string(fstfst $1, raw_pos2pos (sndfst $1))), snd $1} -| QR_PATTERN {to_Call_op_(P_tok, "qr//", from_PATTERN $1) (snd $1)} -| PATTERN {to_Call_op_(P_expr, "m//", var_dollar_ (get_pos $1) :: from_PATTERN $1) (snd $1)} -| PATTERN_SUBST {to_Call_op_(P_expr, "s///", var_dollar_ (get_pos $1) :: from_PATTERN_SUBST $1) (snd $1)} -| diamond {(P_expr, fst $1), snd $1} +| word {new_pesp P_tok (check_word_alone $1.any) $1 $1} +| NUM {new_pesp P_tok (Num($1.any, get_pos $1)) $1 $1} +| STRING {new_pesp P_tok (to_String true $1) $1 $1} +| RAW_STRING {new_pesp P_tok (to_Raw_string $1) $1 $1} +| REVISION {new_pesp P_tok (to_Raw_string $1) $1 $1} +| COMMAND_STRING {to_Call_op_ P_tok "``" [to_String false $1] $1 $1} +| QUOTEWORDS {to_Call_op_ P_tok "qw" [to_Raw_string $1] $1 $1} +| HERE_DOC {new_pesp P_tok (to_String false (new_esp (fst $1.any) $1 $1)) $1 $1} +| RAW_HERE_DOC {new_pesp P_tok (Raw_string(fst $1.any, raw_pos2pos (snd $1.any))) $1 $1} +| QR_PATTERN {to_Call_op_ P_tok "qr//" (from_PATTERN $1) $1 $1} +| PATTERN {to_Call_op_ P_expr "m//" (var_dollar_ (get_pos $1) :: from_PATTERN $1) $1 $1} +| PATTERN_SUBST {to_Call_op_ P_expr "s///" (var_dollar_ (get_pos $1) :: from_PATTERN_SUBST $1) $1 $1} +| diamond {new_pesp P_expr $1.any $1 $1}  diamond: -| LT GT {sp_0($2); to_Call_op("<>", []) (sp_pos_range $1 $2)} -| LT term GT {sp_0($2); sp_0($3); to_Call_op("<>", [sndfst $2]) (sp_pos_range $1 $3)} +| LT GT {sp_0($2); to_Call_op "<>" [] $1 $2} +| LT term GT {sp_0($2); sp_0($3); to_Call_op "<>" [$2.any.expr] $1 $3}  subscripted: /* Some kind of subscripted expression */ -| variable PKG_SCOPE bracket_subscript {sp_0($2); sp_0($3); Call(Too_complex, [fst $3]), sp_pos_range $1 $3} /* $foo::{something} */ -| scalar bracket_subscript             {sp_0($2); check_scalar_subscripted $1; to_Deref_with(I_hash , I_scalar, from_scalar $1, fst                $2), sp_pos_range $1 $2} /* $foo{bar} */ -| scalar arrayref                      {sp_0($2); check_scalar_subscripted $1; to_Deref_with(I_array, I_scalar, from_scalar $1, only_one_array_ref $2), sp_pos_range $1 $2} /* $array[$element] */ -| term ARROW bracket_subscript         {sp_0($2); sp_0($3); check_arrow_needed $1 $2; to_Deref_with(I_hash , I_scalar, sndfst $1, fst                $3), sp_pos_range $1 $3} /* somehref->{bar} */ -| term ARROW arrayref                  {sp_0($2); sp_0($3); check_arrow_needed $1 $2; to_Deref_with(I_array, I_scalar, sndfst $1, only_one_array_ref $3), sp_pos_range $1 $3} /* somearef->[$element] */ -| term ARROW parenthesized             {sp_0($2); sp_0($3); to_Deref_with(I_func , I_scalar, sndfst $1, List(sndfst $3)), sp_pos_range $1 $3} /* $subref->(@args) */ -| subscripted bracket_subscript        {sp_0($2); to_Deref_with(I_hash , I_scalar, fst $1, fst                $2), sp_pos_range $1 $2} /* $foo->[bar]{baz} */ -| subscripted arrayref                 {sp_0($2); to_Deref_with(I_array, I_scalar, fst $1, only_one_array_ref $2), sp_pos_range $1 $2} /* $foo->[$bar][$baz] */ -| subscripted parenthesized            {sp_0($2); to_Deref_with(I_func , I_scalar, fst $1, List(sndfst $2)), sp_pos_range $1 $2} /* $foo->{bar}(@args) */ +| variable PKG_SCOPE bracket_subscript {sp_0($2); sp_0($3); new_esp (Call(Too_complex, [$3.any])) $1 $3} /* $foo::{something} */ +| scalar bracket_subscript             {sp_0($2); check_scalar_subscripted $1; new_esp (to_Deref_with(I_hash , I_scalar, from_scalar $1, $2.any               )) $1 $2} /* $foo{bar} */ +| scalar arrayref                      {sp_0($2); check_scalar_subscripted $1; new_esp (to_Deref_with(I_array, I_scalar, from_scalar $1, only_one_array_ref $2)) $1 $2} /* $array[$element] */ +| term ARROW bracket_subscript         {sp_0($2); sp_0($3); check_arrow_needed $1 $2; new_esp (to_Deref_with(I_hash , I_scalar, $1.any.expr, $3.any               )) $1 $3} /* somehref->{bar} */ +| term ARROW arrayref                  {sp_0($2); sp_0($3); check_arrow_needed $1 $2; new_esp (to_Deref_with(I_array, I_scalar, $1.any.expr, only_one_array_ref $3)) $1 $3} /* somearef->[$element] */ +| term ARROW parenthesized             {sp_0($2); sp_0($3); new_esp (to_Deref_with(I_func , I_scalar, $1.any.expr, List($3.any.expr))) $1 $3} /* $subref->(@args) */ +| subscripted bracket_subscript        {sp_0($2); new_esp (to_Deref_with(I_hash , I_scalar, $1.any, $2.any               )) $1 $2} /* $foo->[bar]{baz} */ +| subscripted arrayref                 {sp_0($2); new_esp (to_Deref_with(I_array, I_scalar, $1.any, only_one_array_ref $2)) $1 $2} /* $foo->[$bar][$baz] */ +| subscripted parenthesized            {sp_0($2); new_esp (to_Deref_with(I_func , I_scalar, $1.any, List($2.any.expr))) $1 $2} /* $foo->{bar}(@args) */  restricted_subscripted: /* Some kind of subscripted expression */ -| variable PKG_SCOPE bracket_subscript {sp_0($2); sp_0($3); Call(Too_complex, [fst $3]), sp_pos_range $1 $3} /* $foo::{something} */ -| scalar bracket_subscript             {sp_0($2); check_scalar_subscripted $1; to_Deref_with(I_hash , I_scalar, from_scalar $1, fst                $2), sp_pos_range $1 $2} /* $foo{bar} */ -| scalar arrayref                      {sp_0($2); check_scalar_subscripted $1; to_Deref_with(I_array, I_scalar, from_scalar $1, only_one_array_ref $2), sp_pos_range $1 $2} /* $array[$element] */ -| restricted_subscripted bracket_subscript        {sp_0($2); to_Deref_with(I_hash , I_scalar, fst $1, fst                $2), sp_pos_range $1 $2} /* $foo->[bar]{baz} */ -| restricted_subscripted arrayref                 {sp_0($2); to_Deref_with(I_array, I_scalar, fst $1, only_one_array_ref $2), sp_pos_range $1 $2} /* $foo->[$bar][$baz] */ -| restricted_subscripted parenthesized            {sp_0($2); to_Deref_with(I_func , I_scalar, fst $1, List(sndfst $2)), sp_pos_range $1 $2} /* $foo->{bar}(@args) */ +| variable PKG_SCOPE bracket_subscript {sp_0($2); sp_0($3); new_esp (Call(Too_complex, [$3.any])) $1 $3} /* $foo::{something} */ +| scalar bracket_subscript             {sp_0($2); check_scalar_subscripted $1; new_esp (to_Deref_with(I_hash , I_scalar, from_scalar $1, $2.any               )) $1 $2} /* $foo{bar} */ +| scalar arrayref                      {sp_0($2); check_scalar_subscripted $1; new_esp (to_Deref_with(I_array, I_scalar, from_scalar $1, only_one_array_ref $2)) $1 $2} /* $array[$element] */ +| restricted_subscripted bracket_subscript        {sp_0($2); new_esp (to_Deref_with(I_hash , I_scalar, $1.any, $2.any               )) $1 $2} /* $foo->[bar]{baz} */ +| restricted_subscripted arrayref                 {sp_0($2); new_esp (to_Deref_with(I_array, I_scalar, $1.any, only_one_array_ref $2)) $1 $2} /* $foo->[$bar][$baz] */ +| restricted_subscripted parenthesized            {sp_0($2); new_esp (to_Deref_with(I_func , I_scalar, $1.any, List($2.any.expr))) $1 $2} /* $foo->{bar}(@args) */  arrayref: -| arrayref_start ARRAYREF_END {sp_0($2); fst $1, sp_pos_range $1 $2} -| arrayref_start expr ARRAYREF_END {sp_0($3); fst $1 @ [sndfst $2], sp_pos_range $1 $3} -| arrayref_start BRACKET expr BRACKET_END ARRAYREF_END {sp_p($2); sp_p($4); sp_0($5); fst $1 @ [Ref(I_hash, sndfst $3)], sp_pos_range $1 $5} +| arrayref_start ARRAYREF_END {sp_0($2); new_esp $1.any $1 $2} +| arrayref_start expr ARRAYREF_END {sp_0($3); new_esp ($1.any @ [$2.any.expr]) $1 $3} +| arrayref_start BRACKET expr BRACKET_END ARRAYREF_END {sp_p($2); sp_p($4); sp_0($5); new_esp ($1.any @ [Ref(I_hash, $3.any.expr)]) $1 $5}  parenthesized: -| parenthesized_start PAREN_END {sp_0_or_cr($2); ((if fst $1 = [] then P_tok else P_paren P_comma), fst $1), sp_pos_range $1 $2} -| parenthesized_start expr PAREN_END {sp_0_or_cr($3); (P_paren(if fst $1 = [] then fstfst $2 else P_comma), fst $1 @ [(if fst $1 = [] then prio_lo P_loose else prio_lo_after P_comma) $2]), sp_pos_range $1 $3} -| parenthesized_start BRACKET expr BRACKET_END PAREN_END {sp_p($4); sp_0_or_cr($5); (P_paren(if fst $1 = [] then P_expr else P_comma), fst $1 @ [Ref(I_hash, sndfst $3)]), sp_pos_range $1 $5} +| parenthesized_start PAREN_END {sp_0_or_cr($2); new_pesp (if $1.any = [] then P_tok else P_paren P_comma) $1.any $1 $2} +| parenthesized_start expr PAREN_END {sp_0_or_cr($3); new_pesp (P_paren (if $1.any = [] then $2.any.priority else P_comma)) ($1.any @ [(if $1.any = [] then prio_lo P_loose else prio_lo_after P_comma) $2]) $1 $3} +| parenthesized_start BRACKET expr BRACKET_END PAREN_END {sp_p($4); sp_0_or_cr($5); new_pesp (P_paren (if $1.any = [] then P_expr else P_comma)) ($1.any @ [Ref(I_hash, $3.any.expr)]) $1 $5}  arrayref_start: -| ARRAYREF {[], snd $1} -| arrayref_start BRACKET expr BRACKET_END comma {sp_p($2); sp_p($3); sp_p($4); fst $1 @ [Ref(I_hash, sndfst $3)], sp_pos_range $1 $5} +| ARRAYREF {new_esp [] $1 $1} +| arrayref_start BRACKET expr BRACKET_END comma {sp_p($2); sp_p($3); sp_p($4); new_esp ($1.any @ [Ref(I_hash, $3.any.expr)]) $1 $5}  parenthesized_start: -| PAREN {[], snd $1} -| parenthesized_start BRACKET expr BRACKET_END comma {(if fst $1 = [] then sp_0_or_cr else sp_p)($2); sp_p($3); sp_p($4); fst $1 @ [Ref(I_hash, sndfst $3)], sp_pos_range $1 $5} +| PAREN {new_esp [] $1 $1} +| parenthesized_start BRACKET expr BRACKET_END comma {(if $1.any = [] then sp_0_or_cr else sp_p)($2); sp_p($3); sp_p($4); new_esp ($1.any @ [Ref(I_hash, $3.any.expr)]) $1 $5}  my_our: /* Things that can be "my"'d */ -| my_our_paren PAREN_END {sp_0($2); if sndfst $1 <> [] && fst (fstfst $1) then die_rule "syntax error";    My_our(snd (fstfst $1), sndfst $1, get_pos $1), sp_pos_range $1 $2} -| my_our_paren SCALAR_IDENT PAREN_END {(if sndfst $1 = [] then sp_0 else sp_1)($2); check_my_our_paren $1; My_our(snd (fstfst $1), sndfst $1 @ [I_scalar, sndfst $2], pos_range $1 $3), sp_pos_range $1 $3} -| my_our_paren HASH_IDENT   PAREN_END {(if sndfst $1 = [] then sp_0 else sp_1)($2); check_my_our_paren $1; My_our(snd (fstfst $1), sndfst $1 @ [I_hash,   sndfst $2], pos_range $1 $3), sp_pos_range $1 $3} -| my_our_paren ARRAY_IDENT  PAREN_END {(if sndfst $1 = [] then sp_0 else sp_1)($2); check_my_our_paren $1; My_our(snd (fstfst $1), sndfst $1 @ [I_array,  sndfst $2], pos_range $1 $3), sp_pos_range $1 $3} -| MY_OUR SCALAR_IDENT {My_our(fst $1, [I_scalar, sndfst $2], get_pos $2), sp_pos_range $1 $2} -| MY_OUR HASH_IDENT   {My_our(fst $1, [I_hash,   sndfst $2], get_pos $2), sp_pos_range $1 $2} -| MY_OUR ARRAY_IDENT  {My_our(fst $1, [I_array,  sndfst $2], get_pos $2), sp_pos_range $1 $2} +| my_our_paren     PAREN_END {sp_0($2); if snd $1.any <> [] && fstfst $1.any then die_rule "syntax error";       new_esp (My_our(sndfst $1.any, snd $1.any, get_pos $1)) $1 $2} +| my_our_paren SCALAR_IDENT PAREN_END {(if snd $1.any = [] then sp_0 else sp_1)($2); check_my_our_paren $1; new_esp (My_our(sndfst $1.any, snd $1.any @ [I_scalar, snd $2.any], pos_range $1 $3)) $1 $3} +| my_our_paren HASH_IDENT   PAREN_END {(if snd $1.any = [] then sp_0 else sp_1)($2); check_my_our_paren $1; new_esp (My_our(sndfst $1.any, snd $1.any @ [I_hash,   snd $2.any], pos_range $1 $3)) $1 $3} +| my_our_paren ARRAY_IDENT  PAREN_END {(if snd $1.any = [] then sp_0 else sp_1)($2); check_my_our_paren $1; new_esp (My_our(sndfst $1.any, snd $1.any @ [I_array,  snd $2.any], pos_range $1 $3)) $1 $3} +| MY_OUR SCALAR_IDENT {new_esp (My_our($1.any, [I_scalar, snd $2.any], get_pos $2)) $1 $2} +| MY_OUR HASH_IDENT   {new_esp (My_our($1.any, [I_hash,   snd $2.any], get_pos $2)) $1 $2} +| MY_OUR ARRAY_IDENT  {new_esp (My_our($1.any, [I_array,  snd $2.any], get_pos $2)) $1 $2}  my_our_paren: -| MY_OUR PAREN {sp_1($2); ((true, fst $1), []), sp_pos_range $1 $2} -| my_our_paren comma {if fst (fstfst $1) then die_rule "syntax error"; ((true, snd (fstfst $1)), sndfst $1), sp_pos_range $1 $2} -| my_our_paren BAREWORD {check_my_our_paren $1; if fst $2 <> "undef" then die_rule "scalar expected"; ((false, snd (fstfst $1)), sndfst $1 @ [I_raw, fst $2]), sp_pos_range $1 $2} -| my_our_paren SCALAR_IDENT {check_my_our_paren $1; ((false, snd (fstfst $1)), sndfst $1 @ [I_scalar, sndfst $2]), sp_pos_range $1 $2} -| my_our_paren HASH_IDENT   {check_my_our_paren $1; ((false, snd (fstfst $1)), sndfst $1 @ [I_hash,   sndfst $2]), sp_pos_range $1 $2} -| my_our_paren ARRAY_IDENT  {check_my_our_paren $1; ((false, snd (fstfst $1)), sndfst $1 @ [I_array,  sndfst $2]), sp_pos_range $1 $2} +| MY_OUR PAREN {sp_1($2); new_esp ((true, $1.any), []) $1 $2} +| my_our_paren comma {if fstfst $1.any then die_rule "syntax error"; new_esp ((true, sndfst $1.any), snd $1.any) $1 $2} +| my_our_paren BAREWORD {check_my_our_paren $1; if $2.any <> "undef" then die_rule "scalar expected"; new_esp ((false, sndfst $1.any), snd $1.any @ [I_raw, $2.any]) $1 $2} +| my_our_paren SCALAR_IDENT {check_my_our_paren $1; new_esp ((false, sndfst $1.any), snd $1.any @ [I_scalar, snd $2.any]) $1 $2} +| my_our_paren HASH_IDENT   {check_my_our_paren $1; new_esp ((false, sndfst $1.any), snd $1.any @ [I_hash,   snd $2.any]) $1 $2} +| my_our_paren ARRAY_IDENT  {check_my_our_paren $1; new_esp ((false, sndfst $1.any), snd $1.any @ [I_array,  snd $2.any]) $1 $2}  termdo: /* Things called with "do" */  | DO term %prec UNIOP { die_rule "\"do EXPR\" not allowed" } /* do $filename */ -| DO BRACKET lines BRACKET_END %prec PREC_HIGH {sp_n($2); check_block_sub $3 $4; Block(fst $3), sp_pos_range $1 $4} /* do { code */ +| DO BRACKET lines BRACKET_END %prec PREC_HIGH {sp_n($2); check_block_sub $3 $4; new_esp (Block $3.any) $1 $4} /* do { code */  bracket_subscript: -| BRACKET expr BRACKET_END {sp_0($1); sp_same $2 $3; check_hash_subscript $2; only_one_in_List $2, sp_pos_range $1 $3} -| COMPACT_HASH_SUBSCRIPT {sp_0($1); to_Raw_string $1, snd $1} +| BRACKET expr BRACKET_END {sp_0($1); sp_same $2 $3; check_hash_subscript $2; new_esp (only_one_in_List $2) $1 $3} +| COMPACT_HASH_SUBSCRIPT {sp_0($1); new_esp (to_Raw_string $1) $1 $1}  variable:  | scalar   %prec PREC_HIGH {$1} @@ -418,9 +419,9 @@ variable:  word:  | bareword { $1 } -| RAW_IDENT { to_Ident $1, snd $1} +| RAW_IDENT { new_esp (to_Ident $1) $1 $1} -comma: COMMA {true, snd $1} | RIGHT_ARROW {sp_p($1); false, snd $1} +comma: COMMA {new_esp true $1 $1} | RIGHT_ARROW {sp_p($1); new_esp false $1 $1}  semi_colon: SEMI_COLON {sp_0($1); $1} @@ -430,24 +431,24 @@ word_or_scalar:  | word_paren {$1}  bareword: -| NEW { Ident(None, "new", get_pos $1), snd $1} -| FORMAT { Ident(None, "format", get_pos $1), snd $1} -| BAREWORD { Ident(None, fst $1, get_pos $1), snd $1} +| NEW { new_esp (Ident(None, "new", get_pos $1)) $1 $1} +| FORMAT { new_esp (Ident(None, "format", get_pos $1)) $1 $1} +| BAREWORD { new_esp (Ident(None, $1.any, get_pos $1)) $1 $1}  word_paren: -| BAREWORD_PAREN { Ident(None, fst $1, get_pos $1), snd $1} -| RAW_IDENT_PAREN { to_Ident $1, snd $1} -| PO_COMMENT word_paren { po_comment($1); fst $2, sp_pos_range $1 $2 } +| BAREWORD_PAREN { new_esp (Ident(None, $1.any, get_pos $1)) $1 $1} +| RAW_IDENT_PAREN { new_esp (to_Ident $1) $1 $1} +| PO_COMMENT word_paren { po_comment($1); new_esp $2.any $1 $2 } -arraylen: ARRAYLEN_IDENT {deref_arraylen (to_Ident $1), snd $1} | ARRAYLEN  scalar {sp_0($2); deref_arraylen (fst $2), snd $1} | ARRAYLEN  bracket_subscript {deref_arraylen (fst $2), sp_pos_range $1 $2} -scalar:   SCALAR_IDENT   {Deref(I_scalar, to_Ident $1), snd $1} | DOLLAR    scalar {sp_0($2); Deref(I_scalar, fst $2), snd $1} | DOLLAR    bracket_subscript {deref_raw I_scalar (fst $2), sp_pos_range $1 $2} | DOLLAR BRACKET BRACKET expr BRACKET_END BRACKET_END {sp_0($2); sp_0($3); sp_p($5); sp_0($6); Deref(I_scalar, Ref(I_hash, sndfst $4)), sp_pos_range $1 $6} -func:     FUNC_IDENT     {Deref(I_func  , to_Ident $1), snd $1} | AMPERSAND scalar {sp_0($2); Deref(I_func  , fst $2), snd $1} | AMPERSAND bracket_subscript {deref_raw I_func   (fst $2), sp_pos_range $1 $2} -array:    ARRAY_IDENT    {Deref(I_array , to_Ident $1), snd $1} | AT        scalar {sp_0($2); Deref(I_array , fst $2), snd $1} | AT        bracket_subscript {deref_raw I_array  (fst $2), sp_pos_range $1 $2} -hash:     HASH_IDENT     {Deref(I_hash  , to_Ident $1), snd $1} | PERCENT   scalar {sp_0($2); Deref(I_hash  , fst $2), snd $1} | PERCENT   bracket_subscript {deref_raw I_hash   (fst $2), sp_pos_range $1 $2} -star:     STAR_IDENT     {Deref(I_star  , to_Ident $1), snd $1} | STAR      scalar {sp_0($2); Deref(I_star  , fst $2), snd $1} | STAR      bracket_subscript {deref_raw I_star   (fst $2), sp_pos_range $1 $2} +arraylen: ARRAYLEN_IDENT {new_esp (deref_arraylen (to_Ident $1)) $1 $1} | ARRAYLEN  scalar {sp_0($2); new_esp (deref_arraylen  $2.any ) $1 $1} | ARRAYLEN  bracket_subscript {new_esp (deref_arraylen      $2.any) $1 $2} +scalar:   SCALAR_IDENT   {new_esp (Deref(I_scalar, to_Ident $1)) $1 $1} | DOLLAR    scalar {sp_0($2); new_esp (Deref(I_scalar, $2.any)) $1 $1} | DOLLAR    bracket_subscript {new_esp (deref_raw I_scalar  $2.any) $1 $2} | DOLLAR BRACKET BRACKET expr BRACKET_END BRACKET_END {sp_0($2); sp_0($3); sp_p($5); sp_0($6); new_esp (Deref(I_scalar, Ref(I_hash, $4.any.expr))) $1 $6} +func:     FUNC_IDENT     {new_esp (Deref(I_func  , to_Ident $1)) $1 $1} | AMPERSAND scalar {sp_0($2); new_esp (Deref(I_func  , $2.any)) $1 $1} | AMPERSAND bracket_subscript {new_esp (deref_raw I_func    $2.any) $1 $2} +array:    ARRAY_IDENT    {new_esp (Deref(I_array , to_Ident $1)) $1 $1} | AT        scalar {sp_0($2); new_esp (Deref(I_array , $2.any)) $1 $1} | AT        bracket_subscript {new_esp (deref_raw I_array   $2.any) $1 $2} +hash:     HASH_IDENT     {new_esp (Deref(I_hash  , to_Ident $1)) $1 $1} | PERCENT   scalar {sp_0($2); new_esp (Deref(I_hash  , $2.any)) $1 $1} | PERCENT   bracket_subscript {new_esp (deref_raw I_hash    $2.any) $1 $2} +star:     STAR_IDENT     {new_esp (Deref(I_star  , to_Ident $1)) $1 $1} | STAR      scalar {sp_0($2); new_esp (Deref(I_star  , $2.any)) $1 $1} | STAR      bracket_subscript {new_esp (deref_raw I_star    $2.any) $1 $2} -expr_or_empty: {Block [], (Space_none, bpos)} | expr {sndfst $1, snd $1} +expr_or_empty: {default_esp (Block [])} | expr {new_esp $1.any.expr $1 $1}  %% diff --git a/perl_checker.src/parser_helper.ml b/perl_checker.src/parser_helper.ml index 696a36e..2a1bce2 100644 --- a/perl_checker.src/parser_helper.ml +++ b/perl_checker.src/parser_helper.ml @@ -5,12 +5,20 @@ open Printf  let bpos = -1, -1  let raw_pos2pos(a, b) = !Info.current_file, a, b -let pos_range (_, (_, (a1, b1))) (_, (_, (a2, b2))) = raw_pos2pos((if a1 = -1 then a2 else a1), (if b2 = -1 then b1 else b2)) -let sp_pos_range (_, (space, (a1, b1))) (_, (_, (a2, b2))) = space, ((if a1 = -1 then a2 else a1), (if b2 = -1 then b1 else b2)) -let get_pos (_, (_, pos)) = raw_pos2pos pos +let raw_pos_range { pos = (a1, b1) } { pos = (a2, b2) } = (if a1 = -1 then a2 else a1), (if b2 = -1 then b1 else b2) +let pos_range esp1 esp2 = raw_pos2pos (raw_pos_range esp1 esp2) +let get_pos pesp = raw_pos2pos pesp.pos +let get_pos_start { pos = (start, _) } = start +let get_pos_end { pos = (_, end_) } = end_  let var_dollar_ pos = Deref(I_scalar, Ident(None, "_", pos))  let var_STDOUT = Deref(I_star, Ident(None, "STDOUT", raw_pos2pos bpos)) +let new_any any spaces pos = { any = any ; spaces = spaces ; pos = pos } +let new_esp e esp_start esp_end = new_any e esp_start.spaces (raw_pos_range esp_start esp_end) +let new_pesp prio e esp_start esp_end = new_any { priority = prio ; expr = e } esp_start.spaces (raw_pos_range esp_start esp_end) +let default_esp e = new_any e Space_none bpos +let default_pesp prio e = new_any { priority = prio ; expr = e } Space_none bpos +  let split_name_or_fq_name full_ident =    match split_at2 ':'':' full_ident with    | [] -> internal_error "split_ident" @@ -138,13 +146,13 @@ let rec is_same_fromparser a b =    | _ -> false -let from_scalar (e, _) = -  match e with +let from_scalar esp = +  match esp.any with    | Deref(I_scalar, ident) -> ident    | _ -> internal_error "from_scalar" -let from_array (e, _) = -  match e with +let from_array esp = +  match esp.any with    | Deref(I_array, ident) -> ident    | _ -> internal_error "from_array" @@ -163,6 +171,8 @@ let warn_cr		start = warn_verb start "you should not have a carriage-return (\\n  let warn_space		start = warn_verb start "you should not have a space here"  let rec prio_less = function +  | P_none, _ | _, P_none -> internal_error "prio_less" +    | P_paren_wanted prio1, prio2    | prio1, P_paren_wanted prio2 -> prio_less(prio1, prio2) @@ -211,76 +221,76 @@ let rec prio_less = function    | P_paren _, _ -> true    | P_tok, _ -> true -let prio_lo pri_out ((pri_in, e), (_, pos)) = -  if prio_less(pri_in, pri_out) then -    (match pri_in with +let prio_lo pri_out in_ = +  if prio_less(in_.any.priority, pri_out) then +    (match in_.any.priority with      | P_paren (P_paren_wanted _) -> ()      | P_paren pri_in' ->  	if pri_in' <> pri_out &&  -	   prio_less(pri_in', pri_out) && not_complex (un_parenthesize e) then  -	  warn pos "unneeded parentheses" +	   prio_less(pri_in', pri_out) && not_complex (un_parenthesize in_.any.expr) then  +	  warn in_.pos "unneeded parentheses"      | _ -> ()) -  else warn pos "missing parentheses (needed for clarity)" ; -  e +  else warn in_.pos "missing parentheses (needed for clarity)" ; +  in_.any.expr -let prio_lo_after pri_out ((pri_in, e), _ as para) = -  if pri_in = P_call_no_paren then e else prio_lo pri_out para +let prio_lo_after pri_out in_ = +  if in_.any.priority = P_call_no_paren then in_.any.expr else prio_lo pri_out in_ -let prio_lo_concat ((pri_in, e), both) = prio_lo P_mul ((P_paren_wanted pri_in, e), both) +let prio_lo_concat esp = prio_lo P_mul { esp with any = { esp.any with priority = P_paren_wanted esp.any.priority } } -let sp_0(_, (spaces, (start, _))) = -  match spaces with +let sp_0 esp = +  match esp.spaces with    | Space_none -> ()    | Space_0 -> ()    | Space_1 -  | Space_n -> warn_space start -  | Space_cr -> warn_cr start +  | Space_n -> warn_space (get_pos_start esp) +  | Space_cr -> warn_cr (get_pos_start esp) -let sp_0_or_cr(_, (spaces, (start, _))) = -  match spaces with +let sp_0_or_cr esp = +  match esp.spaces with    | Space_none -> ()    | Space_0 -> ()    | Space_1 -  | Space_n -> warn_space start +  | Space_n -> warn_space (get_pos_start esp)    | Space_cr -> () -let sp_1(_, (spaces, (start, _))) = -  match spaces with +let sp_1 esp = +  match esp.spaces with    | Space_none -> () -  | Space_0 -> warn_no_space start +  | Space_0 -> warn_no_space (get_pos_start esp)    | Space_1 -> () -  | Space_n -> warn_too_many_space start -  | Space_cr -> warn_cr start +  | Space_n -> warn_too_many_space (get_pos_start esp) +  | Space_cr -> warn_cr (get_pos_start esp) -let sp_n(_, (spaces, (start, _))) = -  match spaces with +let sp_n esp = +  match esp.spaces with    | Space_none -> () -  | Space_0 -> warn_no_space start +  | Space_0 -> warn_no_space (get_pos_start esp)    | Space_1 -> ()    | Space_n -> () -  | Space_cr -> warn_cr start +  | Space_cr -> warn_cr (get_pos_start esp) -let sp_p(_, (spaces, (start, _))) = -  match spaces with +let sp_p esp = +  match esp.spaces with    | Space_none -> () -  | Space_0 -> warn_no_space start +  | Space_0 -> warn_no_space (get_pos_start esp)    | Space_1 -> ()    | Space_n -> ()    | Space_cr -> () -let sp_cr(_, (spaces, (start, _))) = -  match spaces with +let sp_cr esp = +  match esp.spaces with    | Space_none -> ()    | Space_0    | Space_1 -  | Space_n -> warn_verb start "you should have a carriage-return (\\n) here" +  | Space_n -> warn_verb (get_pos_start esp) "you should have a carriage-return (\\n) here"    | Space_cr -> () -let sp_same (_, (spaces1, _) as ter1) (_, (spaces2, _) as ter2) = -  if spaces1 <> Space_0 then sp_p ter2 -  else if spaces2 <> Space_0 then sp_p ter1 +let sp_same esp1 esp2 = +  if esp1.spaces <> Space_0 then sp_p esp2 +  else if esp2.spaces <> Space_0 then sp_p esp1 -let check_word_alone (word, _) = +let check_word_alone word =    match word with    | Ident(None, f, pos) ->        (match f with @@ -303,60 +313,60 @@ let check_word_alone (word, _) =        | _ -> word)    | _ -> word -let check_parenthesized_first_argexpr word ((_, e), (_, (start, _)) as ex) = +let check_parenthesized_first_argexpr word esp =    let want_space = word.[0] = '-' in    if word = "return" then () else -  match e with +  match esp.any.expr with    | [ Call_op(_, (e' :: l), _) ]    | e' :: l ->        if is_parenthesized e' then  	if l = [] then  -	  (if want_space then sp_n else sp_0) ex +	  (if want_space then sp_n else sp_0) esp  	else   	  (* eg: join (" ", @l) . "\n" *) -	  die_with_rawpos (start, start) "please remove the space before the function call" +	  die_with_rawpos (get_pos_start esp, get_pos_start esp) "please remove the space before the function call"        else -	sp_p(ex) +	sp_p esp    | _ ->         if word = "time" then die_rule "please use time() instead of time"; -      sp_p(ex) +      sp_p esp -let check_parenthesized_first_argexpr_with_Ident ident ((prio, e), _ as ex) = -  if prio = P_tok then (); +let check_parenthesized_first_argexpr_with_Ident ident esp = +  if esp.any.priority = P_tok then ();    (match ident with    | Ident(Some _, _, _) -> -      (match e with +      (match esp.any.expr with        | [e] when is_parenthesized e -> ()        | _ -> warn_rule "use parentheses around argument (otherwise it might cause syntax errors if the package is \"require\"d and not \"use\"d")    | Ident(None, word, _) when List.mem word ["ref" ; "readlink"] -> -      if prio <> P_tok then warn_rule "use parentheses around argument" +      if esp.any.priority <> P_tok then warn_rule "use parentheses around argument"    | _ -> ()); -  check_parenthesized_first_argexpr (string_of_Ident ident) ex +  check_parenthesized_first_argexpr (string_of_Ident ident) esp -let check_hash_subscript ((_, e), (_, pos)) = +let check_hash_subscript esp =    let can_be_raw_string = function      | "" | "x" | "y" -> false (* special case for {'y'} otherwise the emacs mode goes wild, special case for {'x'} to have the same as {'y'} (since they usually go together) *)      | s ->   	char_is_alpha s.[0] && (String.length s = 1 || string_forall_with char_is_alphanumerical_ 1 s)    in -  match e with -  | List [String ([(s, List [])], _)] when can_be_raw_string s -> warn pos (sprintf "{\"%s\"} can be written {%s}" s s) -  | List [Raw_string(s, _)] when can_be_raw_string s -> warn pos (sprintf "{'%s'} can be written {%s}" s s) +  match esp.any.expr with +  | List [String ([(s, List [])], _)] when can_be_raw_string s -> warn esp.pos (sprintf "{\"%s\"} can be written {%s}" s s) +  | List [Raw_string(s, _)] when can_be_raw_string s -> warn esp.pos (sprintf "{'%s'} can be written {%s}" s s)    | _ -> () -let check_arrow_needed ((_, e), _) ter = -  match e with +let check_arrow_needed esp1 esp2 = +  match esp1.any.expr with    | Deref_with(I_array, I_scalar, List [List [Call _]], _) -> () (* "->" needed for (f())[0]->{XX} *) -  | Deref_with _ -> warn (sndsnd ter) "the arrow \"->\" is unneeded" +  | Deref_with _ -> warn esp2.pos "the arrow \"->\" is unneeded"    | _ -> () -let check_scalar_subscripted (e, _) = -  match e with +let check_scalar_subscripted esp = +  match esp.any with    | Deref(I_scalar, Deref _) -> warn_rule "for complex dereferencing, use \"->\""    | _ -> () -let check_negatable_expr ((_, e), _) = -  match un_parenthesize_full e with +let check_negatable_expr esp = +  match un_parenthesize_full esp.any.expr with    | Call_op("m//", var :: _, _) when not (is_var_dollar_ var) ->        warn_rule "!($var =~ /.../) is better written $var !~ /.../"    | Call_op("!m//", var :: _, _) when not (is_var_dollar_ var) -> @@ -392,49 +402,50 @@ let check_ternary_paras(cond, a, b) =    if is_same_fromparser cond a && dont_need_short_circuit b && is_a_scalar a && is_a_scalar b then warn_rule "you can replace \"$foo ? $foo : $bar\" with \"$foo || $bar\"";    [ cond; a; b ] -let check_unneeded_var_dollar_    ((_, e), (_, pos)) = -  if is_var_dollar_ e then warn pos "\"$_ =~ /regexp/\" can be written \"/regexp/\"" else -  if is_var_number_match e then warn pos "do not use the result of a match (eg: $1) to match another pattern" -let check_unneeded_var_dollar_not ((_, e), (_, pos)) = -  if is_var_dollar_ e then warn pos "\"$_ !~ /regexp/\" can be written \"!/regexp/\"" else -  if is_var_number_match e then warn pos "do not use the result of a match (eg: $1) to match another pattern" -let check_unneeded_var_dollar_s   ((_, e), (_, pos)) =  -  if is_var_dollar_ e then warn pos "\"$_ =~ s/regexp/.../\" can be written \"s/regexp/.../\"" else -  if is_var_number_match e then die_with_rawpos pos "do not modify the result of a match (eg: $1)" - -let check_MULT_is_x (s, _) = if s <> "x" then die_rule "syntax error" -let check_my (s, _) = if s <> "my" then die_rule "syntax error" -let check_foreach (s, (_, pos)) = if s = "for"     then warn pos "write \"foreach\" instead of \"for\"" -let check_for     (s, (_, pos)) = if s = "foreach" then warn pos "write \"for\" instead of \"foreach\"" -let check_for_foreach (s, (_, pos)) ((_, expr), _) = -  match expr with +let check_unneeded_var_dollar_ esp = +  if is_var_dollar_ esp.any.expr then warn esp.pos "\"$_ =~ /regexp/\" can be written \"/regexp/\"" else +  if is_var_number_match esp.any.expr then warn esp.pos "do not use the result of a match (eg: $1) to match another pattern" +let check_unneeded_var_dollar_not esp = +  if is_var_dollar_ esp.any.expr then warn esp.pos "\"$_ !~ /regexp/\" can be written \"!/regexp/\"" else +  if is_var_number_match esp.any.expr then warn esp.pos "do not use the result of a match (eg: $1) to match another pattern" +let check_unneeded_var_dollar_s esp =  +  if is_var_dollar_ esp.any.expr then warn esp.pos "\"$_ =~ s/regexp/.../\" can be written \"s/regexp/.../\"" else +  if is_var_number_match esp.any.expr then die_with_rawpos esp.pos "do not modify the result of a match (eg: $1)" + +let check_MULT_is_x esp = if esp.any <> "x" then die_rule "syntax error" +let check_my esp = if esp.any <> "my" then die_rule "syntax error" +let check_foreach esp = if esp.any = "for"     then warn esp.pos "write \"foreach\" instead of \"for\"" +let check_for     esp = if esp.any = "foreach" then warn esp.pos "write \"for\" instead of \"foreach\"" +let check_for_foreach esp arg = +  match arg.any.expr with    | List [ Deref(I_scalar, _) ] -> -      if s = "foreach" then warn pos "you are using the special fpons trick to locally set $_ with a value, for this please use \"for\" instead of \"foreach\"" +      if esp.any = "foreach" then warn esp.pos "you are using the special fpons trick to locally set $_ with a value, for this please use \"for\" instead of \"foreach\""    | List [ Deref_with(context, I_scalar, _, _) ] when context <> I_func ->  -      if s = "foreach" then warn pos "you are using the special fpons trick to locally set $_ with a value, for this please use \"for\" instead of \"foreach\"" +      if esp.any = "foreach" then warn esp.pos "you are using the special fpons trick to locally set $_ with a value, for this please use \"for\" instead of \"foreach\""    | _ ->  -      if s = "for" then warn pos "write \"foreach\" instead of \"for\"" +      if esp.any = "for" then warn esp.pos "write \"foreach\" instead of \"for\"" -let check_block_sub (l, (_, (_, end_)) as ter_lines) (_, (space, _) as ter_BRACKET_END) =   -  if l = [] then -    sp_0_or_cr ter_BRACKET_END -  else ( -    (if l <> [] && List.hd l = Semi_colon then sp_0 else sp_p) ter_lines ; -    sp_p ter_BRACKET_END ; +let check_block_sub esp_lines esp_BRACKET_END = +  match esp_lines.any with +  | [] ->  +      sp_0_or_cr esp_BRACKET_END +  | l -> +      (if List.hd l = Semi_colon then sp_0 else sp_p) esp_lines ; +      sp_p esp_BRACKET_END ; -    if space <> Space_cr then -      (if l <> [] && last l = Semi_colon then warn_verb end_ "spurious \";\" before closing block") -  ) +      if esp_BRACKET_END.spaces <> Space_cr then +	(if last l = Semi_colon then warn_verb (get_pos_end esp_lines) "spurious \";\" before closing block") -let check_block_ref (l, (_, (_, end_)) as ter_lines) (_, (space, _) as ter_BRACKET_END) = +let check_block_ref esp_lines esp_BRACKET_END = +  let l = esp_lines.any in    if l <> [] && List.hd l = Semi_colon  -  then (sp_0 ter_lines ; sp_p ter_BRACKET_END) -  else sp_same ter_lines ter_BRACKET_END ; +  then (sp_0 esp_lines ; sp_p esp_BRACKET_END) +  else sp_same esp_lines esp_BRACKET_END ; -  if space <> Space_cr then -    (if l <> [] && last l = Semi_colon then warn_verb end_ "spurious \";\" before closing block") +  if esp_BRACKET_END.spaces <> Space_cr then +    (if l <> [] && last l = Semi_colon then warn_verb (get_pos_end esp_lines) "spurious \";\" before closing block") -let check_my_our_paren (((comma_closed, _), _), _) =  +let check_my_our_paren { any = ((comma_closed, _), _) } =     if not comma_closed then die_rule "syntax error"  let check_simple_pattern = function @@ -446,25 +457,25 @@ let check_simple_pattern = function  	  warn_rule (sprintf "\"... =~ /^%s$/\" is better written \"... eq '%s'\"" st st)    | _ -> () -let rec only_one (l, (spaces, pos)) = -  match l with -  | [List l'] -> only_one (l', (spaces, pos)) +let rec only_one esp = +  match esp.any with +  | [List l'] -> only_one { esp with any = l' }    | [e] -> e -  | [] -> die_with_rawpos pos "you must give one argument" -  | _  -> die_with_rawpos pos "you must give only one argument" +  | [] -> die_with_rawpos esp.pos "you must give one argument" +  | _  -> die_with_rawpos esp.pos "you must give only one argument" -let only_one_array_ref (l, (spaces, pos)) = -  let e = only_one (l, (spaces, pos)) in +let only_one_array_ref esp = +  let e = only_one esp in    (match e with    | Call_op("last_array_index", [Deref(I_array, e)], _) -> -      warn pos (sprintf "you can replace $#%s with -1" (string_of_Ident e)) +      warn esp.pos (sprintf "you can replace $#%s with -1" (string_of_Ident e))    | _ -> ());    e -let only_one_in_List ((_, e), both) = -  match e with -  | List l -> only_one(l, both) -  | _ -> e +let only_one_in_List esp = +  match esp.any.expr with +  | List l -> only_one { esp with any = l } +  | e -> e  let rec is_only_one_in_List = function    | [List l] -> is_only_one_in_List l @@ -492,8 +503,8 @@ let deref_raw context e =    | _ -> e    in Deref(context, e) -let to_Ident ((fq, name), (_, pos)) = Ident(fq, name, raw_pos2pos pos) -let to_Raw_string (s, (_, pos)) = Raw_string(s, raw_pos2pos pos) +let to_Ident { any = (fq, name); pos = pos } = Ident(fq, name, raw_pos2pos pos) +let to_Raw_string { any = s; pos = pos } = Raw_string(s, raw_pos2pos pos)  let to_Method_call (object_, method_, para) =     match method_ with    | Ident(Some "SUPER", name, pos) -> Method_call(maybe_to_Raw_string object_, Raw_string(name, pos), para) @@ -504,11 +515,11 @@ let to_Deref_with(from_context, to_context, ref_, para) =    Deref_with(from_context, to_context, ref_, para) -let to_Local ((_, e), (_, pos)) = +let to_Local esp =    let l =  -    match e with +    match esp.any.expr with      | List[List l] -> l -    | _ -> [e] +    | e -> [e]    in    let local_vars, local_exprs = fpartition (function      | Deref(I_star as context, Ident(None, ident, _)) @@ -522,19 +533,35 @@ let to_Local ((_, e), (_, pos)) =      | Deref_with(I_hash, I_scalar, Deref_with(I_hash, I_scalar, Ident _, _), _)      | Deref_with(I_hash, I_scalar, Deref_with(I_hash, I_scalar, Deref(I_scalar, Ident _), _), _) ->  	None -    | _ -> die_with_rawpos pos "bad argument to \"local\"" +    | _ -> die_with_rawpos esp.pos "bad argument to \"local\""    ) l in -  if local_vars = [] then Call_op("local", local_exprs, raw_pos2pos pos) -  else if local_exprs = [] then My_our("local", local_vars, raw_pos2pos pos) -  else die_with_rawpos pos "bad argument to \"local\"" - -let op prio s (_, both) = prio, (((), both), s) -let op_p prio s e = sp_p e ; op prio s e +  if local_vars = [] then Call_op("local", local_exprs, raw_pos2pos esp.pos) +  else if local_exprs = [] then My_our("local", local_vars, raw_pos2pos esp.pos) +  else die_with_rawpos esp.pos "bad argument to \"local\""  let sub_declaration (name, proto) body = Sub_declaration(name, proto, Block body) -let anonymous_sub (body, (_, pos)) = Anonymous_sub (Block body, raw_pos2pos pos) +let anonymous_sub body = Anonymous_sub (Block body.any, raw_pos2pos body.pos) -let cook_call_op(op, para, pos) = +let cook_call_op op para pos = +  (match op with +  | "==" | "!=" | "<=" | ">=" | ">"  | "<"  | "<=>" -> +      if List.exists (function  +	| Undef +	| List [] -> op <> "==" && op <> "!=" (* allowing @l == () *) +	| e -> is_not_a_scalar_or_array e) para then +	warn_rule "don't do this" +      else if List.exists is_a_string para then +	warn_rule (sprintf "you should use a string operator, not the number operator \"%s\"" op) +  | "le" | "ge" | "eq" | "ne" | "gt" | "lt" | "cmp" -> +      if List.exists is_not_a_scalar para then +	warn_rule "don't do this" +      else if List.exists (function Num _ -> true | _ -> false) para then +	warn_rule (sprintf "you should use a number operator, not the string operator \"%s\" (or replace the number with a string)" op) +  | "||=" | "&&=" -> +      (match List.hd para with +      | List [ List _ ] -> warn_rule "remove the parentheses" +      | e -> if is_not_a_scalar e then warn_rule (sprintf "\"%s\" is only useful with a scalar" op)) +  | _ -> ());    let call = Call_op(op, para, raw_pos2pos pos) in    match op, para with    | "=", [My_our _; Ident(None, "undef", _)] ->  @@ -573,43 +600,24 @@ let cook_call_op(op, para, pos) =    | _ ->         call -let call_op_((prio, (prev_ter, op)), ter, para) (sp, pos) =  -  (match op with -  | "==" | "!=" | "<=" | ">=" | ">"  | "<"  | "<=>" -> -      if List.exists (function  -	| Undef -	| List [] -> op <> "==" && op <> "!=" (* allowing @l == () *) -	| e -> is_not_a_scalar_or_array e) para then -	warn_rule "don't do this" -      else if List.exists is_a_string para then -	warn_rule (sprintf "you should use a string operator, not the number operator \"%s\"" op) -  | "le" | "ge" | "eq" | "ne" | "gt" | "lt" | "cmp" -> -      if List.exists is_not_a_scalar para then -	warn_rule "don't do this" -      else if List.exists (function Num _ -> true | _ -> false) para then -	warn_rule (sprintf "you should use a number operator, not the string operator \"%s\" (or replace the number with a string)" op) -  | "||=" | "&&=" -> -      (match List.hd para with -      | List [ List _ ] -> warn_rule "remove the parentheses" -      | e -> if is_not_a_scalar e then warn_rule (sprintf "\"%s\" is only useful with a scalar" op)) -  | _ -> ()); -  sp_same prev_ter ter ; -  (prio, cook_call_op(op, para, pos)), (sp, pos) - -let to_Call_op(op, para) (sp, pos) = Call_op(op, para, raw_pos2pos pos), (sp, pos) -let to_Call_op_(prio, op, para) (sp, pos) = (prio, Call_op(op, para, raw_pos2pos pos)), (sp, pos) +let to_Call_op op para esp_start esp_end =  +  let pos = raw_pos_range esp_start esp_end in +  new_any (cook_call_op op para pos) esp_start.spaces pos +let to_Call_op_ prio op para esp_start esp_end =  +  let pos = raw_pos_range esp_start esp_end in +  new_any { priority = prio ; expr = cook_call_op op para pos } esp_start.spaces pos -let followed_by_comma ((_,e), _) (true_comma, _) = -  if true_comma then e else -    match split_last e with +let followed_by_comma pesp true_comma = +  if true_comma.any then pesp.any.expr else +    match split_last pesp.any.expr with      | l, Ident(None, s, pos) -> l @ [Raw_string(s, pos)] -    | _ -> e +    | _ -> pesp.any.expr  let pot_strings = Hashtbl.create 16  let pot_strings_and_file = Hashtbl.create 16  let po_comments = ref [] -let po_comment (s, _) = lpush po_comments s +let po_comment esp = lpush po_comments esp.any  let check_format_a_la_printf s pos =    let rec check_format_a_la_printf_ i = @@ -733,7 +741,7 @@ let call_func is_a_func (e, para) =  let call(e, para) = call_func false (e, para) -let call_one_scalar_para (e, (_, pos)) para = +let call_one_scalar_para { any = e ; pos = pos } para esp_start esp_end =    let para =      match para with      | [] -> @@ -741,19 +749,20 @@ let call_one_scalar_para (e, (_, pos)) para =  	  [var_dollar_ (raw_pos2pos pos)]      | _ -> para    in -  P_mul, call(Deref(I_func, Ident(None, e, raw_pos2pos pos)), para) +  new_pesp P_mul (call(Deref(I_func, Ident(None, e, raw_pos2pos pos)), para)) esp_start esp_end -let call_op_if_infix left right (sp, pos) = +let call_op_if_infix left right esp_start esp_end =    (match left, right with    | List [Call_op("=", [Deref(context, _); _], _)], _ when non_scalar_context context -> ()    | List [Call_op("=", [v; _], _)],      List [Call_op("not", [v'], _)] when is_same_fromparser v v' ->        warn_rule "\"$foo = ... if !$foo\" can be written \"$foo ||= ...\""    | _ -> ()); -  Call_op("if infix", [ left ; right], raw_pos2pos pos), (sp, pos) +  let pos = raw_pos_range esp_start esp_end in +  new_any (Call_op("if infix", [ left ; right], raw_pos2pos pos)) esp_start.spaces pos -let call_op_unless_infix left right (sp, pos) = +let call_op_unless_infix left right esp_start esp_end =    (match left, right with    | List [Call_op("=", [Deref(context, _); _], _)], _ when non_scalar_context context -> ()    | List [Call_op("=", [v; _], _)], List [v'] when is_same_fromparser v v' -> @@ -765,7 +774,8 @@ let call_op_unless_infix left right (sp, pos) =        | "&&" | "||" | "not" | "ne" | "?:" -> warn_rule "don't use \"unless\" when the condition is complex, use \"if\" instead"        | _ -> ());    | _ -> ()); -  Call_op("unless infix", [ left ; right], raw_pos2pos pos), (sp, pos) +  let pos = raw_pos_range esp_start esp_end in +  new_any (Call_op("unless infix", [ left ; right], raw_pos2pos pos)) esp_start.spaces pos  let (current_lexbuf : Lexing.lexbuf option ref) = ref None @@ -792,7 +802,7 @@ let parse_interpolated parse l =    | pl, ("", List []) -> pl    | _ -> l' -let to_String parse strict (l, (_, pos)) =  +let to_String parse strict { any = l ; pos = pos } =     let l' = parse_interpolated parse l in    (match l' with    | [ "", List [Deref(I_scalar, Ident(None, ident, _))]] ->  @@ -806,7 +816,7 @@ let to_String parse strict (l, (_, pos)) =    | _ -> ());    String(l', raw_pos2pos pos) -let from_PATTERN parse ((s, opts), (_, pos)) =  +let from_PATTERN parse { any = (s, opts) ; pos = pos } =     let re = parse_interpolated parse s in    (match List.rev re with    | (s, List []) :: _ -> @@ -817,7 +827,7 @@ let from_PATTERN parse ((s, opts), (_, pos)) =    | _ -> ());    [ String(re, raw_pos2pos pos) ;       Raw_string(opts, raw_pos2pos pos) ] -let from_PATTERN_SUBST parse ((s1, s2, opts), (_, pos)) =  +let from_PATTERN_SUBST parse { any = (s1, s2, opts) ; pos = pos } =     [ String(parse_interpolated parse s1, raw_pos2pos pos) ;       String(parse_interpolated parse s2, raw_pos2pos pos) ;       Raw_string(opts, raw_pos2pos pos) ] diff --git a/perl_checker.src/parser_helper.mli b/perl_checker.src/parser_helper.mli index 82bd947..7d8f7a3 100644 --- a/perl_checker.src/parser_helper.mli +++ b/perl_checker.src/parser_helper.mli @@ -1,19 +1,36 @@  val bpos : int * int  val raw_pos2pos : 'a * 'b -> string * 'a * 'b +val raw_pos_range : +  'a Types.any_spaces_pos -> 'b Types.any_spaces_pos -> int * int  val pos_range : -  'a * ('b * (int * int)) -> 'c * ('d * (int * int)) -> string * int * int -val sp_pos_range : -  'a * ('b * (int * int)) -> 'c * ('d * (int * int)) -> 'b * (int * int) -val get_pos : 'a * ('b * ('c * 'd)) -> string * 'c * 'd +  'a Types.any_spaces_pos -> 'b Types.any_spaces_pos -> string * int * int +val get_pos : 'a Types.any_spaces_pos -> string * int * int +val get_pos_start : 'a Types.any_spaces_pos -> int +val get_pos_end : 'a Types.any_spaces_pos -> int  val var_dollar_ : Types.pos -> Types.fromparser  val var_STDOUT : Types.fromparser +val new_any : 'a -> Types.spaces -> int * int -> 'a Types.any_spaces_pos +val new_esp : +  'a -> +  'b Types.any_spaces_pos -> +  'c Types.any_spaces_pos -> 'a Types.any_spaces_pos +val new_pesp : +  Types.priority -> +  'a -> +  'b Types.any_spaces_pos -> +  'c Types.any_spaces_pos -> 'a Types.prio_anyexpr Types.any_spaces_pos +val default_esp : 'a -> 'a Types.any_spaces_pos +val default_pesp : +  Types.priority -> 'a -> 'a Types.prio_anyexpr Types.any_spaces_pos  val split_name_or_fq_name : string -> string option * string  val is_var_dollar_ : Types.fromparser -> bool  val is_var_number_match : Types.fromparser -> bool  val non_scalar_context : Types.context -> bool  val is_scalar_context : Types.context -> bool  val is_not_a_scalar : Types.fromparser -> bool +val is_not_a_scalar_or_array : Types.fromparser -> bool  val is_a_scalar : Types.fromparser -> bool +val is_a_string : Types.fromparser -> bool  val is_parenthesized : Types.fromparser -> bool  val un_parenthesize : Types.fromparser -> Types.fromparser  val un_parenthesize_full : Types.fromparser -> Types.fromparser @@ -25,8 +42,8 @@ val string_of_Ident : Types.fromparser -> string  val context2s : Types.context -> string  val variable2s : Types.context * string -> string  val is_same_fromparser : Types.fromparser -> Types.fromparser -> bool -val from_scalar : Types.fromparser * 'a -> Types.fromparser -val from_array : Types.fromparser * 'a -> Types.fromparser +val from_scalar : Types.fromparser Types.any_spaces_pos -> Types.fromparser +val from_array : Types.fromparser Types.any_spaces_pos -> Types.fromparser  val msg_with_rawpos : int * int -> string -> string  val die_with_rawpos : int * int -> string -> 'a  val warn : int * int -> string -> unit @@ -41,74 +58,75 @@ val warn_space : int -> unit  val prio_less : Types.priority * Types.priority -> bool  val prio_lo :    Types.priority -> -  (Types.priority * Types.fromparser) * ('a * (int * int)) -> +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos ->    Types.fromparser  val prio_lo_after :    Types.priority -> -  (Types.priority * Types.fromparser) * ('a * (int * int)) -> +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos ->    Types.fromparser  val prio_lo_concat : -  (Types.priority * Types.fromparser) * ('a * (int * int)) -> +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos ->    Types.fromparser -val sp_0 : 'a * (Types.spaces * (int * 'b)) -> unit -val sp_0_or_cr : 'a * (Types.spaces * (int * 'b)) -> unit -val sp_1 : 'a * (Types.spaces * (int * 'b)) -> unit -val sp_n : 'a * (Types.spaces * (int * 'b)) -> unit -val sp_p : 'a * (Types.spaces * (int * 'b)) -> unit -val sp_cr : 'a * (Types.spaces * (int * 'b)) -> unit -val sp_same : -  'a * (Types.spaces * (int * 'b)) -> -  'c * (Types.spaces * (int * 'd)) -> unit -val check_word_alone : Types.fromparser * 'a -> Types.fromparser +val sp_0 : 'a Types.any_spaces_pos -> unit +val sp_0_or_cr : 'a Types.any_spaces_pos -> unit +val sp_1 : 'a Types.any_spaces_pos -> unit +val sp_n : 'a Types.any_spaces_pos -> unit +val sp_p : 'a Types.any_spaces_pos -> unit +val sp_cr : 'a Types.any_spaces_pos -> unit +val sp_same : 'a Types.any_spaces_pos -> 'b Types.any_spaces_pos -> unit +val check_word_alone : Types.fromparser -> Types.fromparser  val check_parenthesized_first_argexpr :    string -> -  ('a * Types.fromparser list) * (Types.spaces * (int * 'b)) -> unit +  Types.fromparser list Types.prio_anyexpr Types.any_spaces_pos -> unit  val check_parenthesized_first_argexpr_with_Ident :    Types.fromparser -> -  (Types.priority * Types.fromparser list) * (Types.spaces * (int * 'a)) -> -  unit +  Types.fromparser list Types.prio_anyexpr Types.any_spaces_pos -> unit  val check_hash_subscript : -  ('a * Types.fromparser) * ('b * (int * int)) -> unit +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos -> unit  val check_arrow_needed : -  ('a * Types.fromparser) * 'b -> 'c * ('d * (int * int)) -> unit -val check_scalar_subscripted : Types.fromparser * 'a -> unit -val check_negatable_expr : ('a * Types.fromparser) * 'b -> unit +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos -> +  'a Types.any_spaces_pos -> unit +val check_scalar_subscripted : Types.fromparser Types.any_spaces_pos -> unit +val check_negatable_expr : +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos -> unit  val check_ternary_paras :    Types.fromparser * Types.fromparser * Types.fromparser ->    Types.fromparser list  val check_unneeded_var_dollar_ : -  ('a * Types.fromparser) * ('b * (int * int)) -> unit +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos -> unit  val check_unneeded_var_dollar_not : -  ('a * Types.fromparser) * ('b * (int * int)) -> unit +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos -> unit  val check_unneeded_var_dollar_s : -  ('a * Types.fromparser) * ('b * (int * int)) -> unit -val check_MULT_is_x : string * 'a -> unit -val check_my : string * 'a -> unit -val check_foreach : string * ('a * (int * int)) -> unit -val check_for : string * ('a * (int * int)) -> unit +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos -> unit +val check_MULT_is_x : string Types.any_spaces_pos -> unit +val check_my : string Types.any_spaces_pos -> unit +val check_foreach : string Types.any_spaces_pos -> unit +val check_for : string Types.any_spaces_pos -> unit  val check_for_foreach : -  string * ('a * (int * int)) -> ('b * Types.fromparser) * 'c -> unit +  string Types.any_spaces_pos -> +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos -> unit  val check_block_sub : -  Types.fromparser list * (Types.spaces * (int * int)) -> -  'a * (Types.spaces * (int * 'b)) -> unit +  Types.fromparser list Types.any_spaces_pos -> +  'a Types.any_spaces_pos -> unit  val check_block_ref : -  Types.fromparser list * (Types.spaces * (int * int)) -> -  'a * (Types.spaces * (int * 'b)) -> unit -val check_my_our_paren : ((bool * 'a) * 'b) * 'c -> unit +  Types.fromparser list Types.any_spaces_pos -> +  'a Types.any_spaces_pos -> unit +val check_my_our_paren : ((bool * 'a) * 'b) Types.any_spaces_pos -> unit  val check_simple_pattern : Types.fromparser list -> unit -val only_one : Types.fromparser list * ('a * (int * int)) -> Types.fromparser +val only_one : Types.fromparser list Types.any_spaces_pos -> Types.fromparser  val only_one_array_ref : -  Types.fromparser list * ('a * (int * int)) -> Types.fromparser +  Types.fromparser list Types.any_spaces_pos -> Types.fromparser  val only_one_in_List : -  ('a * Types.fromparser) * ('b * (int * int)) -> Types.fromparser +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos -> +  Types.fromparser  val is_only_one_in_List : Types.fromparser list -> bool  val maybe_to_Raw_string : Types.fromparser -> Types.fromparser  val to_List : Types.fromparser list -> Types.fromparser  val deref_arraylen : Types.fromparser -> Types.fromparser  val deref_raw : Types.context -> Types.fromparser -> Types.fromparser  val to_Ident : -  (string option * string) * ('a * (int * int)) -> Types.fromparser -val to_Raw_string : string * ('a * (int * int)) -> Types.fromparser +  (string option * string) Types.any_spaces_pos -> Types.fromparser +val to_Raw_string : string Types.any_spaces_pos -> Types.fromparser  val to_Method_call :    Types.fromparser * Types.fromparser * Types.fromparser list ->    Types.fromparser @@ -116,51 +134,54 @@ val to_Deref_with :    Types.context * Types.context * Types.fromparser * Types.fromparser ->    Types.fromparser  val to_Local : -  ('a * Types.fromparser) * ('b * (int * int)) -> Types.fromparser -val op : 'a -> 'b -> 'c * 'd -> 'a * ((unit * 'd) * 'b) -val op_p : -  'a -> -  'b -> -  'c * (Types.spaces * (int * 'd)) -> -  'a * ((unit * (Types.spaces * (int * 'd))) * 'b) +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos -> +  Types.fromparser  val sub_declaration :    Types.fromparser * string -> Types.fromparser list -> Types.fromparser  val anonymous_sub : -  Types.fromparser list * ('a * (int * int)) -> Types.fromparser +  Types.fromparser list Types.any_spaces_pos -> Types.fromparser  val cook_call_op : -  string * Types.fromparser list * (int * int) -> Types.fromparser -val call_op_ : -  ('a * (('b * (Types.spaces * (int * 'c))) * string)) * -  ('d * (Types.spaces * (int * 'e))) * Types.fromparser list -> -  'f * (int * int) -> ('a * Types.fromparser) * ('f * (int * int)) +  string -> Types.fromparser list -> int * int -> Types.fromparser  val to_Call_op : -  string * Types.fromparser list -> -  'a * (int * int) -> Types.fromparser * ('a * (int * int)) +  string -> +  Types.fromparser list -> +  'a Types.any_spaces_pos -> +  'b Types.any_spaces_pos -> Types.fromparser Types.any_spaces_pos  val to_Call_op_ : -  'a * string * Types.fromparser list -> -  'b * (int * int) -> ('a * Types.fromparser) * ('b * (int * int)) +  Types.priority -> +  string -> +  Types.fromparser list -> +  'a Types.any_spaces_pos -> +  'b Types.any_spaces_pos -> +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos  val followed_by_comma : -  ('a * Types.fromparser list) * 'b -> bool * 'c -> Types.fromparser list +  Types.fromparser list Types.prio_anyexpr Types.any_spaces_pos -> +  bool Types.any_spaces_pos -> Types.fromparser list  val pot_strings : (string, string list) Hashtbl.t  val pot_strings_and_file : (string, string) Hashtbl.t  val po_comments : string list ref -val po_comment : string * 'a -> unit +val po_comment : string Types.any_spaces_pos -> unit  val check_format_a_la_printf : string -> int -> unit  val generate_pot : string -> unit  val call_func :    bool -> Types.fromparser * Types.fromparser list -> Types.fromparser  val call : Types.fromparser * Types.fromparser list -> Types.fromparser  val call_one_scalar_para : -  string * ('a * (int * int)) -> -  Types.fromparser list -> Types.priority * Types.fromparser +  string Types.any_spaces_pos -> +  Types.fromparser list -> +  'a Types.any_spaces_pos -> +  'b Types.any_spaces_pos -> +  Types.fromparser Types.prio_anyexpr Types.any_spaces_pos  val call_op_if_infix :    Types.fromparser ->    Types.fromparser -> -  'a * (int * int) -> Types.fromparser * ('a * (int * int)) +  'a Types.any_spaces_pos -> +  'b Types.any_spaces_pos -> Types.fromparser Types.any_spaces_pos  val call_op_unless_infix :    Types.fromparser ->    Types.fromparser -> -  'a * (int * int) -> Types.fromparser * ('a * (int * int)) +  'a Types.any_spaces_pos -> +  'b Types.any_spaces_pos -> Types.fromparser Types.any_spaces_pos  val current_lexbuf : Lexing.lexbuf option ref  val list2tokens : ((int * int) * 'a) list -> Lexing.lexbuf -> 'a  val parse_tokens : @@ -172,14 +193,14 @@ val parse_interpolated :  val to_String :    ((Lexing.lexbuf -> 'a) -> Lexing.lexbuf -> Types.fromparser list) ->    bool -> -  (string * ((int * int) * 'a) list) list * ('b * (int * int)) -> +  (string * ((int * int) * 'a) list) list Types.any_spaces_pos ->    Types.fromparser  val from_PATTERN :    ((Lexing.lexbuf -> 'a) -> Lexing.lexbuf -> Types.fromparser list) -> -  ((string * ((int * int) * 'a) list) list * string) * ('b * (int * int)) -> +  ((string * ((int * int) * 'a) list) list * string) Types.any_spaces_pos ->    Types.fromparser list  val from_PATTERN_SUBST :    ((Lexing.lexbuf -> 'a) -> Lexing.lexbuf -> Types.fromparser list) ->    ((string * ((int * int) * 'a) list) list * -   (string * ((int * int) * 'a) list) list * string) * -  ('b * (int * int)) -> Types.fromparser list +   (string * ((int * int) * 'a) list) list * string) +  Types.any_spaces_pos -> Types.fromparser list diff --git a/perl_checker.src/types.mli b/perl_checker.src/types.mli index 4c94d47..6f49cd9 100644 --- a/perl_checker.src/types.mli +++ b/perl_checker.src/types.mli @@ -65,3 +65,19 @@ type priority =  | P_paren_wanted of priority  | P_paren of priority + +| P_none + +type 'a any_spaces_pos = { +    any : 'a ; +    spaces : spaces ; +    pos : int * int ; +  } + +type 'a prio_anyexpr = { +    priority : priority ; +    expr : 'a +  } + +type prio_expr_spaces_pos = fromparser prio_anyexpr any_spaces_pos +type prio_lexpr_spaces_pos = fromparser list prio_anyexpr any_spaces_pos  | 
