Грамматика JavaCC - правильный лексинг

У меня есть грамматика JavaCC со следующими определениями:

<REGULAR_IDENTIFIER : (["A"-"Z"])+ > // simple identifier like say "DODGE"
<_LABEL : (["A"-"Z"])+ (":") > // label, eg "DODGE:"
<DOUBLECOLON : "::">
<COLON : ":">

Прямо сейчас "DODGE::" лексируется как <_LABEL> <COLON> ("DODGE:" ":"), но мне нужно, чтобы <REGULAR_IDENTIFIER> <DOUBLECOLON> ("DODGE" "::")

2 ответа

Я думаю, что следующее будет работать

MORE: { < (["A"-"Z"])+ :S0 > } // Could be identifier or label.
<S0> TOKEN: { <LABEL : ":" : DEFAULT> } // label, eg "DODGE:"
<S0> TOKEN: { <IDENTIFIER : "" : DEFAULT > } // simple identifier like say "DODGE"
<S0> TOKEN: { <IDENTIFIER : "::" { matchedToken.image = image.substring(0,image.size()-2) ; } : S1 > }
<S1> TOKEN: { <DOUBLECOLON : "" { matchedToken.image =  "::" ; } : DEFAULT> }
<DOUBLECOLON : "::">
<COLON : ":">

Обратите внимание, что "DODGE:::" - это три токена, а не два.

В javacc используется правило максимального соответствия (правило соответствия самого длинного префикса), см.: http://www.engr.mun.ca/~theo/JavaCC-FAQ/javacc-faq-moz.htm.

Это означает, что токен _LABEL будет сопоставляться перед токеном REGULAR_IDENTIFIER, поскольку токен _LABEL будет содержать больше символов. Это означает, что то, что вы пытаетесь сделать, не должно выполняться в токенизаторе.

Я написал парсер, который распознает грамматику правильно, я использую парсер для распознавания _LABEL вместо токенизатора:

options {
    STATIC = false;
}

PARSER_BEGIN(Parser)

import java.io.StringReader;

public class Parser {

    //Main method, parses the first argument to the program
    public static void main(String[] args) throws ParseException {
        System.out.println("Parseing: " + args[0]);
        Parser parser = new Parser(new StringReader(args[0]));
        parser.Start();
    }
}

PARSER_END(Parser)

//The _LABEL will be recognized by the parser, not the tokenizer
TOKEN :
{
    <DOUBLECOLON : "::"> //The double token will be preferred to the single colon due to the maximal munch rule
    |
    <COLON : ":">
    |
    <REGULAR_IDENTIFIER : (["A"-"Z"])+ > // simple identifier like say "DODGE"
}

/** Root production. */
void Start() :
{}
{
    ( 
        LOOKAHEAD(2) //We need a lookahead of two, to see if this is a label or not
        <REGULAR_IDENTIFIER> <COLON> { System.err.println("label"); } //Labels, should probably be put in it's own production
        | <REGULAR_IDENTIFIER> { System.err.println("reg_id"); }  //Regulair identifiers
        | <DOUBLECOLON> { System.err.println("DC"); } 
        | <COLON> { System.err.println("C"); } 
    )+
}

В реале ты должен, конечно, сдвинуть <REGULAR_IDENTIFIER> <COLON> к _label производство.

Надеюсь, поможет.

Другие вопросы по тегам