2016-04-05 6 views
0

私は次の言語L0またはL1のいずれかに属するすべての入力文字列を認識することを意図されたJavaCCパーサ/レクサを書いています:「拡張内」(...。)*の処理方法は「空の文字列で一致させることはできますか?

L0
L0から文字列が空白文字で区切られた複数のブロックで構成されてい。 少なくとも1つのブロックが存在していなければなりません(つまり、いくつかの空白で構成される入力は許可されません)。

  • ブロックは、小文字(a-z)の奇数長のシーケンスです。
  • 最初のブロックの前または最後のブロックの後にスペースを入れることはできません。
  • ブロック間のスペースの数は奇数でなければなりません。

L1
L1から文字列が空白文字で区切られた複数のブロックから構成されています。 少なくとも1つのブロックが存在する必要があります。

  • ブロックには2種類あります。第1種のブロックは、 の大文字の偶数長のシーケンス(A-Z)でなければなりません。 第2種のブロックは、形状<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> 
} 

問題: 私が午前問題は、私はAssignment.jjjavaccを実行すると、次のように端末にプリントアウトされることです。

  • Link 1

    は(私はdidnの」:Expansion within "(. . .)*" can be matched by empty string.は、私はより良い、このエラーを理解しようとするためには、以下のリンクを見てきましたこれは非常に便利です)。
  • Link 2(これはかなり役に立ちました)

第2のリンクは、それがゼロにマッチすることができないように、膨張内. . .を変更する推奨しました。しかし、私はL1で文字列を受け取るプロダクションを持っている間にこれを行うのに苦労しています。

ヒントまたは訂正Input2()ためのルールで

答えて

2

(...)*内部に含まれるパターン:

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

は、空の文字列にマッチすることができます。

あなたはA<WHITESPACE> Input()B<WHITESPACE> (<IDUPPER><IDUPPER>)+あり、そしてA* B*に関係なく何であるかABの、空の文字列を一致させることができているフォーム(A* B*)*に拡大を減らすことができます。

JavaCCでは、囲まれた式が空の文字列と一致する可能性があります。これは、エラーメッセージがあなたに伝えようとしているものです。

合理的な選択肢はかもしれない:

(A | B)* 

ので、この場合に<WHITESPACE>の両方AB開始、それを考慮することが必要であろう。

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

'B'は( 'ですA * B *)* 'ではなく、'(A + B *)* 'に含まれています。同様に 'BB'など私は' B *(A B *)* 'を提案します。 –

+0

@theodore:かなり正しい。私はそれを厳密に同等に変更しました。 '| '演算子が不可能な場合、別の非終端記号を導入することができます。 – rici

+0

はい '(A | B)*'が最適です。 –

関連する問題