Java PL/0 编译器词法分析器错误:Unknown token
Java PL/0 编译器词法分析器错误:Unknown token
本文将解决在 Java 编写的 PL/0 编译器词法分析器中出现的 'Unknown token' 错误。该错误通常是由于词法分析器无法识别输入代码中的某些字符或字符串导致的。
错误信息:
Exception in thread 'main' java.lang.IllegalArgumentException: Unknown token: a=10 at PL0Tokenizer.getTokenType(PL0Tokenizer.java:87) at PL0Tokenizer.main(PL0Tokenizer.java:62)
原因分析:
之前的代码中,使用 RESERVED_WORDS.containsKey(token) 来匹配保留字,这只能处理完全匹配的情况,而无法识别标识符中包含保留字的情况。例如,对于标识符 'abegin',代码会将其识别为 'Unknown token',因为它包含保留字 'begin'。
解决方案:
为了解决这个问题,需要修改词法分析器的代码,使其能够识别标识符中包含保留字的情况。以下代码展示了如何实现这一点:javaimport java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.util.HashMap;import java.util.Map;
public class PL0Tokenizer {
private static final Map<String, String> RESERVED_WORDS = new HashMap<>(); private static final Map<String, String> OPERATORS = new HashMap<>(); private static final Map<String, String> DELIMITERS = new HashMap<>(); private static final String IDENTIFIER_REGEX = '[A-Z][A-Z0-9]*'; private static final String NUMBER_REGEX = '\d+';
static { RESERVED_WORDS.put('begin', 'beginsym'); RESERVED_WORDS.put('call', 'callsym'); RESERVED_WORDS.put('const', 'constsym'); RESERVED_WORDS.put('do', 'dosym'); RESERVED_WORDS.put('end', 'endsym'); RESERVED_WORDS.put('if', 'ifsym'); RESERVED_WORDS.put('odd', 'oddsym'); RESERVED_WORDS.put('procedure', 'proceduresym'); RESERVED_WORDS.put('read', 'readsym'); RESERVED_WORDS.put('then', 'thensym'); RESERVED_WORDS.put('var', 'varsym'); RESERVED_WORDS.put('while', 'whilesym'); RESERVED_WORDS.put('write', 'writesym');
OPERATORS.put('+', 'plus'); OPERATORS.put('-', 'minus'); OPERATORS.put('*', 'times'); OPERATORS.put('/', 'slash'); OPERATORS.put('odd', 'oddsym'); OPERATORS.put('=', 'eql'); OPERATORS.put('<>', 'neq'); OPERATORS.put('<', 'lss'); OPERATORS.put('<=', 'leq'); OPERATORS.put('>', 'gtr'); OPERATORS.put('>=', 'geq'); OPERATORS.put(':=', 'becomes');
DELIMITERS.put('(', 'lparen'); DELIMITERS.put(')', 'rparen'); DELIMITERS.put(',', 'comma'); DELIMITERS.put(';', 'semicolon'); DELIMITERS.put('.', 'period'); }
public static void main(String[] args) { try { BufferedReader reader = new BufferedReader(new FileReader('input.txt')); BufferedWriter writer = new BufferedWriter(new FileWriter('output.txt'));
String line; while ((line = reader.readLine()) != null) { String[] tokens = line.split('\s+|(?<=[(),;.])|(?=[(),;.])'); for (String token : tokens) { if (!token.isEmpty()) { String tokenType = getTokenType(token); writer.write('( ' + tokenType + ', ' + token + ' )
'); } } }
reader.close(); writer.close(); } catch (IOException e) { e.printStackTrace(); } }
private static String getTokenType(String token) { if (RESERVED_WORDS.containsKey(token)) { return RESERVED_WORDS.get(token); } else if (token.matches(IDENTIFIER_REGEX)) { return 'IDENT'; } else if (token.matches(NUMBER_REGEX)) { return 'NUMBER'; } else if (OPERATORS.containsKey(token)) { return OPERATORS.get(token); } else if (DELIMITERS.containsKey(token)) { return DELIMITERS.get(token); } else { // 检查标识符是否包含保留字 for (String reservedWord : RESERVED_WORDS.keySet()) { if (token.contains(reservedWord)) { throw new IllegalArgumentException('Unknown token: ' + token); } } throw new IllegalArgumentException('Unknown token: ' + token); } }}
代码解释:
- 在
getTokenType方法中,首先检查当前 token 是否为保留字、标识符、数字、运算符或分隔符。2. 如果都不是,则遍历所有保留字,检查当前 token 是否包含任意一个保留字。3. 如果包含,则抛出 'Unknown token' 异常。
使用方法:
将上述代码保存为 PL0Tokenizer.java 文件,并使用以下命令编译运行:
javac PL0Tokenizer.javajava PL0Tokenizer
注意:
- 请确保输入文件
input.txt中的代码符合 PL/0 语法规范。2. 修改后的代码仍然可能存在其他问题,请根据实际情况进行调试和修改。
希望以上信息能够帮助您解决问题。如果问题仍然存在,请提供您的输入文件内容,以便我进行进一步的分析。
原文地址: https://www.cveoy.top/t/topic/cg1G 著作权归作者所有。请勿转载和采集!