บทความนี้อธิบายการใช้งานของ Java เพื่อกำหนดฟังก์ชั่นภาษาอย่างง่ายตามรูปแบบล่าม แบ่งปันสำหรับการอ้างอิงของคุณดังนี้:
คำจำกัดความรูปแบบ
รูปแบบล่าม: มันคือการแสดงไวยากรณ์ของภาษาและกำหนดล่ามเพื่อตีความประโยคในภาษา รูปแบบล่ามอธิบายวิธีการตีความข้อความเหล่านี้โดยใช้การออกแบบรูปแบบหลังจากไวยากรณ์อย่างง่าย
ตัวอย่างของโหมดที่สอง
1 การวิเคราะห์รูปแบบ
เราออกแบบภาษาเพื่อแสดงรูปแบบนี้ด้วยตนเอง
(1) ภาษาเป็นตัวพิมพ์เล็ก (2) ภาษาเริ่มต้นด้วยโปรแกรมและจบลงด้วยการสิ้นสุด (3) println หมายถึงการพิมพ์บรรทัดและทำลายมัน (4) ใช้สำหรับ ... จาก ... ถึง ... สิ้นสุดหมายถึงลูป
เนื้อหาภาษาตัวอย่างมีดังนี้:
โปรแกรม println start ... สำหรับ i จาก 90 ถึง 100 println ฉันสิ้นสุด println end ... สิ้นสุด
ความหมายของประโยคนี้คือ: พิมพ์ครั้งแรกการแบ่งบรรทัดด้วย "Start ... " จากนั้นวนรอบเส้นแบ่งด้วย "90", "91", ... "100" และในที่สุดก็พิมพ์เส้นแบ่งด้วย "End ... "
2 ภาษานี้อธิบายโครงสร้างต้นไม้
3 กิจกรรมไดอะแกรมของล่ามภาษา
4 ตัวอย่างรหัส
4.1 สร้างสภาพแวดล้อมบริบท - บริบท
แพ็คเกจ com.demo.interpreter.context; นำเข้า java.util.hashmap; นำเข้า java.util.iterator; นำเข้า java.util.map นำเข้า java.util.stringTokenizer;/** ** ** สภาพแวดล้อมบริบท * * @author */บริบทคลาสสาธารณะ // คำสั่งปัจจุบันสตริงส่วนตัว currentToken; // ใช้เพื่อจัดเก็บการเปลี่ยนแปลงเนื้อหาข้อมูลแบบไดนามิกแผนที่สุดท้าย <String, Object> MAP = ใหม่ HashMap <String, Object> (); / ** * constructor ตั้งค่าการแยกวิเคราะห์เนื้อหา * * @param text */ บริบทสาธารณะ (ข้อความสตริง) {// ใช้ช่องว่างเพื่อแยกข้อความที่จะแยกวิเคราะห์ this.stringTokenizer = new StringTokenizer (ข้อความ); } / *** การแยกวิเคราะห์ข้อความ* / สตริงสาธารณะถัดไป () {ถ้า (this.stringTokenizer.hasmoretokens ()) {currentToken = this.stringTokenizer.nexttoken (); } else {currentToken = null; } return currentToken; } / ** * พิจารณาว่าคำสั่งถูกต้อง * * @param คำสั่ง * @return * / บูลีนสาธารณะ EqualswithCommand (คำสั่งสตริง) {ถ้า (command == null ||! command.equals (this.currentToken)) {return false; } return true; } / ** * รับเนื้อหาคำสั่งปัจจุบัน * * @return * / สตริงสาธารณะ getCurrentToken () {return this.currentToken; } / ** * รับเนื้อหาของโหนด * * @return * / สตริงสาธารณะ getTokenContent (ข้อความสตริง) {string str = text; if (str! = null) {// แทนที่เนื้อหาที่เปลี่ยนแปลงแบบไดนามิกในแผนที่และส่งคืนตัววนซ้ำ <string> // แทนที่เนื้อหาที่เปลี่ยนแปลงแบบไดนามิกในแผนที่และส่งคืน iterator <string> iterator = this.map.keyset () iterator (); ในขณะที่ (iterator.hasnext ()) {string key = iterator.next (); Object obj = map.get (key); str = str.replaceall (คีย์, obj.toString ()); }} return str; } โมฆะสาธารณะใส่ (คีย์สตริง, ค่าวัตถุ) {this.map.put (คีย์, ค่า); } โมฆะสาธารณะล้าง (คีย์สตริง) {this.map.remove (คีย์); -4.2 อินเตอร์เฟสนิพจน์ - IExpressions
แพ็คเกจ com.demo.interpreter.express; นำเข้า com.demo.interpreter.context.context;/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * นั้น * * * * * * * * * * * * * * * * * * * * * * * * * * * * * นั้น / ** * วิธีการดำเนินการ * * @param บริบท */ โมฆะสาธารณะตีความ ();}
4.3 นิพจน์หลัก - programexpression
แพ็คเกจ com.demo.interpreter.express; นำเข้า com.demo.interpreter.context.context;/** * การแสดงออกของโปรแกรม * * @author * */programexpression คลาสสาธารณะใช้ IExpressions {// บริบทบริบทบริบท // คำสั่งปัจจุบันคำสั่งสตริงคงสุดท้ายสุดท้าย = "โปรแกรม"; // จัดเก็บนิพจน์การอ้างอิงส่วนตัวการแสดงออกของ IExpressions ส่วนตัว; / ** * ตัวสร้างส่งเนื้อหาที่จะแยกวิเคราะห์ลงใน * * @param text */ public programexpression (ข้อความสตริง) {this.context = บริบทใหม่ (ข้อความ); this.parse (this.context); } @Override โมฆะสาธารณะแยกวิเคราะห์ (บริบทบริบท) {// รับคำสั่งแรกโหนด this.context.next (); } / *** วิธีการใช้งานการใช้งาน* / @Override โมฆะสาธารณะตีความ () {// พิจารณาว่ามันเริ่มต้นด้วยโปรแกรมถ้า (! this.context.equalswithCommand (คำสั่ง)) {system.out.println ("" " + คำสั่ง +" } else {// เริ่ม this.context.next () ด้วยโปรแกรม; this.expressions = new ListExpression (); this.expressions.parse (this.context); // expression listexpression เริ่มแยกวิเคราะห์สิ่งนี้ expressions.interpret (); -4.4 รายการนิพจน์ - ListExpression
แพ็คเกจ com.demo.interpreter.express; นำเข้า java.util.arraylist; นำเข้า java.util.iterator; นำเข้า com.demo.interpreter.context.context;/** * รายการนิพจน์ * * @author * */คลาสสาธารณะ ArrayList สุดท้าย <Iexpressions> list = new ArrayList <Iexpressions> (); / ** * Constructor ผ่านบริบทที่จะแยกวิเคราะห์ลงในบริบท * * @param */ Public Void Parse (บริบทบริบท) {this.context = บริบท; // ในนิพจน์การแยกวิเคราะห์รายการ ListExpression ลูปเพื่อตีความแต่ละคำในคำสั่งจนกว่านิพจน์เทอร์มิเนเตอร์หรือข้อยกเว้นจะออกในขณะที่ (จริง) {ถ้า (this.context.getCurrentToken () == null) {// รับโหนดปัจจุบัน ถ้าเป็นโมฆะก็หมายความว่านิพจน์สุดท้ายจะหายไป System.out.println ("ข้อผิดพลาด: การหมดอายุหายไป 'สิ้นสุด'!"); หยุดพัก; } อื่นถ้า (this.context.equalswithcommand ("end")) {this.context.next (); // การแยกวิเคราะห์ปกติจะสิ้นสุดลง } else {// สร้างนิพจน์คำสั่ง iexpressions expressions = new CommandExpersion (this.context); // เพิ่มใน list.add (นิพจน์); }}} / *** ใช้วิธีการอธิบาย* / @Override โมฆะสาธารณะตีความ () {// วนคำอธิบายของแต่ละนิพจน์ในรายการรายการเพื่อเรียกใช้ตัววนซ้ำ <Iexpressions> iterator = list.iterator (); ในขณะที่ (iterator.hasnext ()) {(iterator.next ()). ตีความ (); -4.5 นิพจน์คำสั่ง - คำสั่งการเพียบ
แพ็คเกจ com.demo.interpreter.express; นำเข้า com.demo.interpreter.context.context;/** * นิพจน์คำสั่ง * * @author * */คลาสสาธารณะ Commandexpersion ใช้ IExpressions {บริบทบริบทสุดท้ายส่วนตัว; การแสดงออกของ IExpressions ส่วนตัว / ** * วิธีการสร้างผ่านบริบทที่จะแยกวิเคราะห์ลงในบริบท * * @param */ public CommandExperssion (บริบทบริบท) {this.context = บริบท; this.parse (this.context); } public void parse (บริบทบริบท) {// การตัดสินหมวดหมู่คำสั่งปัจจุบันแยกแยะเฉพาะและคำสั่งดั้งเดิมถ้า (this.context.equalswithCommand ("for")) {// สร้างเพื่อนิพจน์สำหรับการวิเคราะห์การวิเคราะห์ } else {// สร้างนิพจน์คำสั่งต้นฉบับสำหรับการแยกการวิเคราะห์เนื้อหา = primitiveExpression ใหม่ (this.context); }} / *** การแยกวิเคราะห์เนื้อหา* / @Override โมฆะสาธารณะตีความ () {// การแยกวิเคราะห์เนื้อหา this.Expressions.interpret (); -4.6 Expression - Forexpression
แพ็คเกจ com.demo.interpreter.express; นำเข้า com.demo.interpreter.context.context;/** * สำหรับนิพจน์ * * @author * */คลาสสาธารณะ Forexpression ใช้ IExpressions {บริบทบริบทสุดท้ายส่วนตัว; // จัดเก็บตัวแปรคีย์ดัชนีดัชนีปัจจุบันตัวแปรส่วนตัว; // จัดเก็บตำแหน่งเริ่มต้นของ Loop Private Int Start_index; // เก็บตำแหน่งสิ้นสุดของลูปส่วนตัว INT end_index; การแสดงออกของ IExpressions ส่วนตัว / ** * ตัวสร้างผ่านบริบทที่จะแยกวิเคราะห์ลงในบริบท * * @param */ public forexpression (บริบทบริบท) {this.context = บริบท; this.parse (this.context); } / *** การแยกวิเคราะห์นิพจน์* / @Override โมฆะสาธารณะแยกวิเคราะห์ (บริบทบริบท) {// ก่อนอื่นรับโหนดปัจจุบัน this.context.next (); ในขณะที่ (จริง) {// ตัดสินโหนดถ้า (this.context.equalswithCommand ("จาก")) {// ตั้งค่าสตริงเนื้อหาดัชนีเริ่มต้น nextstr = this.context.next (); ลอง {this.start_index = integer.parseint (nextstr); } catch (exception e) {system.out .println ("ข้อผิดพลาด: หลัง 'จาก' การแสดงออกที่มีอยู่ 'โปรดตรวจสอบรูปแบบของนิพจน์ถูกต้อง!"); หยุดพัก; } // รับโหนดถัดไป this.context.next (); } อื่นถ้า (this.context.equalswithcommand ("ถึง")) {// ตั้งค่าสตริงเนื้อหาดัชนีสิ้นสุด nextStr = this.context.next (); ลอง {this.end_index = integer.parseint (nextstr); } catch (exception e) {system.out .println ("ข้อผิดพลาด: หลัง 'ถึง' การแสดงออกที่มีอยู่ 'โปรดตรวจสอบรูปแบบของนิพจน์ถูกต้อง!"); } this.context.next (); หยุดพัก; } else {// ตั้งค่าเนื้อหาของตัวแปรดัชนีปัจจุบันถ้า (this.variable == null) {this.variable = this.context.getCurrentToken (); } // รับโหนดถัดไป this.context.next (); }} // สร้างรายการนิพจน์ this.expressions = new ListExpression (); this.expressions.parse (this.context); } / *** ใช้วิธีการอธิบาย* / @Override โมฆะสาธารณะตีความ () {// สร้างนิพจน์คำสั่งสำหรับ (int x = this.start_index; x <= this.end_index; x ++) {// ตั้งเนื้อหาตัวแปร this.context.put ("" this.variable, x); // ดำเนินการคำอธิบายวิธีนี้ expressions.interpret (); } // ลบเนื้อหาตัวแปรชั่วคราวที่ใช้ this.context.clear ("" + this.variable); -4.7 นิพจน์พื้นฐาน - PrimitiveExpression
แพ็คเกจ com.demo.interpreter.express; นำเข้า com.demo.interpreter.context.context;/** * นิพจน์พื้นฐานที่สุด * * @author * */คลาสสาธารณะ PrimitiveExpression ใช้ IExpressions {บริบทบริบทส่วนตัว; // ชื่อโหนดสตริงส่วนตัว tokenname; // เนื้อหาข้อความข้อความสตริงส่วนตัว; / ** * ตัวสร้างผ่านบริบทที่จะแยกวิเคราะห์ลงในบริบท * * @param */ primitiveExpression สาธารณะ (บริบทบริบท) {this.parse (บริบท); } @Override โมฆะสาธารณะแยกวิเคราะห์ (บริบทบริบท) {this.context = บริบท; this.tokenName = this.context.getCurrentToken (); this.context.next (); if ("println" .equals (this.tokenname)) {this.text = this.context.getCurrentToken (); this.context.next (); }} / *** วิธีการใช้งานคำอธิบาย* / @Override โมฆะสาธารณะตีความ () {// ก่อนอื่นรับเนื้อหาโหนดปัจจุบันถ้า ("println" .Equals (toKenname)) {// ได้รับข้อมูลเนื้อหา // ระบบเนื้อหาพิมพ์. -4.8 ให้ล่ามภาษาเริ่มทำงาน - ไคลเอนต์
แพ็คเกจ com.demo.interpreter; นำเข้า com.demo.interpreter.express.iexpressions; นำเข้า com.demo.interpreter.express.programexpression;/** * แอปพลิเคชันหลัก * * @author */ไคลเอนต์คลาสสาธารณะ {/** * @param args */สาธารณะ 90 ถึง 100 println ฉันจบ println end ... end "; System.out.println ("str:" + str); // สร้างนิพจน์โปรแกรม IExpressions Expressions = ใหม่ programexpression (STR); // อธิบายการดำเนินการของนิพจน์การตีความ (); -5 ผลการทำงาน
str: โปรแกรม println start ... สำหรับ i จาก 90 ถึง 100 println ฉันจบ println end ... สิ้นสุด
เริ่ม...
90
91
92
93
94
95
96
97
98
99
100
จบ...
สามหลักการออกแบบ
หลักการ 1 "Open-Close"
2 หลักการของการเปลี่ยนแปลงปิด
สี่ครั้งการใช้งาน
(1) ปัญหาเฉพาะประเภทเกิดขึ้นที่ความถี่สูงและกฎทางธุรกิจเปลี่ยนไปบ่อยครั้งและสถานการณ์ที่คล้ายกันเกิดขึ้นซ้ำ ๆ
(2) กฎทางธุรกิจไม่ซับซ้อนและยุ่งยากเกินไปและง่ายต่อการใช้กฎไวยากรณ์ที่เป็นนามธรรม
(3) ประสิทธิภาพไม่ได้เป็นปัจจัยหลักที่พิจารณาในระบบซอฟต์แวร์
แผนภาพคลาสล่ามห้าโหมดสแตติกคลาส
สำหรับเนื้อหาที่เกี่ยวข้องกับ Java ผู้อ่านที่สนใจในเว็บไซต์นี้สามารถดูหัวข้อ: "บทนำและการสอนขั้นสูงเกี่ยวกับการเขียนโปรแกรมเชิงวัตถุ Java", "การสอนเกี่ยวกับโครงสร้างข้อมูล Java และอัลกอริทึม" สรุปการดำเนินงานของ Java
ฉันหวังว่าบทความนี้จะเป็นประโยชน์กับการเขียนโปรแกรม Java ของทุกคน