@license{
  Copyright (c) 2009-2015 CWI
  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
}
module lang::rascal::grammar::definition::Keywords

import Grammar;
import ParseTree;
import Node;
import lang::rascal::grammar::definition::Symbols;

public Grammar expandKeywords(Grammar g) {
  return visit(g) {
    case conditional(sym, conds) => conditional(sym, expandKeywords(g, conds)) 
  };
}

public set[Condition] expandKeywords(Grammar g, set[Condition] conds) {
  names = {};
  done = {};
  todo = conds;

  solve(todo) {  
    for (cond <- todo, !(cond in done)) {
      todo -= {cond};
      
      if (cond has symbol, keywords(str name) := cond.symbol) {
        if (name notin names) {
        	names += {name};
        	todo += {cond[symbol=s] | choice(_, set[Production] alts) := g.rules[unsetRec(cond.symbol)], prod(_,[s],_) <- alts};
      	}  
      } else {
        done += cond;
      }
    }
  }
  
  return done;  
}

public set[Production] getKeywords(Grammar g) {
  return {g.rules[unsetRec(s)] | s:keywords(_) <- g.rules}; 
}
