ENH: add support for m4 filtering of lemon grammars

This commit is contained in:
Mark Olesen 2019-10-11 09:24:04 +02:00 committed by Andrew Heather
parent 28a9cde028
commit 1ddcdb083e
3 changed files with 157 additions and 44 deletions

View File

@ -1,4 +1,4 @@
SUFFIXES += .ly .lyy
SUFFIXES += .ly .lyy .lyy-m4
lytoo = $E $(call QUIET_MESSAGE,lemon,$(<F)) \
$(WM_SCHEDULER) $(WM_SCRIPTS)/wrap-lemon -d$(@D) $< $(AND) \
@ -7,3 +7,11 @@ lytoo = $E $(call QUIET_MESSAGE,lemon,$(<F)) \
lyytoo = $E $(call QUIET_MESSAGE,lemon,$(<F)) \
$(WM_SCHEDULER) $(WM_SCRIPTS)/wrap-lemon -d$(@D) -ecc $< $(AND) \
$(CC) $(c++FLAGS) -c $(@D)/$(*F).cc -o $@
# Retain intermediate files (-with-debug) to help when something goes wrong,
# and to verify that the generated grammar looks correct.
lyy-m4too = $E $(call QUIET_MESSAGE,lemon-m4,$(<F)) \
$(WM_SCHEDULER) $(WM_SCRIPTS)/wrap-lemon -with-debug -d$(@D) -ecc $< $(AND) \
$(CC) $(c++FLAGS) -c $(@D)/$(*F).cc -o $@
#------------------------------------------------------------------------------

View File

@ -29,8 +29,10 @@ options:
-parser=FILE Generate lemon parser header
-scanner=FILE Generate ragel scanner code
-parser Use 'LemonParser.lyy' for non-prefixed parser name
-parser-m4 Use 'LemonParser.lyy-m4' for non-prefixed parser name
-scanner Use 'Scanner.rl' for non-prefixed scanner name
-code Generate lemon parser code
-with-debug Retain intermediate files (eg, m4 output)
-remove Remove generated code
-h, -help Print the usage
@ -44,7 +46,7 @@ USAGE
# Parse arguments and options
#------------------------------------------------------------------------------
unset prefix parser scanner optCode optRemove
unset prefix parser scanner optCode optDebug optRemove
while [ "$#" -gt 0 ]
do
case "$1" in
@ -55,8 +57,10 @@ do
(-scanner=*) scanner="${1#*=}" ;;
(-parser) parser=LemonParser.lyy ;;
(-parser-m4) parser=LemonParser.lyy-m4 ;;
(-scanner) scanner=Scanner.rl ;;
(-code) optCode=true ;;
(-with-debug) optDebug=true ;;
(-remove) optRemove=true ;;
(*) break ;;
@ -98,21 +102,28 @@ esac
case "$parser" in
(*.ly | *.lyy)
(*.ly | *.lyy | *.ly*m4)
extCode=cc
input="${prefix}${parser}"
output="${parser%.*}.h"
# Pass -with-debug to wrap-lemon
[ -n "$optDebug" ] && optDebug="-with-debug"
# Additional message (eg, using m4 etc)
unset message
case "$parser" in (*m4) message=", using m4 filtering" ;; esac
if [ "$optRemove" = true ]
then
removeFile "$output" "lemon header"
elif [ "$optCode" = true ]
then
echo "Generating lemon parser code ($extCode)"
"$WM_PROJECT_DIR/wmake/scripts/wrap-lemon" -e"$extCode" -s "$input"
echo "Generating lemon parser code ($extCode)$message"
"$WM_PROJECT_DIR/wmake/scripts/wrap-lemon" $optDebug -e"$extCode" -s "$input"
else
echo "Generating lemon parser header"
"$WM_PROJECT_DIR/wmake/scripts/wrap-lemon" -header -s "$input"
echo "Generating lemon parser header$message"
"$WM_PROJECT_DIR/wmake/scripts/wrap-lemon" $optDebug -header -s "$input"
fi
echo
;;

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
#------------------------------------------------------------------------------
# ========= |
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
@ -14,7 +14,7 @@
# wrap-lemon
#
# Usage
# wrap-lemon [lemon-options]
# wrap-lemon [options] [lemon args/options]
#
# Description
# A wrapper to use lemon compiled with OpenFOAM with the appropriate
@ -38,9 +38,13 @@ Usage: ${0##*/} [options] [lemon args/options]
options:
-header Generate header only, suppressing other output
-with-debug Retain intermediate files (eg, m4 output)
-h, -help Print the usage
A lemon wrapper using predefined executable and skeleton locations
A lemon wrapper using predefined executable and skeleton locations.
Files ending with 'm4' (eg, .lyym4, .lyy-m4) will be filtered through
the m4(1) macro processor and lemon will be called with 'm4' as a macro
definition, which can be used in conditions (%ifdef m4, %ifndef m4)
USAGE
exit 1
@ -50,56 +54,146 @@ USAGE
# Parse arguments and options
#------------------------------------------------------------------------------
# wrap-lemon -header-only
unset optHeader
# wrap-lemon -header
unset optHeader optDebug
while [ "$#" -gt 0 ]
do
case "$1" in
(-h | -help*) usage ;;
(-h | -help*) usage ;;
(-header*) optHeader=true ;;
(-head*) optHeader=true ;;
(-with-debug) optDebug=true ;;
(*) break ;;
esac
shift
done
#------------------------------------------------------------------------------
# Get some information based on the lemon options
# * '-dXX' for the output directory
# * '-eXX' for the output extension
# The last argument is the input file
# No special handling
if [ -z "$optHeader" ]
unset tmpDir tmpFile outputDir parser extCode
findLemonOptions()
{
while [ "$#" -gt 1 ]
do
case "$1" in
(-d*) outputDir="${1#-d}" ;;
(-e*) extCode="${1#-e}" ;;
esac
shift
done
if [ "$#" -eq 1 ]
then
parser="$1"
fi
}
findLemonOptions "$@"
# Detect m4 use (defines lemon macro too) and get extension without m4
unset extLemon usingMacros
case "$parser" in
(*.*m4)
extLemon=".${parser##*.}" # The extension (with dot)
extLemon="${extLemon%m4}" # Without trailing m4
extLemon="${extLemon/%[-_]/}" # Without - or _ separators
usingMacros="-Dm4"
;;
esac
rc=1 # Assume some failure
if [ -n "$optHeader" ]
then
"$lemon" "$skel" $*
exit $?
# Drop last argument (the parser input file)
set -- "${@:1:${#}-1}"
# Header only, which means we create a temp directory for the output
tmpDir="lemonWrapper-$$"
rm -rf "$tmpDir" 2>/dev/null
mkdir "$tmpDir" 2>/dev/null
if [ -n "$usingMacros" ]
then
# Using m4 - redirect to a temporary file
tmpFile="$tmpDir/${parser##*/}"
tmpFile="${tmpFile%.*}$extLemon" # Eg, from .lyy-m4 -> .lyy
if m4 "$parser" > "$tmpFile" && [ -f "$tmpFile" ]
then
parser="$tmpFile"
else
echo "m4 stage failed on $parser" 2>/dev/null
fi
fi
# DO WE WANT THIS?
# trap 'rm -f $tmpDir 2>/dev/null; exit $rc' EXIT TERM INT
"$lemon" "$skel" "-d$tmpDir" "$@" $usingMacros "$parser"
rc=$?
for src in "$tmpDir"/*.h
do
dst="${src##*/}"
if [ -f "$src" ]
then
if ! cmp "$src" "$dst" 2>/dev/null
then
mv "$src" "$dst"
echo "Updating $dst" 1>&2
fi
fi
done
rm -rf "$tmpDir" 2>/dev/null
elif [ -n "$usingMacros" ]
then
# Drop last argument (the parser input file)
set -- "${@:1:${#}-1}"
# Filter via m4
if [ -n "$outputDir" ]
then
tmpFile="$outputDir/${parser##*/}"
else
tmpFile="${parser}"
fi
tmpFile="${tmpFile%.*}$extLemon" # Eg, from .lyy-m4 -> .lyy
# DO WE WANT THIS?
# trap 'rm -f $tmpFile 2>/dev/null; exit $rc' EXIT TERM INT
if m4 "$parser" > "$tmpFile" && [ -f "$tmpFile" ]
then
"$lemon" "$skel" "$@" $usingMacros "$tmpFile"
rc=$?
else
echo "m4 stage failed on $parser" 2>/dev/null
fi
if [ -n "$optDebug" ]
then
echo "Retaining intermediate: $tmpFile" 2>/dev/null
else
rm -f "$tmpFile" 2>/dev/null
fi
else
# No special handling
"$lemon" "$skel" "$@"
rc=$?
fi
# Header only, which means we create a temp directory for the output
tmpDir="lemonWrapper-$$"
rm -rf "$tmpDir" 2>/dev/null
mkdir "$tmpDir" 2>/dev/null
# DO WE WANT THIS?
# trap 'rm -f $tmpDir 2>/dev/null; exit $rc' EXIT TERM INT
"$lemon" "$skel" "-d$tmpDir" $*
rc=$?
for src in "$tmpDir"/*.h
do
dst="${src##*/}"
if [ -f "$src" ]
then
if ! cmp "$src" "$dst" 2>/dev/null
then
mv "$src" "$dst"
echo "Updating $dst" 1>&2
fi
fi
done
rm -rf "$tmpDir" 2>/dev/null
exit "$rc" # Exit with lemon return code
#------------------------------------------------------------------------------