2016-04-05 2 views
0

Я пишу JavaCC синтаксический анализатор/лексера который предназначен распознавать все входные строки, принадлежащие к одному из следующих языков L0 или L1:Как справиться с «Расширением внутри» (...) * «может быть сопоставлено пустая строка»?

L0
Строка из L0 состоит из нескольких блоков, разделенных пробелами , Должен присутствовать хотя бы один блок (т. Е. Не допускается вход, состоящий только из некоторого количества пробелов).

  • Блок представляет собой последовательность строчных букв без буквы (a-z).
  • Перед первым блоком или после последнего пробела не допускается пробел.
  • Число пробелов между блоками должно быть нечетным.

L1
Строка из L1 состоит из нескольких блоков, разделенных пробелами. Должен присутствовать хотя бы один блок.

  • Существует два вида блоков. Блок первого типа должен быть четной последовательностью заглавных букв (A-Z). Блок второго типа должен иметь форму <2U>. . .</2U>, где . . . стоит для любой строки из L0.
  • Перед первым блоком или после последнего пробела не допускается пробел.
  • Число пробелов между блоками должно быть нечетным.

Это мой код до сих пор:

PARSER_BEGIN(Assignment) 

    /** A parser which determines if user's input belongs to L0 or L1. */ 
    public class Assignment { 
    public static void main(String[] args) { 
     String returnString = null; 
     boolean toPrintEmptyInput = false; 
     try { 
     Assignment parser = new Assignment(System.in); 
     if(parser.Input()) { 
      System.out.println("YES"); // If the user's input belongs to L0, print YES. 
     } else { 
      System.out.println("NO"); 
     } 
     } catch (ParseException e) { 
     System.out.println("NO"); // If the user's input does not belong to L0, print NO.  
     } 
    } 
    } 

PARSER_END(Assignment) 

//** A token which matches any lowercase letter from the English alphabet. */ 
TOKEN : 
{ 
    < IDLOWER: (["a"-"z"]) > 
} 

//* A token which matches any uppercase letter from the English alphabet. */ 
TOKEN: 
{ 
    < IDUPPER: (["A"-"Z"]) > 
} 

//* A token which matches a single white space. */ 
TOKEN : 
{ 
    <WHITESPACE: " "> 
} 

/** This production is the basis for the construction of strings which belong to language L0. */ 
boolean Input() : 
{} 
{ 
    <IDLOWER>(<IDLOWER><IDLOWER>)* ((<WHITESPACE>(<WHITESPACE><WHITESPACE>)*)<IDLOWER>(<IDLOWER><IDLOWER>)*)* ("\n"|"\r") <EOF> 
    {  
    return true;  
    } 

    | 

    {   
    return false; 
    } 
} 

/** This production is the basis for the construction of strings which belong to language L1. */ 
void Input2() : 
{} 
{ 
    Input() ((<WHITESPACE> Input())* (<WHITESPACE> (<IDUPPER><IDUPPER>)+)*)* ("\n"|"\r") <EOF> 

    | 

    (<IDUPPER><IDUPPER>)+ ((<WHITESPACE> (<IDUPPER><IDUPPER>)+)* (<WHITESPACE> Input())*)* ("\n"|"\r") <EOF> 
} 

Выпуск: Вопрос, который я имею, что, когда я бегу javacc на Assignment.jj следующее печатается на терминале: Expansion within "(. . .)*" can be matched by empty string. Я посмотрел на следующие ссылки для того, чтобы попытаться лучше понять эту ошибку:

  • Link 1 (я Ждут» t найти это очень полезно).
  • Link 2 (Я нашел это довольно полезным).

Вторая ссылка рекомендовала модифицировать . . . в пределах расширения, чтобы его нельзя было сопоставить с нулем. Тем не менее, я изо всех сил стараюсь сделать это, все еще имея производство, которое принимает строки в L1.

Я бы оценил советы или исправления!

ответ

2

В правиле для Input2(), шаблон содержится внутри (...)* в:

((<WHITESPACE> Input())* (<WHITESPACE> (<IDUPPER><IDUPPER>)+)*)* 

может быть согласован с пустой строкой.

Вы можете уменьшить расширение в форме (A* B*)*, где A является <WHITESPACE> Input() и B является <WHITESPACE> (<IDUPPER><IDUPPER>)+ и A* B* может соответствовать пустой строке, независимо от того, что A и B являются.

JavaCC не разрешает расширения (...)*, если вложенное выражение может соответствовать пустой строке, что и пытается сообщить вам сообщение об ошибке.

Разумной альтернативой может быть:

(A | B)* 

Так как в этом случае как A и B начать с <WHITESPACE>, будет необходимо учитывать его:

(<WHITESPACE> (Input() | (<IDUPPER><IDUPPER>)+))* 
+0

'B' в' (A * B *) * ', но не в' (A + B *) * '. Аналогично «BB» и т. Д. Я бы предложил «B * (A B *) *». –

+0

@theodore: совершенно верно. Я изменил его на строгий эквивалент. Если оператор '|' не был возможен, можно было бы ввести другой нетерминал. – rici

+0

Да '(A | B) *' лучше. –

Смежные вопросы