[antlr-interest] Island grammar for reading shell commands

Jim Idle jimi at temporal-wave.com
Tue Nov 30 15:49:39 PST 2010


REST_OF_LINE allows an empty token which will immediately match nothing and
continue to do so forever. You want +  not *. I think you might be doing
this wrong to be honest. I would probably not use ANTLR for this.

Jim

> -----Original Message-----
> From: antlr-interest-bounces at antlr.org [mailto:antlr-interest-
> bounces at antlr.org] On Behalf Of Bill Lear
> Sent: Tuesday, November 30, 2010 2:52 PM
> To: Terence Parr
> Cc: antlr-interest at antlr.org
> Subject: Re: [antlr-interest] Island grammar for reading shell commands
> 
> On Tuesday, November 30, 2010 at 13:07:57 (-0800) Terence Parr writes:
> >Wow. input.LT(1) or LT(-1) is returning null.
> >
> >I'd turn on -trace option of antlr then recompile and retry. that may
> >say more
> 
> Here's the output with -trace turned on:
> 
> enter SHELL s line=1:0
> Got shell.  Going native.
> enter REST_OF_LINE   line=1:5
> exit REST_OF_LINE c line=2:0
> enter shell [@-1,0:0='<no text>',<-1>,0:-1] exit shell [@-1,0:0='<no
> text>',<-1>,0:-1] exit SHELL c line=2:0 Exception in thread "main"
> java.lang.NullPointerException
>         at org.antlr.runtime.Parser.getMissingSymbol(Parser.java:70)
>         at
> org.antlr.runtime.BaseRecognizer.recoverFromMismatchedToken(BaseRecogni
> zer.java:604)
>         at
> org.antlr.runtime.BaseRecognizer.match(BaseRecognizer.java:115)
>         at ShellParser.shell(ShellParser.java:49)
>         at CommandLexer.mSHELL(CommandLexer.java:58)
>         at CommandLexer.mTokens(CommandLexer.java:712)
>         at org.antlr.runtime.Lexer.nextToken(Lexer.java:84)
>         at
> org.antlr.runtime.CommonTokenStream.fillBuffer(CommonTokenStream.java:9
> 5)
>         at
> org.antlr.runtime.CommonTokenStream.LT(CommonTokenStream.java:238)
>         at org.antlr.runtime.Parser.traceIn(Parser.java:92)
>         at CommandParser.commands(CommandParser.java:47)
>         at Command.main(Command.java:8)
> 
> I posted the grammars previously, but just case you missed them, I
> posted them (Shell.g, Command.g) below.
> 
> 
> Bill
> 
> // Grammar for 'shell ...' command
> grammar Shell;
> 
> @parser::members {
>     private String command;
>     public String getCommand() {
>         return command;
>     }
> }
> 
> shell: REST_OF_LINE {
>         command = $REST_OF_LINE.text.trim();
>     }
>     ;
> 
> REST_OF_LINE: (options {greedy=false;} : . )* '\r'? '\n' {
>         emit(Token.EOF_TOKEN);
>     }
>     ;
> 
> // Grammar for other, regular commands
> grammar Command;
> 
> @lexer::members {
>     public static final int SHELL_CHANNEL = 1; }
> 
> commands : command+ ;
> 
> command
> scope {
>     int timeout;
>     List<String> notifyList;
> }
> @init {
>     $command::timeout = -1;
>     $command::notifyList = new ArrayList<String>(); }
>     : cleanup | cleanlog {
>     }
>     | SHELL
>     | NEWLINE
>     ;
> 
> cleanup
>     : CLEANUP command_options? {
>         System.out.println("cleanup::timeout=" + $command::timeout
>                            + " email=" + $command::notifyList);
>     }
>     ;
> 
> cleanlog
>     : CLEANLOG command_options? {
>         System.out.println("cleanlog::timeout=" + $command::timeout
>                            + " email=" + $command::notifyList);
>     }
>     ;
> 
> SHELL
>     : 'shell' {
>         System.out.println("Got shell.  Going native.");
> 
>         ShellLexer l = new ShellLexer(input);
> 
>         CommonTokenStream tokens = new CommonTokenStream(l);
> 
>         ShellParser parser = new ShellParser(tokens);
>         parser.shell();
> 
>         String command = parser.getCommand();
> 
>         System.out.println("Got command from ShellParser:[" + command +
> "]");
>         $channel = SHELL_CHANNEL;
>     }
>     ;
> 
> command_options
>     : timeoutOption
>     | notifyOption
>     | timeoutOption notifyOption
>     | notifyOption timeoutOption
>     ;
> 
> timeoutOption
>     : TIMEOUT INT { $command::timeout = Integer.parseInt($INT.text); }
>     ;
> 
> notifyOption
>     : NOTIFY EMAIL {
>         $command::notifyList.add($EMAIL.text);
>     }
>     | NOTIFY QUOTED_STRING {
>         String[] l = $QUOTED_STRING.text.split("\\s+");
> 
>         for (int i = 0; i < l.length; i++) {
>             $command::notifyList.add(l[i]);
>         }
>     }
>     ;
> 
> CLEANUP: 'cleanup' ;
> CLEANLOG: 'cleanlog' ;
> TIMEOUT: '-timeout' ;
> NOTIFY: '-notify' ;
> INT: '0'..'9'+ ;
> 
> QUOTED_STRING:
>     '"' ( ESCAPE_SEQUENCE | ~('\\'|'"') )* '"' {
>         setText(getText().substring(1, getText().length() - 1));
>     }
>     | '\'' ( ESCAPE_SEQUENCE | ~('\\'|'\'') )* '\'' {
>         setText(getText().substring(1, getText().length() - 1));
>     }
>     ;
> 
> WS: (' ' | '\t')+ { skip(); } ;
> 
> NEWLINE: '\r'? '\n' { } ;
> 
> EMAIL: ~('\n' | '\r' | ' ' | '"')+ {
>     }
>     ;
> 
> COMMENT
>     : '//' ~('\n'|'\r')* '\r'? '\n' { skip(); }
>     | '/*' ( options {greedy=false;} : . )* '*/' { skip(); }
>     ;
> 
> fragment
> ESCAPE_SEQUENCE : '\\' ('\"'|'\''|'\\') ;
> 
> List: http://www.antlr.org/mailman/listinfo/antlr-interest
> Unsubscribe: http://www.antlr.org/mailman/options/antlr-interest/your-
> email-address



More information about the antlr-interest mailing list