#!/usr/bin/ruby #******************************************************************************* #* Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated. #* All rights reserved. This program and the accompanying materials #* are made available under the terms of the Eclipse Public License v1.0 #* which accompanies this distribution, and is available at #* http://www.eclipse.org/legal/epl-v10.html #* #* File: $Source: /cvsroot/slrp/glitter/com.ibm.adtech.glitter/grammar/bnf2jj.rb,v $ #* Created by: Lee Feigenbaum ( feigenbl@us.ibm.com ) #* Created on: 10/23/2006 #* Revision: $Id: bnf2jj.rb 164 2007-07-31 14:11:09Z mroy $ #* #* Contributors: IBM Corporation - initial API and implementation #*******************************************************************************/ def is_nonterminal token token =~ /^\w*[a-z]\w*(\(\))?$/ end def is_terminal token token =~ /^[A-Z_]+$/ end def print_rule lhs, rhs, nt # ensure whitespace before certain # characters rhs.gsub!(/([?*+\(\)])/) {|c| " " + c} # wrap terminals in angle brackets # add parens to nonterminals rhs = rhs.split(/\s+/).inject([]) { |arr, token| if is_nonterminal token arr << "#{token}()" elsif is_terminal token arr << "<#{token}>" else if (token == '?' || token == '*' || token == '+') && is_nonterminal(arr[-1]) arr[-1] = "(#{arr[-1]})" end arr << token end }.join("\n") if nt puts < } EOF end end if ARGV.length != 1 or not File.exist? ARGV[0] puts "Usage: #{$0} grammar.bnf" exit end nonterminals = true last_line = {'nt' => nil, 'rhs' => nil} File.open(ARGV[0]) { |f| f.each_line { |line| next unless line =~ /\S/ line.chomp! if line =~ /^\[\d+\]\s+(\w+)\s+::=\s+(.+)$/ if last_line['nt'] print_rule(last_line['nt'], last_line['rhs'], nonterminals) end last_line['nt'] = $1 last_line['rhs'] = $2 elsif line =~ /@terminals/ nonterminals = false else last_line['rhs'] += " #{line}" end } } if last_line['nt'] print_rule(last_line['nt'], last_line['rhs'], nonterminals) end