summaryrefslogtreecommitdiffstats
path: root/perl_checker.src
diff options
context:
space:
mode:
authorPascal Rigaux <pixel@mandriva.com>2002-11-14 23:37:43 +0000
committerPascal Rigaux <pixel@mandriva.com>2002-11-14 23:37:43 +0000
commit0eed9c8cc0e8ec742489c5cbec73088dfdc485e0 (patch)
tree66856104165898678319a7588679cf1e151fe01d /perl_checker.src
parent355143d4b44031b4aeea1684cba1b31bb30c03ba (diff)
downloadperl_checker-0eed9c8cc0e8ec742489c5cbec73088dfdc485e0.tar
perl_checker-0eed9c8cc0e8ec742489c5cbec73088dfdc485e0.tar.gz
perl_checker-0eed9c8cc0e8ec742489c5cbec73088dfdc485e0.tar.bz2
perl_checker-0eed9c8cc0e8ec742489c5cbec73088dfdc485e0.tar.xz
perl_checker-0eed9c8cc0e8ec742489c5cbec73088dfdc485e0.zip
*** empty log message ***
Diffstat (limited to 'perl_checker.src')
-rw-r--r--perl_checker.src/Makefile10
-rw-r--r--perl_checker.src/info.ml6
-rw-r--r--perl_checker.src/info.mli3
-rw-r--r--perl_checker.src/parser.mly304
-rw-r--r--perl_checker.src/parser_helper.ml47
-rw-r--r--perl_checker.src/parser_helper.mli32
-rw-r--r--perl_checker.src/types.mli2
7 files changed, 226 insertions, 178 deletions
diff --git a/perl_checker.src/Makefile b/perl_checker.src/Makefile
index 5d28fa6..9f66e4a 100644
--- a/perl_checker.src/Makefile
+++ b/perl_checker.src/Makefile
@@ -1,7 +1,7 @@
# OCAMLC = ocamlcp -p a
OCAMLBCFLAGS = -w A
YFLAGS = -v
-TRASH = parser.output
+TRASH = parser.output TAGS
RESULT = perl_checker
BCSUFFIX = _debug
SOURCES = common.ml types.mli info.ml parser_helper.ml parser.mly lexer.mll perl_checker.ml
@@ -9,6 +9,12 @@ LIBS = unix
NAME = shyant
-default: debug-code native-code
+default: TAGS debug-code native-code
+
+tags:
+ ocamltags *.ml
+
+TAGS:
+ ocamltags *.ml
-include OCamlMakefile \ No newline at end of file
diff --git a/perl_checker.src/info.ml b/perl_checker.src/info.ml
index 3d68439..d15d3c0 100644
--- a/perl_checker.src/info.ml
+++ b/perl_checker.src/info.ml
@@ -29,4 +29,10 @@ let pos2sfull pos =
sprintf "File \"%s\", line %d, character %d-%d\n" file (line + 1) n1 n2
with Not_found -> failwith ("bad position " ^ pos2s pos)
+let is_on_same_line file (a,b) =
+ let line_a, _ = raw_pos2raw_line file a in
+ let line_b, _ = raw_pos2raw_line file b in
+ line_a = line_b
+
+let is_on_same_line_current (a,b) = is_on_same_line !current_file (a,b)
let pos2sfull_current a b = pos2sfull (!current_file, a, b)
diff --git a/perl_checker.src/info.mli b/perl_checker.src/info.mli
index ed9455e..6796a62 100644
--- a/perl_checker.src/info.mli
+++ b/perl_checker.src/info.mli
@@ -5,5 +5,8 @@ val current_file : string ref
val start_a_new_file : string -> unit
val raw_pos2raw_line : string -> int -> int * int
val pos2line : string * int * int -> string * int * int * int
+val pos2s : string * int * int -> string
val pos2sfull : string * int * int -> string
+val is_on_same_line : string -> int * int -> bool
+val is_on_same_line_current : int * int -> bool
val pos2sfull_current : int -> int -> string
diff --git a/perl_checker.src/parser.mly b/perl_checker.src/parser.mly
index 8352c97..d9ef7b2 100644
--- a/perl_checker.src/parser.mly
+++ b/perl_checker.src/parser.mly
@@ -96,68 +96,68 @@ prog: lines EOF {check_package (fst $1); fst $1}
lines: /* A collection of "lines" in the program */
| {[], (Space_none, bpos)}
| sideff {[fst $1], snd $1}
-| line lines {fst $1 :: fst $2, snd $1}
+| line lines {fst $1 @ fst $2, pos_range $1 $2}
line:
-| decl {$1}
-| if_then_else {$1}
-| loop {$1}
-| LABEL {sp_cr($1); Label(fst $1), snd $1}
-| semi_colon {Semi_colon, snd $1}
-| sideff semi_colon {$1}
-| BRACKET lines BRACKET_END {sp_p($2); sp_p($3); Block(fst $2), snd $1}
+| 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}
+| 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)], pos_range $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); sp_p($6); sp_p($7); Call_op("if", prio_lo P_loose $3 :: Block(fst $6) :: fst $8 @ fst $9), snd $1}
-| 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); sp_p($6); sp_p($7); Call_op("unless", prio_lo P_loose $3 :: Block(fst $6) :: fst $8 @ fst $9), snd $1}
+| 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; Call_op("if", prio_lo P_loose $3 :: Block(fst $6) :: fst $8 @ fst $9), 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; Call_op("unless", prio_lo P_loose $3 :: Block(fst $6) :: fst $8 @ fst $9), pos_range $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); sp_p($6); sp_p($7); prio_lo P_loose $3 :: Block(fst $6) :: fst $8, snd $1}
+| 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, pos_range $1 $8}
else_:
| { [], (Space_none, bpos) }
-| ELSE BRACKET lines BRACKET_END {sp_p($1); sp_n($2); sp_p($3); sp_p($4); [ Block(fst $3) ], snd $1 }
+| ELSE BRACKET lines BRACKET_END {sp_p($1); sp_n($2); check_block_sub $3 $4; [Block(fst $3)], pos_range $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); sp_p($6); sp_p($7); Call_op("while", prio_lo P_loose $3 :: fst $6), snd $1}
-| 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); sp_p($6); sp_p($7); Call_op("until", prio_lo P_loose $3 :: fst $6), snd $1}
-| FOR MY SCALAR_IDENT PAREN expr PAREN_END BRACKET lines BRACKET_END cont {sp_p($1); check_foreach($1); sp_n($4); sp_0($5); sp_0_or_cr($6); sp_p($7); sp_p($8); sp_p($9); Call_op("foreach my", to_Ident $3 :: prio_lo P_loose $5 :: fst $8), snd $1}
+| 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; Call_op("while", [ prio_lo P_loose $3; Block(fst $6) ]), 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; Call_op("until", [ prio_lo P_loose $3; Block(fst $6) ]), pos_range $1 $8}
+| FOR MY SCALAR_IDENT PAREN expr PAREN_END BRACKET lines BRACKET_END cont {sp_p($1); check_foreach($1); sp_n($4); sp_0($5); sp_0_or_cr($6); sp_p($7); check_block_sub $8 $9; Call_op("foreach my", [ to_Ident $3; prio_lo P_loose $5; Block(fst $8) ]), pos_range $1 $10}
| 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); sp_p($6); sp_p($7); check_foreach($1); Call_op("foreach", prio_lo P_loose $3 :: fst $6), snd $1}
-| FOR PAREN expr_or_empty semi_colon expr_or_empty semi_colon expr_or_empty PAREN_END BRACKET lines BRACKET_END {sp_p($1); sp_n($2); sp_0($3); check_for($1); Call_op("for", fst $3 :: fst $5 :: fst $7 :: fst $10), snd $1}
+| 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_foreach($1); Call_op("foreach", [ prio_lo P_loose $3; Block(fst $6) ]), 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; Call_op("for", [ fst $3; fst $5; fst $7; Block(fst $10) ]), pos_range $1 $11}
cont: /* Continue blocks */
| {(), (Space_none, bpos)}
-| CONTINUE BRACKET lines BRACKET_END {sp_p($1); sp_n($2); sp_p($3); sp_p($4); (), snd $1}
+| CONTINUE BRACKET lines BRACKET_END {sp_p($1); sp_n($2); check_block_sub $3 $4; (), pos_range $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 ]), snd $1}
-| expr UNLESS expr {sp_p($2); sp_p($3); Call_op("unless infix", [ prio_lo P_loose $1 ; prio_lo P_loose $3 ]), snd $1}
-| expr WHILE expr {sp_p($2); sp_p($3); Call_op("while infix" , [ prio_lo P_loose $1 ; prio_lo P_loose $3 ]), snd $1}
-| expr UNTIL expr {sp_p($2); sp_p($3); Call_op("until infix" , [ prio_lo P_loose $1 ; prio_lo P_loose $3 ]), snd $1}
-| expr FOR expr {sp_p($2); sp_p($3); check_foreach($2); Call_op("for infix" , [ prio_lo P_loose $1 ; prio_lo P_loose $3 ]), 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 ]), 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 ]), pos_range $1 $3}
+| expr WHILE expr {sp_p($2); sp_p($3); Call_op("while infix" , [ prio_lo P_loose $1 ; prio_lo P_loose $3 ]), pos_range $1 $3}
+| expr UNTIL expr {sp_p($2); sp_p($3); Call_op("until infix" , [ prio_lo P_loose $1 ; prio_lo P_loose $3 ]), pos_range $1 $3}
+| expr FOR expr {sp_p($2); sp_p($3); check_foreach($2); Call_op("for infix" , [ prio_lo P_loose $1 ; prio_lo P_loose $3 ]), pos_range $1 $3}
decl:
-| FORMAT BAREWORD ASSIGN {Too_complex, snd $1}
-| FORMAT ASSIGN {Too_complex, snd $1}
+| FORMAT BAREWORD ASSIGN {Too_complex, pos_range $1 $3}
+| FORMAT ASSIGN {Too_complex, pos_range $1 $2}
| func_decl semi_colon {die_rule (if sndfst $1 = "" then "there is no need to pre-declare in Perl!" else "please don't use prototype pre-declaration") }
-| func_decl BRACKET BRACKET_END {sp_n($2); sp_0_or_cr($3); let name, proto = fst $1 in sub_declaration (name, proto) [], snd $1}
-| func_decl BRACKET lines BRACKET_END {sp_n($2); check_lines_after_BRACKET($3); sp_p($4); sub_declaration (fst $1) (fst $3), snd $1}
-| 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)], snd $1}
-| 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)], snd $1}
-| PACKAGE word semi_colon {sp_0_or_cr($1); sp_1($2); Package(fst $2), snd $1}
-| BEGIN BRACKET lines BRACKET_END {sp_0_or_cr($1); sp_1($2); sp_p($3); sp_p($4); Sub_declaration(Ident(None, "BEGIN", get_pos $1), "", fst $3), snd $1}
-| END BRACKET lines BRACKET_END {sp_0_or_cr($1); sp_1($2); sp_p($3); sp_p($4); Sub_declaration(Ident(None, "END", get_pos $1), "", fst $3), snd $1}
+| func_decl BRACKET BRACKET_END {sp_n($2); sp_0_or_cr($3); let name, proto = fst $1 in sub_declaration (name, proto) [], pos_range $1 $3}
+| func_decl BRACKET lines BRACKET_END {sp_n($2); check_block_sub $3 $4; sub_declaration (fst $1) (fst $3), 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)], 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], pos_range $1 $7}
+| PACKAGE word semi_colon {sp_0_or_cr($1); sp_1($2); Package(fst $2), 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), "", fst $3), 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), "", fst $3), pos_range $1 $4}
| use {$1}
use:
-| use_word listexpr semi_colon {sp_n($2); Use(fst $1, sndfst $2), snd $1}
+| use_word listexpr semi_colon {sp_n($2); Use(fst $1, sndfst $2), pos_range $1 $3}
use_word:
-| use_revision word comma {fst $2, snd $1}
-| use_revision word {fst $2, snd $1}
+| use_revision word comma {fst $2, pos_range $1 $3}
+| use_revision word {fst $2, pos_range $1 $2}
| use_revision {Ident(None, "", get_pos $1), snd $1}
use_revision:
@@ -166,7 +166,7 @@ use_revision:
| USE {$1}
func_decl:
-| SUB word {(fst $2, ""), snd $1}
+| SUB word {(fst $2, ""), pos_range $1 $2}
| FUNC_DECL_WITH_PROTO {(Ident(None, fstfst $1, get_pos $1), sndfst $1), snd $1}
listexpr: /* Basic list expressions */
@@ -174,123 +174,121 @@ listexpr: /* Basic list expressions */
| argexpr %prec PREC_LOW {$1}
expr: /* Ordinary expressions; logical combinations */
-| expr AND expr {sp_p($2); sp_p($3); (P_and, Call_op("and", [ prio_lo P_and $1; prio_lo_after P_and $3 ])), snd $1}
-| expr OR expr {sp_p($2); sp_p($3); (P_or, Call_op("or", [ prio_lo P_or $1; prio_lo_after P_or $3 ])), snd $1}
+| expr AND expr {sp_p($2); sp_p($3); (P_and, Call_op("and", [ prio_lo P_and $1; prio_lo_after P_and $3 ])), pos_range $1 $3}
+| expr OR expr {sp_p($2); sp_p($3); (P_or, Call_op("or", [ prio_lo P_or $1; prio_lo_after P_or $3 ])), pos_range $1 $3}
| argexpr %prec PREC_LOW {(fstfst $1, List(sndfst $1)), snd $1}
argexpr: /* Expressions are a list of terms joined by commas */
-| argexpr comma {(P_comma, sndfst $1), snd $1}
-| argexpr comma term {if not_simple (sndfst $3) then sp_p($3); (P_comma, sndfst $1 @ [sndfst $3]), snd $1}
-| argexpr comma BRACKET expr BRACKET_END {sp_p($3); sp_p($5); (P_comma, sndfst $1 @ [ Ref(I_hash, sndfst $4) ]), snd $1}
+| argexpr comma {(P_comma, sndfst $1), pos_range $1 $2}
+| argexpr comma term {if not_simple (sndfst $3) then sp_p($3); (P_comma, sndfst $1 @ [sndfst $3]), pos_range $1 $3}
+| argexpr comma BRACKET expr BRACKET_END {sp_p($3); sp_p($5); (P_comma, sndfst $1 @ [ Ref(I_hash, sndfst $4) ]), pos_range $1 $5}
| term %prec PREC_LOW {(fstfst $1, [sndfst $1]), snd $1}
/********************************************************************************/
term:
-| term ASSIGN term {let pri = P_assign in call_op(op_p pri (fst $2) $2, $3, [prio_lo pri $1; prio_lo_after pri $3]), snd $1}
-| 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]), snd $1}
-| 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]), snd $1}
-| term LT term {let pri = P_cmp in call_op(op_p pri "<" $2, $3, [prio_lo pri $1; prio_lo_after pri $3]), snd $1}
-| term GT term {let pri = P_cmp in call_op(op_p pri ">" $2, $3, [prio_lo pri $1; prio_lo_after pri $3]), snd $1}
-| 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]), snd $1}
-| term POWER term {let pri = P_tight in call_op(op pri "**" $2, $3, [prio_lo pri $1; prio_lo_after pri $3]), snd $1}
-| term BIT_AND term {let pri = P_expr in call_op(op_p pri "&" $2, $3, [prio_lo pri $1; prio_lo_after pri $3]), snd $1}
-| term BIT_OR term {let pri = P_expr in call_op(op pri "|" $2, $3, [prio_lo pri $1; prio_lo_after pri $3]), snd $1}
-| term BIT_XOR term {let pri = P_expr in call_op(op_p pri "^" $2, $3, [prio_lo pri $1; prio_lo_after pri $3]), snd $1}
-| 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]), snd $1}
-| 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]), snd $1}
-| 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]), snd $1}
-| 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]), snd $1}
-| 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]), snd $1}
-| 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]), snd $1}
+| term ASSIGN term {let pri = P_assign in call_op(op_p pri (fst $2) $2, $3, [prio_lo pri $1; prio_lo_after pri $3]), 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]), 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]), 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]), 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]), 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]), 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]), pos_range $1 $3}
+| term BIT_AND term {let pri = P_expr in call_op(op_p pri "&" $2, $3, [prio_lo pri $1; prio_lo_after pri $3]), pos_range $1 $3}
+| term BIT_OR term {let pri = P_expr in call_op(op pri "|" $2, $3, [prio_lo pri $1; prio_lo_after pri $3]), pos_range $1 $3}
+| term BIT_XOR term {let pri = P_expr in call_op(op_p pri "^" $2, $3, [prio_lo pri $1; prio_lo_after pri $3]), 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]), 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]), 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]), 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]), 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]), 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]), 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)]), snd $1}
-| 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)]), snd $1}
-| 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)]), snd $1}
+| 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)]), 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)]), 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)]), pos_range $1 $5}
-| term PATTERN_MATCH PATTERN {sp_n($2); sp_p($3); (P_expr, Call_op("m//", sndfst $1 :: from_PATTERN $3)), snd $1}
-| term PATTERN_MATCH_NOT PATTERN {sp_n($2); sp_p($3); (P_expr, Call_op("!m//", sndfst $1 :: from_PATTERN $3)), snd $1}
-| term PATTERN_MATCH PATTERN_SUBST {sp_n($2); sp_p($3); (P_expr, Call_op("s///", sndfst $1 :: from_PATTERN_SUBST $3)), snd $1}
+| term PATTERN_MATCH PATTERN {sp_n($2); sp_p($3); (P_expr, Call_op("m//", sndfst $1 :: from_PATTERN $3)), pos_range $1 $3}
+| term PATTERN_MATCH_NOT PATTERN {sp_n($2); sp_p($3); (P_expr, Call_op("!m//", sndfst $1 :: from_PATTERN $3)), pos_range $1 $3}
+| term PATTERN_MATCH PATTERN_SUBST {sp_n($2); sp_p($3); (P_expr, Call_op("s///", sndfst $1 :: from_PATTERN_SUBST $3)), pos_range $1 $3}
-| term PATTERN_MATCH scalar { (P_expr, Too_complex), snd $1 }
-| term PATTERN_MATCH_NOT scalar { (P_expr, Too_complex), snd $1 }
+| term PATTERN_MATCH scalar { (P_expr, Too_complex), pos_range $1 $3}
+| term PATTERN_MATCH_NOT scalar { (P_expr, Too_complex), pos_range $1 $3}
-| term PATTERN_MATCH STRING {failwith (msg_with_pos (sndsnd $3) "use a regexp, not a string")}
-| term PATTERN_MATCH_NOT STRING {failwith (msg_with_pos (sndsnd $3) "use a regexp, not a string")}
+| term PATTERN_MATCH STRING {die_with_pos (sndsnd $3) "use a regexp, not a string"}
+| term PATTERN_MATCH_NOT STRING {die_with_pos (sndsnd $3) "use a regexp, not a string"}
-| term QUESTION_MARK term COLON term {sp_n($2); sp_p($3); sp_p($4); sp_p($5); (P_ternary, Call_op("?:", [ prio_lo P_ternary $1 ; prio_lo_after P_ternary $3; prio_lo_after P_ternary $5])), snd $1}
-| term QUESTION_MARK term COLON BRACKET expr BRACKET_END {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sp_p($7); (P_ternary, Call_op("?:", [ prio_lo P_ternary $1 ; prio_lo_after P_ternary $3; sndfst $6])), snd $1}
-| term QUESTION_MARK BRACKET expr BRACKET_END COLON term {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sp_p($7); (P_ternary, Call_op("?:", [ prio_lo P_ternary $1 ; sndfst $4; prio_lo_after P_ternary $7])), snd $1}
-| term QUESTION_MARK BRACKET expr BRACKET_END COLON BRACKET expr BRACKET_END {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sp_p($7); sp_p($8); sp_p($9); (P_ternary, Call_op("?:", [ prio_lo P_ternary $1 ; sndfst $4; sndfst $8])), snd $1}
+| term QUESTION_MARK term COLON term {sp_n($2); sp_p($3); sp_p($4); sp_p($5); (P_ternary, Call_op("?:", [ prio_lo P_ternary $1 ; prio_lo_after P_ternary $3; prio_lo_after P_ternary $5])), pos_range $1 $5}
+| term QUESTION_MARK term COLON BRACKET expr BRACKET_END {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sp_p($7); (P_ternary, Call_op("?:", [ prio_lo P_ternary $1 ; prio_lo_after P_ternary $3; sndfst $6])), pos_range $1 $7}
+| term QUESTION_MARK BRACKET expr BRACKET_END COLON term {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sp_p($7); (P_ternary, Call_op("?:", [ prio_lo P_ternary $1 ; sndfst $4; prio_lo_after P_ternary $7])), pos_range $1 $7}
+| term QUESTION_MARK BRACKET expr BRACKET_END COLON BRACKET expr BRACKET_END {sp_n($2); sp_p($3); sp_p($4); sp_p($5); sp_p($6); sp_p($7); sp_p($8); sp_p($9); (P_ternary, Call_op("?:", [ prio_lo P_ternary $1 ; sndfst $4; sndfst $8])), pos_range $1 $9}
/* Unary operators and terms */
-| PLUS term %prec UNARY_MINUS {if fst $1 <> "-" then die_rule "syntax error"; sp_0($2); (P_tight, Call_op("- unary", [sndfst $2])), snd $1}
-| TIGHT_NOT term {(P_tight, Call_op("not", [sndfst $2])), snd $1}
-| BIT_NEG term {(P_expr, Call_op("~", [sndfst $2])), snd $1}
-| INCR term {sp_0($2); (P_tight, Call_op("++", [sndfst $2])), snd $1}
-| DECR term {sp_0($2); (P_tight, Call_op("--", [sndfst $2])), snd $1}
-| term INCR {sp_0($2); (P_tight, Call_op("++ post", [sndfst $1])), snd $1}
-| term DECR {sp_0($2); (P_tight, Call_op("-- post", [sndfst $1])), snd $1}
-
-| DEFINED scalar {(P_expr, Call(Ident(None, "defined", get_pos $1), [fst $2])), snd $1}
-| DEFINED subscripted {(P_expr, Call(Ident(None, "defined", get_pos $1), [fst $2])), snd $1}
-| DEFINED parenthesized {(P_expr, Call(Ident(None, "defined", get_pos $1), sndfst $2)), snd $1}
-| DEFINED word_paren parenthesized {(P_expr, Call(Ident(None, "defined", get_pos $1), [Call(fst $2, sndfst $3)])), snd $1}
-
-| NOT argexpr {(P_and, Call_op("not", sndfst $2)), snd $1}
-
+| PLUS term %prec UNARY_MINUS {if fst $1 <> "-" then die_rule "syntax error"; sp_0($2); (P_tight, Call_op("- unary", [sndfst $2])), pos_range $1 $2}
+| TIGHT_NOT term {(P_tight, Call_op("not", [sndfst $2])), pos_range $1 $2}
+| BIT_NEG term {(P_expr, Call_op("~", [sndfst $2])), pos_range $1 $2}
+| INCR term {sp_0($2); (P_tight, Call_op("++", [sndfst $2])), pos_range $1 $2}
+| DECR term {sp_0($2); (P_tight, Call_op("--", [sndfst $2])), pos_range $1 $2}
+| term INCR {sp_0($2); (P_tight, Call_op("++ post", [sndfst $1])), pos_range $1 $2}
+| term DECR {sp_0($2); (P_tight, Call_op("-- post", [sndfst $1])), pos_range $1 $2}
+| NOT argexpr {(P_and, Call_op("not", sndfst $2)), pos_range $1 $2}
+
+| DEFINED scalar {(P_expr, Call(Ident(None, "defined", get_pos $1), [fst $2])), pos_range $1 $2}
+| DEFINED subscripted {(P_expr, Call(Ident(None, "defined", get_pos $1), [fst $2])), pos_range $1 $2}
+| DEFINED parenthesized {(P_expr, Call(Ident(None, "defined", get_pos $1), sndfst $2)), pos_range $1 $2}
+| DEFINED word_paren parenthesized {(P_expr, Call(Ident(None, "defined", get_pos $1), [Call(fst $2, sndfst $3)])), pos_range $1 $3}
/* Constructors for anonymous data */
-| ARRAYREF ARRAYREF_END {sp_0($2); (P_expr, Ref(I_array, List[])), snd $1}
-| arrayref_start ARRAYREF_END {(P_expr, Ref(I_array, List(fst $1))), snd $1}
-| arrayref_start expr ARRAYREF_END {(P_expr, Ref(I_array, List(fst $1 @ [sndfst $2]))), snd $1}
-| arrayref_start BRACKET expr BRACKET_END ARRAYREF_END {(P_expr, Ref(I_array, List(fst $1 @ [Ref(I_hash, sndfst $3)]))), snd $1}
+| ARRAYREF ARRAYREF_END {sp_0($2); (P_expr, Ref(I_array, List[])), pos_range $1 $2}
+| arrayref_start ARRAYREF_END {(P_expr, Ref(I_array, List(fst $1))), pos_range $1 $2}
+| arrayref_start expr ARRAYREF_END {(P_expr, Ref(I_array, List(fst $1 @ [sndfst $2]))), pos_range $1 $3}
+| arrayref_start BRACKET expr BRACKET_END ARRAYREF_END {(P_expr, Ref(I_array, List(fst $1 @ [Ref(I_hash, sndfst $3)]))), pos_range $1 $5}
-| BRACKET BRACKET_END {(P_expr, Ref(I_hash, List [])), snd $1} /* empty hash */
-| BRACKET_HASHREF expr BRACKET_END %prec PREC_HIGH {sp_p($3); (P_expr, Ref(I_hash, sndfst $2)), snd $1} /* { foo => "Bar" } */
-| SUB BRACKET BRACKET_END %prec PREC_HIGH {sp_n($2); sp_0($3); (P_expr, Anonymous_sub(Block[])), snd $1}
-| SUB BRACKET lines BRACKET_END %prec PREC_HIGH {sp_n($2); check_lines_after_BRACKET($3); sp_p($4); (P_expr, Anonymous_sub(Block(fst $3))), snd $1}
+| BRACKET BRACKET_END {(P_expr, Ref(I_hash, List [])), pos_range $1 $2} /* empty hash */
+| BRACKET_HASHREF expr BRACKET_END %prec PREC_HIGH {sp_p($3); (P_expr, Ref(I_hash, sndfst $2)), pos_range $1 $3} /* { foo => "Bar" } */
+| SUB BRACKET BRACKET_END %prec PREC_HIGH {sp_n($2); sp_0($3); (P_expr, Anonymous_sub []), pos_range $1 $3}
+| SUB BRACKET lines BRACKET_END %prec PREC_HIGH {sp_n($2); check_block_sub $3 $4; (P_expr, Anonymous_sub(fst $3)), pos_range $1 $4}
| termdo {(P_tok, fst $1), snd $1}
-| REF term {(P_expr, Ref(I_scalar, sndfst $2)), snd $1} /* \$x, \@y, \%z */
+| REF term {(P_expr, Ref(I_scalar, sndfst $2)), pos_range $1 $2} /* \$x, \@y, \%z */
| my %prec UNIOP {(P_expr, List(fst $1)), snd $1}
-| LOCAL term %prec UNIOP {sp_n($2); (P_expr, Local(sndfst $2)), snd $1}
+| LOCAL term %prec UNIOP {sp_n($2); (P_expr, Local(sndfst $2)), pos_range $1 $2}
| parenthesized {(fstfst $1, List(sndfst $1)), snd $1} /* (1, 2) */
-| parenthesized arrayref {sp_0($2); (P_tok, Deref_with(I_array, List(sndfst $1), List(fst $2))), snd $1} /* list slice */
+| parenthesized arrayref {sp_0($2); (P_tok, Deref_with(I_array, List(sndfst $1), List(fst $2))), pos_range $1 $2} /* list slice */
| variable {(P_tok, fst $1), snd $1}
| subscripted {(P_tok, fst $1), snd $1}
-| array arrayref {(P_expr, Deref_with(I_array, fst $1, List(fst $2))), snd $1} /* array slice: @array[vals] */
-| array BRACKET expr BRACKET_END {sp_0($2); sp_0($3); sp_0($4); (P_expr, Deref_with(I_hash, array_ident_to_hash_ident $1, sndfst $3)), snd $1} /* hash slice: @hash{@keys} */
+| array arrayref {(P_expr, Deref_with(I_array, fst $1, List(fst $2))), pos_range $1 $2} /* array slice: @array[vals] */
+| array BRACKET expr BRACKET_END {sp_0($2); sp_0($3); sp_0($4); (P_expr, Deref_with(I_hash, array_ident_to_hash_ident $1, sndfst $3)), pos_range $1 $4} /* hash slice: @hash{@keys} */
/* function_calls */
-| func parenthesized {sp_0($2); (P_tok, call(fst $1, sndfst $2)), snd $1} /* &foo(@args) */
-| word argexpr {check_parenthesized_first_argexpr (string_of_Ident (fst $1)) $2; (P_call_no_paren, call(fst $1, sndfst $2)), snd $1} /* foo $a, $b */
-| word_paren parenthesized {(P_tok, call(fst $1, sndfst $2)), snd $1} /* foo(@args) */
-| word BRACKET lines BRACKET_END listexpr %prec LSTOP {sp_n($2); check_lines_after_BRACKET($3); sp_p($4); ((if sndfst $5 = [] then P_tok else P_call_no_paren), call(fst $1, Anonymous_sub(Block(fst $3)) :: sndfst $5)), snd $1} /* 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(fst $1, Anonymous_sub(Ref(I_hash, sndfst $4)) :: sndfst $7)), snd $1} /* 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(fst $1, Anonymous_sub(Ref(I_hash, sndfst $4)) :: sndfst $8)), snd $1} /* map { { foo }; } @bar */
+| func parenthesized {sp_0($2); (P_tok, call(fst $1, sndfst $2)), pos_range $1 $2} /* &foo(@args) */
+| word argexpr {check_parenthesized_first_argexpr (string_of_Ident (fst $1)) $2; (P_call_no_paren, call(fst $1, sndfst $2)), pos_range $1 $2} /* foo $a, $b */
+| word_paren parenthesized {(P_tok, call(fst $1, sndfst $2)), 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(fst $1, Anonymous_sub(fst $3) :: sndfst $5)), 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(fst $1, Anonymous_sub [ Ref(I_hash, sndfst $4) ] :: sndfst $7)), 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(fst $1, Anonymous_sub [ Ref(I_hash, sndfst $4); Semi_colon ] :: sndfst $8)), pos_range $1 $8} /* map { { foo }; } @bar */
-| term ARROW word_or_scalar parenthesized {sp_0($2); sp_0($3); sp_0($4); (P_tok, Method_callP(sndfst $1, fst $3, sndfst $4)), snd $1} /* $foo->bar(list) */
-| term ARROW word_or_scalar {sp_0($2); sp_0($3); (P_tok, Method_callP(sndfst $1, fst $3, [])), snd $1} /* $foo->bar */
+| term ARROW word_or_scalar parenthesized {sp_0($2); sp_0($3); sp_0($4); (P_tok, Method_callP(sndfst $1, fst $3, sndfst $4)), pos_range $1 $4} /* $foo->bar(list) */
+| term ARROW word_or_scalar {sp_0($2); sp_0($3); (P_tok, Method_callP(sndfst $1, fst $3, [])), pos_range $1 $3} /* $foo->bar */
-| NEW word listexpr { (P_call_no_paren, Method_call(fst $2, Ident(None, "new", get_pos $1), sndfst $3)), snd $1} /* new Class @args */
+| NEW word listexpr { (P_call_no_paren, Method_call(fst $2, Ident(None, "new", get_pos $1), sndfst $3)), pos_range $1 $3} /* new Class @args */
-| PRINT { (P_call_no_paren, Call_op("print", var_STDOUT :: [ var_dollar_ ])), snd $1 }
-| PRINT argexpr {check_parenthesized_first_argexpr (fst $1) $2; (P_call_no_paren, Call_op("print", var_STDOUT :: sndfst $2)), snd $1 }
-| PRINT_TO_STAR { (P_call_no_paren, Call_op("print", Deref(I_star, Ident(None, fst $1, get_pos $1)) :: [ var_dollar_ ])), snd $1 }
-| PRINT_TO_STAR argexpr { (P_call_no_paren, Call_op("print", Deref(I_star, Ident(None, fst $1, get_pos $1)) :: sndfst $2)), snd $1 }
-| PRINT_TO_SCALAR { (P_call_no_paren, Call_op("print", var_STDOUT :: [ Deref(I_scalar, Ident(None, fst $1, get_pos $1)) ])), snd $1 }
-| PRINT_TO_SCALAR argexpr { (P_call_no_paren, Call_op("print", Deref(I_scalar, Ident(None, fst $1, get_pos $1)) :: sndfst $2)), snd $1 }
+| PRINT { (P_call_no_paren, Call_op("print", var_STDOUT :: [ var_dollar_ ])), snd $1}
+| PRINT argexpr {check_parenthesized_first_argexpr (fst $1) $2; (P_call_no_paren, Call_op("print", var_STDOUT :: sndfst $2)), pos_range $1 $2}
+| PRINT_TO_STAR { (P_call_no_paren, Call_op("print", Deref(I_star, Ident(None, fst $1, get_pos $1)) :: [ var_dollar_ ])), snd $1}
+| PRINT_TO_STAR argexpr { (P_call_no_paren, Call_op("print", Deref(I_star, Ident(None, fst $1, get_pos $1)) :: sndfst $2)), pos_range $1 $2}
+| PRINT_TO_SCALAR { (P_call_no_paren, Call_op("print", var_STDOUT :: [ Deref(I_scalar, Ident(None, fst $1, get_pos $1)) ])), snd $1}
+| PRINT_TO_SCALAR argexpr { (P_call_no_paren, Call_op("print", Deref(I_scalar, Ident(None, fst $1, get_pos $1)) :: sndfst $2)), pos_range $1 $2}
-| hash PKG_SCOPE {sp_0($2); (P_tok, Too_complex), snd $1}
+| hash PKG_SCOPE {sp_0($2); (P_tok, Too_complex), pos_range $1 $2} /* %main:: */
| word {(P_tok, check_word_alone $1), snd $1}
@@ -305,48 +303,48 @@ term:
| diamond {(P_expr, fst $1), snd $1}
diamond:
-| LT GT {sp_0($2); Call_op("<>", []), snd $1}
-| LT term GT {sp_0($2); sp_0($3); Call_op("<>", [sndfst $2]), snd $1}
+| LT GT {sp_0($2); Call_op("<>", []), pos_range $1 $2}
+| LT term GT {sp_0($2); sp_0($3); Call_op("<>", [sndfst $2]), pos_range $1 $3}
subscripted: /* Some kind of subscripted expression */
-| variable PKG_SCOPE bracket_subscript {sp_0($2); sp_0($3); Too_complex, snd $1} /* $foo::{something} */
-| scalar bracket_subscript {sp_0($2); Deref_with(I_hash , fst $1, fst $2), snd $1} /* $foo{bar} */
-| scalar arrayref {sp_0($2); Deref_with(I_array, fst $1, only_one $2), snd $1} /* $array[$element] */
-| term ARROW bracket_subscript {sp_0($2); sp_0($3); Deref_with(I_hash , sndfst $1, fst $3), snd $1} /* somehref->{bar} */
-| term ARROW arrayref {sp_0($2); sp_0($3); Deref_with(I_array, sndfst $1, only_one $3), snd $1} /* somearef->[$element] */
-| term ARROW parenthesized {sp_0($2); sp_0($3); Deref_with(I_func , sndfst $1, List(sndfst $3)), snd $1} /* $subref->(@args) */
-| subscripted bracket_subscript {sp_0($2); Deref_with(I_hash , fst $1, fst $2), snd $1} /* $foo->[bar]{baz} */
-| subscripted arrayref {sp_0($2); Deref_with(I_array, fst $1, only_one $2), snd $1} /* $foo->[$bar][$baz] */
-| subscripted parenthesized {sp_0($2); Deref_with(I_func , fst $1, List(sndfst $2)), snd $1} /* $foo->{bar}(@args) */
+| variable PKG_SCOPE bracket_subscript {sp_0($2); sp_0($3); Too_complex, pos_range $1 $3} /* $foo::{something} */
+| scalar bracket_subscript {sp_0($2); Deref_with(I_hash , fst $1, fst $2), pos_range $1 $2} /* $foo{bar} */
+| scalar arrayref {sp_0($2); Deref_with(I_array, fst $1, only_one $2), pos_range $1 $2} /* $array[$element] */
+| term ARROW bracket_subscript {sp_0($2); sp_0($3); Deref_with(I_hash , sndfst $1, fst $3), pos_range $1 $3} /* somehref->{bar} */
+| term ARROW arrayref {sp_0($2); sp_0($3); Deref_with(I_array, sndfst $1, only_one $3), pos_range $1 $3} /* somearef->[$element] */
+| term ARROW parenthesized {sp_0($2); sp_0($3); Deref_with(I_func , sndfst $1, List(sndfst $3)), pos_range $1 $3} /* $subref->(@args) */
+| subscripted bracket_subscript {sp_0($2); Deref_with(I_hash , fst $1, fst $2), pos_range $1 $2} /* $foo->[bar]{baz} */
+| subscripted arrayref {sp_0($2); Deref_with(I_array, fst $1, only_one $2), pos_range $1 $2} /* $foo->[$bar][$baz] */
+| subscripted parenthesized {sp_0($2); Deref_with(I_func , fst $1, List(sndfst $2)), pos_range $1 $2} /* $foo->{bar}(@args) */
arrayref:
-| arrayref_start ARRAYREF_END {sp_0($2); fst $1, snd $1}
-| arrayref_start expr ARRAYREF_END {sp_0($3); fst $1 @ [sndfst $2], snd $1}
-| arrayref_start BRACKET expr BRACKET_END ARRAYREF_END {sp_p($2); sp_p($4); sp_0($5); fst $1 @ [Ref(I_hash, sndfst $3)], snd $1}
+| arrayref_start ARRAYREF_END {sp_0($2); fst $1, pos_range $1 $2}
+| arrayref_start expr ARRAYREF_END {sp_0($3); fst $1 @ [sndfst $2], 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)], pos_range $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), snd $1}
-| parenthesized_start expr PAREN_END {sp_0_or_cr($3); (P_paren(if fst $1 = [] then fstfst $2 else P_comma), fst $1 @ [sndfst $2]), snd $1}
-| 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)]), snd $1}
+| parenthesized_start PAREN_END {sp_0_or_cr($2); ((if fst $1 = [] then P_tok else P_paren P_comma), fst $1), 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 @ [sndfst $2]), 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)]), pos_range $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)], 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)], pos_range $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)], 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)], pos_range $1 $5}
my: /* Things that can be "my"'d */
-| MY parenthesized {List.map (fun e -> My e) (sndfst $2), snd $1}
-| MY scalar {[My(fst $2)], snd $1}
-| MY hash {[My(fst $2)], snd $1}
-| MY array {[My(fst $2)], snd $1}
+| MY parenthesized {List.map (fun e -> My e) (sndfst $2), pos_range $1 $2}
+| MY scalar {[My(fst $2)], pos_range $1 $2}
+| MY hash {[My(fst $2)], pos_range $1 $2}
+| MY array {[My(fst $2)], pos_range $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_lines_after_BRACKET($3); sp_p($4); Block(fst $3), snd $1} /* do { code */
+| DO BRACKET lines BRACKET_END %prec PREC_HIGH {sp_n($2); check_block_sub $3 $4; Block(fst $3), pos_range $1 $4} /* do { code */
bracket_subscript:
-| BRACKET expr BRACKET_END {sp_0($1); sp_0($2); sp_0($3); only_one_in_List $2, snd $1}
+| BRACKET expr BRACKET_END {sp_0($1); sp_0($2); sp_0($3); only_one_in_List $2, pos_range $1 $3}
| COMPACT_HASH_SUBSCRIPT {sp_0($1); to_String $1, snd $1}
variable:
@@ -359,7 +357,7 @@ variable:
word:
| bareword { $1 }
-| RAW_IDENT { to_Ident $1, snd $1 }
+| RAW_IDENT { to_Ident $1, snd $1}
comma: COMMA {$1} | RIGHT_ARROW {sp_p($1); $1}
@@ -371,19 +369,19 @@ 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 { 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}
word_paren:
-| BAREWORD_PAREN { Ident(None, fst $1, get_pos $1), snd $1 }
-| RAW_IDENT_PAREN { to_Ident $1, snd $1 }
-
-arraylen: ARRAYLEN_IDENT {Deref(I_arraylen, to_Ident $1), snd $1} | ARRAYLEN scalar {sp_0($2); Deref(I_arraylen, fst $2), snd $1} | ARRAYLEN BRACKET lines BRACKET_END {sp_0($2); sp_same $3 $4; Deref(I_arraylen, Block(fst $3)), snd $1}
-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 lines BRACKET_END {sp_0($2); sp_same $3 $4; Deref(I_scalar , Block(fst $3)), snd $1} | 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)), snd $1}
-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 lines BRACKET_END {sp_0($2); sp_same $3 $4; Deref(I_func , Block(fst $3)), snd $1}
-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 lines BRACKET_END {sp_0($2); sp_same $3 $4; Deref(I_array , Block(fst $3)), snd $1}
-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 lines BRACKET_END {sp_0($2); sp_same $3 $4; Deref(I_hash , Block(fst $3)), snd $1}
-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 lines BRACKET_END {sp_0($2); sp_same $3 $4; Deref(I_star , Block(fst $3)), snd $1}
+| BAREWORD_PAREN { Ident(None, fst $1, get_pos $1), snd $1}
+| RAW_IDENT_PAREN { to_Ident $1, snd $1}
+
+arraylen: ARRAYLEN_IDENT {Deref(I_arraylen, to_Ident $1), snd $1} | ARRAYLEN scalar {sp_0($2); Deref(I_arraylen, fst $2), snd $1} | ARRAYLEN BRACKET lines BRACKET_END {sp_0($2); check_block_ref $3 $4; sp_same $3 $4; Deref(I_arraylen, Block(fst $3)), pos_range $1 $4}
+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 lines BRACKET_END {sp_0($2); check_block_ref $3 $4; sp_same $3 $4; Deref(I_scalar , Block(fst $3)), pos_range $1 $4} | 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)), 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 lines BRACKET_END {sp_0($2); check_block_ref $3 $4; sp_same $3 $4; Deref(I_func , Block(fst $3)), pos_range $1 $4}
+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 lines BRACKET_END {sp_0($2); check_block_ref $3 $4; sp_same $3 $4; Deref(I_array , Block(fst $3)), pos_range $1 $4}
+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 lines BRACKET_END {sp_0($2); check_block_ref $3 $4; sp_same $3 $4; Deref(I_hash , Block(fst $3)), pos_range $1 $4}
+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 lines BRACKET_END {sp_0($2); check_block_ref $3 $4; sp_same $3 $4; Deref(I_star , Block(fst $3)), pos_range $1 $4}
expr_or_empty: {Block [], (Space_none, bpos)} | expr {sndfst $1, snd $1}
diff --git a/perl_checker.src/parser_helper.ml b/perl_checker.src/parser_helper.ml
index 4be59a0..e489050 100644
--- a/perl_checker.src/parser_helper.ml
+++ b/perl_checker.src/parser_helper.ml
@@ -5,6 +5,7 @@ open Printf
let bpos = -1, -1
let raw_pos2pos(a, b) = !Info.current_file, a, b
+let 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 var_dollar_ = Deref(I_scalar, Ident(None, "_", raw_pos2pos bpos))
let var_STDOUT = Deref(I_star, Ident(None, "STDOUT", raw_pos2pos bpos))
@@ -44,6 +45,7 @@ let die_with_pos raw_pos msg = failwith (msg_with_pos raw_pos msg)
let warn raw_pos msg = prerr_endline (msg_with_pos raw_pos msg)
let die_rule msg = die_with_pos (Parsing.symbol_start(), Parsing.symbol_end()) msg
+let warn_rule msg = warn (Parsing.symbol_start(), Parsing.symbol_end()) msg
let debug msg = if false then prerr_endline msg
let warn_too_many_space start = warn (start, start) "you should have only one space here"
@@ -167,16 +169,6 @@ 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 op prio s (_, both) = prio, (((), both), s)
-let op_p prio s e = sp_p e ; op prio s e
-
-let call_op((prio, (prev_ter, op)), ter, para) =
- sp_same prev_ter ter ;
- prio, Call_op(op, para)
-
-let check_lines_after_BRACKET (l, both) =
- (match l with Semi_colon :: _ -> sp_0 | _ -> sp_p)(l, both)
-
let check_word_alone (word, _) =
if string_of_Ident word = "time" then die_rule "please use time() instead of time";
word
@@ -205,9 +197,44 @@ let check_package t =
| Package _ :: _ -> ()
| _ -> warn (0, 0) (sprintf "module %s does not have \"package xxxx;\" on its first line" !Info.current_file)
+let check_my op para (_, pos) =
+ match op, para with
+ | "=", [List [My _]; Ident(None, "undef", _)] -> warn pos "no need to initialize variable, it's done by default"
+ | "=", [List [My _]; List[]] ->
+ if Info.is_on_same_line_current pos then warn pos "no need to initialize variables, it's done by default"
+ | _ -> ()
+
+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 ;
+
+ if space <> Space_cr then
+ (if l <> [] && last l = Semi_colon then warn (end_, end_) "spurious \";\" before closing block")
+ )
+
+let check_block_ref (l, (_, (_, end_)) as ter_lines) (_, (space, _) as ter_BRACKET_END) =
+ 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 ;
+
+ if space <> Space_cr then
+ (if l <> [] && last l = Semi_colon then warn (end_, end_) "spurious \";\" before closing block")
+
+
let to_Ident ((fq, name), (_, pos)) = Ident(fq, name, raw_pos2pos pos)
let to_String (s, (_, pos)) = String(s, raw_pos2pos pos)
+let op prio s (_, both) = prio, (((), both), s)
+let op_p prio s e = sp_p e ; op prio s e
+
+let call_op((prio, (prev_ter, op)), ter, para) =
+ sp_same prev_ter ter ;
+ check_my op para (snd ter);
+ prio, Call_op(op, para)
+
let rec only_one (l, (spaces, pos)) =
match l with
| [List l'] -> only_one (l', (spaces, pos))
diff --git a/perl_checker.src/parser_helper.mli b/perl_checker.src/parser_helper.mli
index ad0a5db..7c68b7d 100644
--- a/perl_checker.src/parser_helper.mli
+++ b/perl_checker.src/parser_helper.mli
@@ -1,5 +1,7 @@
val bpos : int * int
val raw_pos2pos : 'a * 'b -> string * 'a * 'b
+val pos_range :
+ 'a * ('b * (int * int)) -> 'c * ('d * (int * int)) -> 'b * (int * int)
val get_pos : 'a * ('b * ('c * 'd)) -> string * 'c * 'd
val var_dollar_ : Types.fromparser
val var_STDOUT : Types.fromparser
@@ -13,6 +15,7 @@ val msg_with_pos : int * int -> string -> string
val die_with_pos : int * int -> string -> 'a
val warn : int * int -> string -> unit
val die_rule : string -> 'a
+val warn_rule : string -> unit
val debug : string -> unit
val warn_too_many_space : int -> unit
val warn_no_space : int -> unit
@@ -39,18 +42,6 @@ val sp_cr : 'a * (Types.spaces * (int * 'b)) -> unit
val sp_same :
'a * (Types.spaces * (int * 'b)) ->
'c * (Types.spaces * (int * 'd)) -> unit
-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)
-val call_op :
- ('a * (('b * (Types.spaces * (int * 'c))) * string)) *
- ('d * (Types.spaces * (int * 'e))) * Types.fromparser list ->
- 'a * Types.fromparser
-val check_lines_after_BRACKET :
- Types.fromparser list * (Types.spaces * (int * 'a)) -> unit
val check_word_alone : Types.fromparser * 'a -> Types.fromparser
val check_parenthesized_first_argexpr :
string ->
@@ -58,9 +49,26 @@ val check_parenthesized_first_argexpr :
val check_foreach : string * ('a * (int * int)) -> unit
val check_for : string * ('a * (int * int)) -> unit
val check_package : Types.fromparser list -> unit
+val check_my : string -> Types.fromparser list -> 'a * (int * int) -> unit
+val check_block_sub :
+ Types.fromparser list * (Types.spaces * (int * int)) ->
+ 'a * (Types.spaces * (int * 'b)) -> unit
+val check_block_ref :
+ Types.fromparser list * (Types.spaces * (int * int)) ->
+ 'a * (Types.spaces * (int * 'b)) -> unit
val to_Ident :
(string option * string) * ('a * (int * int)) -> Types.fromparser
val to_String : string * ('a * (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)
+val call_op :
+ ('a * (('b * (Types.spaces * (int * 'c))) * string)) *
+ ('d * (Types.spaces * (int * int))) * Types.fromparser list ->
+ 'a * Types.fromparser
val only_one : Types.fromparser list * ('a * (int * int)) -> Types.fromparser
val only_one_in_List :
('a * Types.fromparser) * ('b * (int * int)) -> Types.fromparser
diff --git a/perl_checker.src/types.mli b/perl_checker.src/types.mli
index 6d61303..567c0c5 100644
--- a/perl_checker.src/types.mli
+++ b/perl_checker.src/types.mli
@@ -35,7 +35,7 @@ type fromparser =
| Method_call of fromparser * fromparser * fromparser list
| Method_callP of fromparser * fromparser * fromparser list
- | Anonymous_sub of fromparser
+ | Anonymous_sub of fromparser list
| My of fromparser
| Local of fromparser
| Use of fromparser * fromparser list