JavaCC สร้างรหัสที่ไม่ทำงาน

ฉันใช้ JavaCC เป็นครั้งแรก และฉันสังเกตเห็นว่ามันสร้างโค้ดที่ไม่ทำงานจำนวนมาก มีหลายบรรทัดที่ดูเหมือน (ขออภัยการเว้นวรรค มันเป็นอัตโนมัติ):

{if ("" != null) return result;}
    throw new Error("Missing return statement in function");
  }

เป็นไปได้ไหมที่จะหลีกเลี่ยงการสร้างโค้ดที่ไม่ทำงานนี้ มันทำให้เกิดคำเตือนของคอมไพเลอร์นับสิบรายการที่หวังว่าจะสามารถหลีกเลี่ยงได้

ขอบคุณ!

นี่เป็นตัวอย่างขั้นต่ำแบบเต็มจากไฟล์ .jj:

Statement UseStatement():
{
    String dbName;
}
{
    <USE> dbName=DbObjectName()
    {
        return new UseStatement(dbName);
    }
}

ซึ่งก่อให้เกิด:

final public Statement UseStatement() throws ParseException {String dbName;
    jj_consume_token(USE);
    dbName = DbObjectName();
{if ("" != null) return new UseStatement(dbName);}
    throw new Error("Missing return statement in function");
  }

นอกจากนี้ JavaCC กำลังสร้างไฟล์ ParserTokenManager ซึ่งส่ง TokenMgrError - แต่โค้ดไม่ได้คอมไพล์ มันประกาศ protected int curChar โดยที่ควรประกาศเป็น char การใช้ Google วลีนี้แสดงตัวอย่างมากมายที่มีการแจ้งอย่างถูกต้องว่า char - นี่เป็นเพียงผู้คนจำนวนมากที่แก้ไขผลลัพธ์ด้วยตนเองหรือไม่


person a_physicist    schedule 25.05.2017    source แหล่งที่มา
comment
คุณใช้ JavaCC เวอร์ชันใดอยู่ คุณได้ลองใช้ตัวเลือก LEGACY_EXCEPTION_HANDLING = false หรือไม่   -  person Theodore Norvell    schedule 27.05.2017
comment
เพื่อตอบคำถามของคุณเกี่ยวกับประเภทของ curChar ไม่ใช่ คุณไม่จำเป็นต้องแก้ไขด้วยมือมากนัก เวอร์ชัน 5 สร้างประเภทเป็น char   -  person Theodore Norvell    schedule 27.05.2017
comment
LEGACY_EXCEPTION_HANDLING จริงๆ แล้วผู้ใช้ไม่สามารถตั้งค่าได้ แต่สามารถเปลี่ยนแปลงได้ - ดูการแก้ไขของฉันด้านล่าง เวอร์ชันที่ใช้โดยปลั๊กอิน Maven ที่ฉันใช้คือ 6.1.3 แต่ฉันพบวิธีย้ายกลับไปใช้ปลั๊กอิน codehaus ดั้งเดิมและบังคับให้เวอร์ชัน JavaCC เป็น 7.x ขอบคุณ!   -  person a_physicist    schedule 29.05.2017


คำตอบ (1)


ฉันไปที่แหล่งที่มาและเพื่อป้องกันโค้ดที่ไม่ทำงาน คุณต้องทริกเกอร์ Options.isLegacyExceptionHandling

  // Add if statement to prevent subsequent code generated
  // from being dead code.
  // NB: eclipse now detects 'if (true)' as dead code, so use the more complicated
  // 'if ("" != null)'
  if (inAction  && (Options.isLegacyExceptionHandling()) ) {
    t.image = "{if (\"\" != null) return";
    jumpPatched = true;
  }

ซึ่งจะกระตุ้นให้เกิด:

if (p.isJumpPatched() && !voidReturn) {
  if (isJavaDialect) {
    // TODO :: I don't think we need to throw an Error/Exception to mark that a return statement is missing as the compiler will flag this error automatically
    if (Options.isLegacyExceptionHandling()) {
        codeGenerator.genCodeLine("    throw new "+(Options.isLegacyExceptionHandling() ? "Error" : "RuntimeException")+"(\"Missing return statement in function\");");
    }
  } else {
    codeGenerator.genCodeLine("    throw \"Missing return statement in function\";");
  }
}

https://github.com/javacc/javacc/blob/e38cbdb1db7ca8bd66f892859fef88b4876e69ba/src/main/javacc/JavaCC.jj#L2771-L2779

https://github.com/javacc/javacc/blob/2ac628df1f899fdf6acf1f87fad313b6797085f7/src/main/java/org/javacc/parser/ParseEngine.java#L707-L712

การจัดการข้อยกเว้นแบบเดิมเป็นตัวเลือกที่ได้รับซึ่งเป็นเท็จเฉพาะเมื่อ JAVA_TEMPLATE_TYPE=modern วิธีเดียวที่จะตั้งค่าได้อย่างถูกต้องคือรวมไว้ในบล็อก options ในไฟล์ .jj ดังนี้:

options {
    JAVA_TEMPLATE_TYPE="modern";
}

ตามทฤษฎีแล้ว ยังสามารถตั้งค่าได้ผ่านตัวเลือกบรรทัดคำสั่ง แต่ในขณะที่เขียนนี้ จริงๆ แล้วเป็นไปไม่ได้เลยที่จะตั้งค่าตัวเลือกที่ได้รับก่อนที่อาร์กิวเมนต์บรรทัดคำสั่งจะถูกแยกวิเคราะห์ (#25)

person a_physicist    schedule 26.05.2017
comment
มีวิธีปิด 'การจัดการข้อยกเว้นแบบเดิม' หรือไม่ - person user207421; 27.05.2017
comment
ใช่ - ดูการแก้ไขของฉัน มันบ้านิดหน่อย แต่ฉันก็เข้าใจในที่สุด - person a_physicist; 29.05.2017