1#!/bin/sh 2 3# Copyright (C) 2019-2021 Internet Systems Consortium, Inc. ("ISC") 4# 5# This Source Code Form is subject to the terms of the Mozilla Public 6# License, v. 2.0. If a copy of the MPL was not distributed with this 7# file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 9# Get BNF grammars from bison files 10# 11# This script takes 1 or 2 parameters: 12# 13# Basic usage: 14# ./extract_bnf.sh <bison-file-base-name> - will generate BNF notation in plain text 15# 16# Markdown: 17# ./extract_bnf.sh <bison-file-base-name> --markdown 18 19# Check if there are one or two arguments 20if [ $# -lt 1 ]; then 21 echo "extract_bnf.sh <bison-file-base-name> [--markdown <name>]" 22 exit 1 23fi 24 25markdown=0 26if [ $# -eq 3 ] && [ "$2" = "--markdown" ]; then 27 markdown=1 28 md_name=$3 29fi 30 31# Get the output file 32base=$1 33output= 34now=$(date +"%Y-%m-%-d %H:%m") 35 36header="Grammar generated on $now. See Chapter $md_name for an explanation." 37 38if [ -f "${base}.yy" ]; then 39 # We want to explicitly set the language to English. Otherwise 40 # bison may produce language specific wording (like "symbole terminalne" 41 # if you system is set to Polish, rather than "Terminals") and this will 42 # confuse our script. 43 LANG=en_US LANGUAGE=en_US @YACC@ -v "${base}.yy" -o output 44 rm -f output output.h *.hh 45 mv output.output /tmp/output 46 output=/tmp/output 47else 48 echo "cannot find ${base}.yy" 49 exit 1 50fi 51 52# Process the output file 53# - extract the grammar part 54# - remove line numbers 55# - remove intermediate productions 56# - remove intermediate non-terminals 57# - replace standard tokens 58# - replace : by BNF ::= 59# - squeeze multiple blank lines 60 61cat $output |\ 62@AWK@ '/^Terminal/ { exit }; // { print }' |\ 63@AWK@ '// { gsub("^ +[0-9]+ ", ""); print }' |\ 64@AWK@ '/^\$@[0-9]+:/ { next }; // { print }' |\ 65@AWK@ '// { gsub(" \\$@[0-9]+ ", " ") ; print }' |\ 66@AWK@ '// { gsub("\"constant string\"", "STRING"); print }' |\ 67@AWK@ '// { gsub("\"integer\"", "INTEGER"); print }' |\ 68@AWK@ '// { gsub("\"floating point\"", "FLOAT"); print }' |\ 69@AWK@ '// { gsub("\"boolean\"", "BOOLEAN"); print }' |\ 70@AWK@ '// { gsub("\"null\"", "NULL"); print }' |\ 71@AWK@ '// { gsub("\"constant hexstring\"", "HEXSTRING"); print }' |\ 72@AWK@ '// { gsub("\"option name\"", "OPTION_NAME"); print }' |\ 73@AWK@ '// { gsub("\"ip address\"", "IP_ADDRESS"); print }' |\ 74@AWK@ '// { gsub("\"end of file\"", "EOF"); print }' |\ 75@AWK@ '// { gsub("%empty", ""); print }' |\ 76@AWK@ '// { gsub(": ", " ::= "); print }' |\ 77cat -s > $output.2 78 79if [ "$markdown" -eq 1 ]; then 80 cat > $output.3 << EOF 81 82$header 83 84.. code-block:: BNF 85 :linenos: 86 87EOF 88 cat $output.2 | @AWK@ '/^.+$/ { print " ",$0 }; /^$/ { print } ' >> $output.3 89 cat $output.3 90else 91 cat $output.2 92fi 93