|
| 1 | +# Copyright (C) 2014,2015 American Registry for Internet Numbers (ARIN) |
| 2 | +# |
| 3 | +# Permission to use, copy, modify, and/or distribute this software for any |
| 4 | +# purpose with or without fee is hereby granted, provided that the above |
| 5 | +# copyright notice and this permission notice appear in all copies. |
| 6 | +# |
| 7 | +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 8 | +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 9 | +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| 10 | +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 11 | +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 12 | +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR |
| 13 | +# IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 14 | + |
| 15 | +# Configuration |
| 16 | +$parslet_src_file = "../lib/jcr/parser.rb" |
| 17 | +$abnf_out_file = "jcr-abnf.txt" |
| 18 | +$margin = 0 |
| 19 | +$indent = 19 |
| 20 | +$keyword_indent = 30 |
| 21 | + |
| 22 | +# Primary data stores |
| 23 | +$mappings = {} |
| 24 | +$lines = [] |
| 25 | +$keywords = {} |
| 26 | + |
| 27 | +def main |
| 28 | + read_parslet_def |
| 29 | + write_abnf |
| 30 | +end |
| 31 | + |
| 32 | +def read_parslet_def |
| 33 | + File.foreach( $parslet_src_file ) { |line| |
| 34 | + conditionally_grab_mapping( line ) |
| 35 | + conditionally_grab_abnf( line ) |
| 36 | + conditionally_grab_keywords( line ) |
| 37 | + } |
| 38 | +end |
| 39 | + |
| 40 | +def conditionally_grab_mapping( line ) |
| 41 | + # Example haystack: #/ spcCmnt -> sp-cmt |
| 42 | + if m = %r|^\s*#/\s*([\w?]+)\s*->\s*(.*)|.match( line ) |
| 43 | + key, value = m.captures |
| 44 | + $mappings[key] = value |
| 45 | + end |
| 46 | +end |
| 47 | + |
| 48 | +def conditionally_grab_abnf( line ) |
| 49 | + # Example haystack: #! spcCmnt = spaces / comment |
| 50 | + if m = /^\s*#!\s*(.*)/.match( line ) |
| 51 | + $lines << m[1] |
| 52 | + end |
| 53 | +end |
| 54 | + |
| 55 | +def conditionally_grab_keywords( line ) |
| 56 | + # Example haystack: #> jcr-version-kw = "jcr-version" |
| 57 | + if m = /^\s*#>\s*([\w_\-]+kw)(\s*=\s*)"([^"]+)"/.match( line ) |
| 58 | + name, equals, keyword = m.captures |
| 59 | + ascii_codes = keyword.chars.map{ |c| "%02X" % c.ord }.join( '.' ) |
| 60 | + comment_padding = ' ' * [($keyword_indent - 3*keyword.length), 0].max |
| 61 | + line = name + equals + '%x' + ascii_codes + comment_padding + ' ; "' + keyword + '"' |
| 62 | + $keywords[name] = line |
| 63 | + end |
| 64 | +end |
| 65 | + |
| 66 | +def write_abnf |
| 67 | + File.open( $abnf_out_file, 'w' ) { |fout| |
| 68 | + print_captured_abnf( fout ) |
| 69 | + print_keywords( fout ) |
| 70 | + print_referenced_rfc5234_rules( fout ) |
| 71 | + } |
| 72 | +end |
| 73 | + |
| 74 | +def print_captured_abnf( fout ) |
| 75 | + for line in $lines |
| 76 | + line = do_name_mappings( line ) |
| 77 | + pretty_print( line, fout ) |
| 78 | + end |
| 79 | +end |
| 80 | + |
| 81 | +def do_name_mappings( line ) |
| 82 | + for mapping_from in mapping_keys_sorted_longest_first |
| 83 | + line.gsub!( mapping_from, $mappings[mapping_from] ) |
| 84 | + end |
| 85 | + line.gsub!( '_', '-' ) |
| 86 | + return line |
| 87 | +end |
| 88 | + |
| 89 | +def mapping_keys_sorted_longest_first |
| 90 | + return $mappings.keys.sort_by { |m| m.length }.reverse |
| 91 | +end |
| 92 | + |
| 93 | +def print_keywords( fout ) |
| 94 | + pretty_print( '', fout ) |
| 95 | + pretty_print( ';; Keywords', fout ) |
| 96 | + for kw in $keywords.keys().sort |
| 97 | + pretty_print( $keywords[kw], fout ) |
| 98 | + end |
| 99 | +end |
| 100 | + |
| 101 | +def print_referenced_rfc5234_rules( fout ) |
| 102 | + rfc5234_core_rules = [ |
| 103 | + 'ALPHA = %x41-5A / %x61-7A ; A-Z / a-z', |
| 104 | + 'CR = %x0D ; carriage return', |
| 105 | + 'DIGIT = %x30-39 ; 0-9', |
| 106 | + # 'DQUOTE = %x22 ; " (Double Quote)', |
| 107 | + 'HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"', |
| 108 | + 'HTAB = %x09 ; horizontal tab', |
| 109 | + 'LF = %x0A ; linefeed', |
| 110 | + 'SP = %x20 ; space', |
| 111 | + 'WSP = SP / HTAB ; white space' |
| 112 | + ] |
| 113 | + pretty_print( '', fout ) |
| 114 | + pretty_print( ';; Referenced RFC 5234 Core Rules', fout ) |
| 115 | + for rule in rfc5234_core_rules |
| 116 | + pretty_print( rule, fout ) |
| 117 | + end |
| 118 | +end |
| 119 | + |
| 120 | +def pretty_print( line, fout ) |
| 121 | + if is_blank_line?( line ) |
| 122 | + fout.write( "\n" ) |
| 123 | + else |
| 124 | + fout.write( ' ' * $margin ) |
| 125 | + if is_block_comment?( line ) |
| 126 | + fout.write( line + "\n" ) |
| 127 | + elsif comment = local_comment( line ) |
| 128 | + fout.write( ' ' * $indent + comment + "\n" ) |
| 129 | + elsif mapping = abnf_mapping( line ) |
| 130 | + name, expansion = mapping |
| 131 | + equals = ' = ' |
| 132 | + padding_needed = [ $indent - (name.length + equals.length), 0 ].max |
| 133 | + padding = ' ' * padding_needed |
| 134 | + fout.write( name + padding + equals + expansion + "\n" ) |
| 135 | + else |
| 136 | + fout.write( ' ' * $indent + line + "\n" ) # A 2nd/3rd expression line |
| 137 | + end |
| 138 | + end |
| 139 | +end |
| 140 | + |
| 141 | +def is_blank_line?( line ) |
| 142 | + return /^\s*$/.match( line ) |
| 143 | +end |
| 144 | + |
| 145 | +def is_block_comment?( line ) |
| 146 | + return /^\s*;;/.match( line ) |
| 147 | +end |
| 148 | + |
| 149 | +def local_comment( line ) |
| 150 | + return (m = /^\s*(;.*)/.match( line )) ? m[1] : false |
| 151 | +end |
| 152 | + |
| 153 | +def abnf_mapping( line ) |
| 154 | + return (m = /([\w_\-]+)\s*=\s*(.*)/.match( line )) ? [m[1], m[2]] : false |
| 155 | +end |
| 156 | + |
| 157 | +main |
0 commit comments