简体   繁体   中英

How to define multi-character exclusion in ANTLR3 lexer rule?

I'm trying to create a lexer rule for Antlr3, which would match a triple-quoted strings. For example:

"""this is some text"""

This is how I'm doing it:

TEXT:
  '"""' ('\\"' | ~'"')+ '"""'
  { 
    this.setText(
      this.getText()
        .substring(3, this.getText().length() - 3)
        .replace("\\\"", "\"")
    ); 
  }
  ;

Works good, but every single quote mark has to be escaped in the input text, like this:

"""this is the same text, but with \"escaped quotes\" inside"""

I'm trying to get rid of this mandatory escaping of quotes, and parse anything (!) between triple-quote marks, like this:

"""sample text again, with "quotes" inside"""

I'm trying to change the rule to:

TEXT:
  '"""' (~'"""')+ '"""'

And Antlr3 3.5 complains:

error(100): Spec.g:153:13: syntax error: buildnfa: NoViableAltException(58@[])
error(100): Spec.g:0:1: syntax error: buildnfa: MismatchedTreeNodeException(3!=29)
error(100): Spec.g:0:: syntax error: buildnfa: NoViableAltException(3@[])
error(100): Spec.g:0:1: syntax error: buildnfa: MismatchedTreeNodeException(29!=28)
error(10):  internal error: Spec.g : java.lang.NullPointerException
org.antlr.tool.NFAFactory.build_Aplus(NFAFactory.java:516)
...

What is wrong? What is a possible workaround?

The best way is probably with a predicate.

TEXT
  : '"""'
    ( ~'"'
    | {input.LA(2) != '"' || input.LA(3) != '"'}? '"'
    )*
    '"""'
  ;

This works in ANTLR 4 as well as long as you change input to _input in the predicate.

Since .* and .+ are ungreedy by default, have tried simply doing:

TEXT
 : '"""' .* '"""'
   { 
     ... 
   }
 ;

?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM