[antlr-interest] Island grammar for reading shell commands

Bill Lear rael at zopyra.com
Tue Nov 30 14:52:11 PST 2010


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(BaseRecognizer.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:95)
        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 : '\\' ('\"'|'\''|'\\') ;


More information about the antlr-interest mailing list