c0ee726fb2
Preprocessor is now a library installed by opam. Replaced ligolang@gmail.com by contact@ligolang.org in opam files. Reformatted some opam files. Removed #line directive from preprocessor. Added to the interface of ParserUnit. Script messages.sh now checks the identity of .msg and .msg.old to avoid undue warning about possibly different LR items.
227 lines
6.1 KiB
Bash
Executable File
227 lines
6.1 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# This script uses Menhir to generate the exhaustive list of errors
|
|
# for a given parser specification. The generated file has to be
|
|
# filled with the error messages. The script must be called in the
|
|
# same directory where the parser specification and external token
|
|
# specifications are located, in accordance with the convention of the
|
|
# LIGO compiler source code.
|
|
|
|
#set -x
|
|
|
|
# ====================================================================
|
|
# General Settings and wrappers
|
|
|
|
script=$(basename $0)
|
|
|
|
print_nl () { test "$quiet" != "yes" && echo "$1"; }
|
|
|
|
print () { test "$quiet" != "yes" && printf "$1"; }
|
|
|
|
fatal_error () {
|
|
echo "$script: fatal error:"
|
|
echo "$1" 1>&2
|
|
exit 1
|
|
}
|
|
|
|
warn () {
|
|
print_nl "$script: warning:"
|
|
print_nl "$1"
|
|
}
|
|
|
|
failed () {
|
|
printf "\033[31mFAILED$1\033[0m\n"
|
|
}
|
|
|
|
emphasise () {
|
|
printf "\033[31m$1\033[0m\n"
|
|
}
|
|
|
|
# ====================================================================
|
|
# Parsing loop
|
|
#
|
|
while : ; do
|
|
case "$1" in
|
|
"") break;;
|
|
--par-tokens=*)
|
|
if test -n "$par_tokens"; then
|
|
fatal_error "Repeated option --par-tokens."; fi
|
|
par_tokens=$(expr "$1" : "[^=]*=\(.*\)")
|
|
;;
|
|
--par-tokens)
|
|
no_eq=$1
|
|
break
|
|
;;
|
|
--lex-tokens=*)
|
|
if test -n "$lex_tokens"; then
|
|
fatal_error "Repeated option --lex-tokens."; fi
|
|
lex_tokens=$(expr "$1" : "[^=]*=\(.*\)")
|
|
;;
|
|
--lex-tokens)
|
|
no_eq=$1
|
|
break
|
|
;;
|
|
-h | --help | -help)
|
|
help=yes
|
|
;;
|
|
# Invalid option
|
|
#
|
|
-*)
|
|
fatal_error "Invalid option \"$1\"."
|
|
;;
|
|
# Invalid argument
|
|
#
|
|
*)
|
|
if test -n "$parser"; then
|
|
fatal_error "Only one Menhir specification allowed."; fi
|
|
parser=$1
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# ====================================================================
|
|
# Help
|
|
#
|
|
usage () {
|
|
cat <<EOF
|
|
Usage: $(basename $0) [-h|--help] --lex-tokens=<lex_tokens>.mli \
|
|
--par-tokens=<par_tokens>.mly <parser>.mly
|
|
|
|
Generates in place <parser>.msg, the form containing the exhaustive
|
|
list of errors for the LR automaton generated by Menhir from
|
|
<parser>.mly, <par_tokens>.mly and <lex_tokens>.mli. The file
|
|
<parser>.msg is meant to be edited and filled with the error messages.
|
|
|
|
The following options, if given, must be given only once.
|
|
|
|
Display control:
|
|
-h, --help display this help and exit
|
|
Mandatory options:
|
|
--lex-tokens=<name>.mli the lexical tokens
|
|
--par-tokens=<name>.mly the syntactical tokens
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
if test "$help" = "yes"; then usage; fi
|
|
|
|
# ====================================================================
|
|
# Checking the command-line options and arguments and applying some of
|
|
# them.
|
|
|
|
# It is a common mistake to forget the "=" in GNU long-option style.
|
|
|
|
if test -n "$no_eq"; then
|
|
fatal_error "Long option style $no_eq must be followed by \"=\"."
|
|
fi
|
|
|
|
# Checking the parser and tokens
|
|
|
|
if test -z "$parser"; then
|
|
fatal_error "No parser specification."; fi
|
|
|
|
if test -z "$par_tokens"; then
|
|
fatal_error "No syntactical tokens specification (use --par-tokens)."; fi
|
|
|
|
if test -z "$lex_tokens"; then
|
|
fatal_error "No lexical tokens specification (use --lex-tokens)."; fi
|
|
|
|
if test ! -e "$parser"; then
|
|
fatal_error "Parser specification \"$parser\" not found."; fi
|
|
|
|
if test ! -e "$lex_tokens"; then
|
|
fatal_error "Lexical tokens specification \"$lex_tokens\" not found."; fi
|
|
|
|
if test ! -e "$par_tokens"; then
|
|
fatal_error "Syntactical tokens specification \"$par_tokens\" not found."; fi
|
|
|
|
parser_ext=$(expr "$parser" : ".*\.mly$")
|
|
if test "$parser_ext" = "0"; then
|
|
fatal_error "Parser specification must have extension \".mly\"."; fi
|
|
|
|
par_tokens_ext=$(expr "$par_tokens" : ".*\.mly$")
|
|
if test "$par_tokens_ext" = "0"; then
|
|
fatal_error "Syntactical tokens specification must have extension \".mly\"."
|
|
fi
|
|
|
|
lex_tokens_ext=$(expr "$lex_tokens" : ".*\.mli$")
|
|
if test "$lex_tokens_ext" = "0"; then
|
|
fatal_error "Lexical tokens specification must have extension \".mli\"."
|
|
fi
|
|
|
|
mly=$parser
|
|
parser_base=$(basename $mly .mly)
|
|
par_tokens_base=$(basename $par_tokens .mly)
|
|
lex_tokens_base=$(basename $lex_tokens .mli)
|
|
|
|
# ====================================================================
|
|
# Menhir's flags
|
|
|
|
flags="--table --strict --external-tokens $lex_tokens_base \
|
|
--base $parser_base $par_tokens"
|
|
|
|
# ====================================================================
|
|
# Generating error messages with Menhir
|
|
|
|
msg=$parser_base.msg
|
|
err=.$msg.err
|
|
out=.$mly.out
|
|
|
|
if test -e $msg; then mv -f $msg $msg.old; echo "Saved $msg."; fi
|
|
|
|
printf "Making new $msg from $mly... "
|
|
menhir --list-errors $flags $mly > $msg 2>$out
|
|
|
|
if test "$?" = "0"; then
|
|
sentences=$(grep "YOUR SYNTAX ERROR MESSAGE HERE" $msg | wc -l)
|
|
if test -z "$sentences"; then printf "done.\n"
|
|
else
|
|
spurious=$(grep WARNING $msg | wc -l)
|
|
printf "done:\n"
|
|
printf "There are %s error sentences, %s with spurious reductions.\n" \
|
|
$sentences $spurious; fi
|
|
if test -s $out; then cat $out; fi
|
|
if test -f $msg.old; then
|
|
printf "Checking inclusion of mappings (new in old)... "
|
|
menhir --compare-errors $msg \
|
|
--compare-errors $msg.old \
|
|
$flags $mly 2> $out
|
|
if test "$?" = "0"; then
|
|
if test -s $out; then
|
|
printf "done:\n"
|
|
cat $out
|
|
else printf "done.\n"; fi
|
|
rm -f $out
|
|
printf "Updating $msg... "
|
|
menhir --update-errors $msg.old \
|
|
$flags $mly > $msg 2> $err
|
|
if test "$?" = "0"; then
|
|
if $(diff $msg $msg.old 2>&1 > /dev/null); then
|
|
echo "done."
|
|
else
|
|
printf "done:\n"
|
|
emphasise "Warning: The LR items may have changed."
|
|
emphasise "> Check your error messages again."
|
|
fi
|
|
rm -f $err
|
|
else failed "."
|
|
touch $err
|
|
mv -f $msg.old $msg
|
|
echo "Restored $msg."; fi
|
|
else failed ":"
|
|
mv -f $out $err
|
|
sed -i -e "s/\.msg/.msg.new/g" \
|
|
-e "s/\.new\.old//g" $err
|
|
mv -f $msg $msg.new
|
|
emphasise "See $err and update $msg."
|
|
echo "The default messages are in $msg.new."
|
|
mv -f $msg.old $msg
|
|
echo "Restored $msg."; fi; fi
|
|
else
|
|
failed ":"
|
|
mv -f $out $err
|
|
emphasise "> See $err."
|
|
mv -f $msg.old $msg
|
|
echo "Restored $msg."
|
|
fi
|