1 /*********************************************************************
2 Copyright 2012, Ralph Ronnquist.
4 This file is part of GORITE.
6 GORITE is free software: you can redistribute it and/or modify it
7 under the terms of the Lesser GNU General Public License as published
8 by the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GORITE is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the Lesser GNU General Public
17 License along with GORITE. If not, see <http://www.gnu.org/licenses/>.
18 **********************************************************************/
20 package com.intendico.sdp;
22 import java.lang.reflect.Constructor;
23 import java.util.Vector;
24 import java.util.Enumeration;
25 import java.util.Hashtable;
28 * Class LLBNF defines a standard recursive descent BNF, using "<" and
29 * ">" to indicate non-terminals, and "'" to indicate terminals.
31 public class LLBNF extends BNFGrammar {
34 * Utility method to instantiate a Production object. The method
35 * first tries to instantiate with the name given, thereafter by
36 * assuming its an inner class of the target grammar
38 Class findClass(String clsname)
39 throws ClassNotFoundException
41 ClassNotFoundException ex = null;
42 // Try the name as given
44 return Class.forName( clsname );
45 } catch (ClassNotFoundException e) {
48 // Trying the name as inner class of the target class, or
49 // any of the target class base classes.
50 for (Class tc = target.getClass(); tc != null;
51 tc = tc.getSuperclass() ) {
53 return Class.forName( tc.getName() + "$" + clsname );
54 } catch (ClassNotFoundException e) {
58 // Trying the name as a class of the same package as the
59 // target class or any of its base classes
60 for (Class tc = target.getClass(); tc != null;
61 tc = tc.getSuperclass() ) {
62 String pkg = tc.getName();
63 int x = pkg.lastIndexOf( '.' );
67 pkg.substring( 0, x ) + "." + clsname );
68 } catch (ClassNotFoundException e) {
75 Object create(String clsname)
78 Class cls = findClass( clsname );
79 Class ctx = cls.getDeclaringClass();
81 return cls.newInstance();
82 return cls.getConstructor(
83 new Class [] { ctx } ).newInstance( new Object [] { target } );
86 Object createNamed(String clsname,String name)
89 Class cls = findClass( clsname );
90 Class ctx = cls.getDeclaringClass();
92 return cls.getConstructor(
93 new Class [] { String.class } ).
94 newInstance( new Object [] { name } );
95 return cls.getConstructor(
96 new Class [] { ctx, String.class } ).
97 newInstance( new Object [] { target, name } );
100 Hashtable grammars = new Hashtable();
102 Grammar getGrammar(String grammar)
105 Class c = findClass( grammar );
106 grammar = c.getName();
107 Grammar g = (Grammar) grammars.get( grammar );
109 g = (Grammar) create( grammar );
110 grammars.put( grammar, g );
115 Link linkGrammar(String rule,String goal,String grammar)
118 return target.new Link( rule, goal, getGrammar( grammar ) );
123 final Grammar grammar;
126 BackLink(String rule,String goal,String g,Grammar target)
129 grammar = getGrammar( g );
130 link = grammar.new Link( rule, goal, target );
135 grammar.addRule( link );
139 BackLink backlinkGrammar(String rule,String goal,String grammar)
142 return new BackLink( rule, goal, grammar, target );
146 * Generic Helper class that tags with a string.
148 public static class Tag extends Production {
150 public final String tag;
151 public final Grammar grammar;
153 public Tag(Grammar g,String t)
160 public Object action(Vector v)
163 RuleAction action = (RuleAction) grammar.rule_actions.get( tag );
164 if ( action != null )
165 return action.action( v );
172 public String toString() {
173 StringBuffer s = new StringBuffer();
175 for ( int i=0; i<tokens.length; i++ ) {
176 s.append( tokens[i].toString() );
192 public void initialisation()
198 new Production( new Token [] {
199 new NonTerminal( "identifier" ),
200 new Terminal( "::=" ),
201 new NonTerminal( "productions" )
203 public Object action(Vector v) {
204 Vector p = (Vector) v.get( 1 );
205 Production [] px = new Production[ p.size() ];
206 return target.new ProductionList(
208 (Production[]) p.toArray( px ) );
210 new Production( new Token [] {
211 new NonTerminal( "identifier" ),
212 new Terminal( "is" ),
213 new Terminal( "lexical" ),
214 new NonTerminal( "any" )
216 public Object action(Vector v)
219 String name = (String) v.get( 0 );
220 String clsname = (String) v.get( 1 );
221 return (Lexical) createNamed( clsname, name );
225 new Production( new Token [] {
226 new NonTerminal( "identifier" ),
227 new Terminal( "is" ),
228 new Terminal( "linked" ),
229 new Terminal( "to" ),
230 new NonTerminal( "nonterminal" ),
231 new Terminal( "in" ),
232 new NonTerminal( "any" )
234 public Object action(Vector v)
237 String rule = (String) v.get( 0 );
238 String goal = (String) v.get( 1 );
239 String grammar = (String) v.get( 2 );
240 return linkGrammar( rule, goal, grammar );
244 new Production( new Token [] {
245 new NonTerminal( "identifier" ),
246 new Terminal( "of" ),
247 new NonTerminal( "any" ),
248 new Terminal( "is" ),
249 new Terminal( "linked" ),
250 new Terminal( "to" ),
251 new NonTerminal( "nonterminal" ),
254 public Object action(Vector v)
257 String rule = (String) v.get( 0 );
258 String goal = (String) v.get( 2 );
259 String grammar = (String) v.get( 1 );
260 return backlinkGrammar( rule, goal, grammar );
269 new Production( new Token [] {
270 new NonTerminal( "end" ),
272 public Object action(Vector v) {
276 new Production( new Token [] {
277 new NonTerminal( "rule" ),
278 new NonTerminal( "rules" )
280 public Object action(Vector v) {
281 Vector all = (Vector) v.get( 1 );
282 all.add( 0, v.get( 0 ) );
291 new Production( new Token [] {
292 new NonTerminal( "production" ),
294 new NonTerminal( "productions" )
296 public Object action(Vector v) {
297 Vector all = (Vector) v.get( 1 );
298 all.add( 0, v.get( 0 ) );
302 new Production( new Token [] {
303 new NonTerminal( "production" )
305 public Object action(Vector v) {
314 new Production( new Token [] {
315 new NonTerminal( "tokenlist" ),
318 new NonTerminal( "any" ),
320 public Object action(Vector v)
323 Vector x = (Vector) v.get( 0 );
324 Production p = new Tag(
325 target, (String) v.get( 1 ) );
327 (Token[]) x.toArray( new Token[x.size()] ) );
331 new Production( new Token [] {
332 new NonTerminal( "tokenlist" ),
334 new NonTerminal( "any" ),
336 public Object action(Vector v)
339 Vector x = (Vector) v.get( 0 );
340 Production p = (Production)
341 create( (String) v.get( 1 ) );
343 (Token[]) x.toArray( new Token[x.size()] ) );
347 new Production( new Token [] {
348 new NonTerminal( "tokenlist" )
350 public Object action(Vector v) {
351 Vector x = (Vector) v.get( 0 );
352 return target.new Production(
353 (Token[]) x.toArray( new Token [ x.size() ] )
362 new Production( new Token [] {
363 new NonTerminal( "token" ),
364 new NonTerminal( "tokenlist" )
366 public Object action(Vector v) {
367 Vector all = (Vector) v.get( 1 );
368 all.add( 0, v.get( 0 ) );
372 new Production( new Token [] {
373 new NonTerminal( "token" )
375 public Object action(Vector v) {
384 new Production( new Token [] {
385 new NonTerminal( "nonterminal" ),
387 public Object action(Vector v) {
388 return target.new NonTerminal(
389 (String) v.get( 0 ) );
392 new Production( new Token [] {
393 new NonTerminal( "terminal" ),
395 public Object action(Vector v) {
396 v = (Vector) v.get( 0 );
397 boolean option = "?".equals( v.get( 0 ) );
399 option || "!".equals( v.get( 0 ) );
400 return target.new Terminal(
410 new Production( new Token [] {
412 new NonTerminal( "identifier" ),
420 new Production( new Token [] {
421 new Terminal( "!", true ),
422 new NonTerminal( "any" )
424 new Production( new Token [] {
425 new Terminal( "'", true ),
426 new NonTerminal( "any" )
428 new Production( new Token [] {
429 new Terminal( "?", true ),
430 new NonTerminal( "any" )
433 addRule( new AnySymbol( "any" ) );
434 addRule( new Identifier( "identifier" ) );
435 addRule( new End( "end" ) );
439 * Utility method to define rules using LLBNF syntax.
441 public Grammar addRules(Grammar g,String rules)
445 //trace = TRACE_STACK;
447 grammars.put( g.getClass().getName(), target );
449 Vector v = (Vector) parseAndProcess( "rules", rules );
450 for ( Enumeration e = v.elements(); e.hasMoreElements(); ) {
451 Object r = e.nextElement();
452 if ( r instanceof BackLink )
453 ((BackLink) r).addRule();
455 target.addRule( (Rule) r );
458 } catch (Throwable t) {
459 throw hideParse( t, LLBNF.class.getName() );
464 * A Test main method.
466 public static void main(String [] args)
469 LLBNF g = new LLBNF();
470 String rules = g.toString() ;
471 Grammar x = g.addRules( new Grammar(), rules );
472 System.out.println( x );