options { LOOKAHEAD=1; } PARSER_BEGIN(Q3) public class Q3 { /*** Main routine - just call parser ***/ public static void main(String args[]) throws ParseException { Q3 parser = new Q3(System.in); try { String out_string = parser.inp_line(); if (out_string != null) System.out.println("Answer is: " + out_string); } catch (ParseException x) { System.out.println("Exiting due to parse error."); throw x; } } } PARSER_END(Q3) SKIP : /*** Ignoring spaces/tabs ***/ { " " | "\t" } TOKEN : /* Some extra ones, just for fun */ { < STRING : ( ["a"-"z"] )+ > | < NUMBER : ( ["0"-"9"] )+ > | < CONCAT : "+" > | < KPRE : ">" > | < KSUFF : "<" > | < LBR : "(" > | < RBR : ")" > } /*************************/ /***** GRAMMAR RULES *****/ /*************************/ String inp_line() : { String ans; } { ans=expr() ( | "\n" | "\r") { return ans; } } String expr() : { String st1, st2; } { st1=suf_term() ( st2=suf_term() { st1 = st1+st2;} )* { return st1; } } String suf_term() : { String pt; int to_keep=Integer.MAX_VALUE; Token n; } { pt=pre_term() ( n= { to_keep = Math.min(to_keep,Integer.parseInt(n.image)); } )* { if (to_keep >= pt.length()) return pt; else return pt.substring(pt.length()-to_keep); } } String pre_term() : { String bt; int to_keep=Integer.MAX_VALUE; Token n; } { ( n= { to_keep = Math.min(to_keep,Integer.parseInt(n.image)); } )* bt=basic_term() { if (to_keep >= bt.length()) return bt; else return bt.substring(0,to_keep); } } String basic_term() : { String s; } { s=expr() { return s; } | { return token.image; } }