基于Jflex与Java版Bison的编译器:如何实现变量重声明/未声明错误检测
Let's break down how to implement checks for undeclared/redeclared variables in your Java Bison parser—you don't need to jump through hoops like passing tokens to external instances, because Java Bison lets you embed custom logic directly in the parser class.
Core Idea
Add a symbol table as a member variable to the generated parser class, then manipulate this table directly within your grammar rule actions to validate variable declarations and usage.
Step 1: Add a Symbol Table to Your Parser Class
Use the %code class block in your .y file to inject custom members and methods into the generated parser. This is how you'll track declared variables:
%code class { // Symbol table to track declared variables (global scope for simplicity) private java.util.Set<String> declaredVars = new java.util.HashSet<>(); // Flag to track if any semantic error occurred private boolean hasSemanticError = false; // Helper method to report semantic errors private void reportSemanticError(String msg) { System.err.println("Semantic Error: " + msg); hasSemanticError = true; } }
Step 2: Check for Redeclared Variables in Declaration Rules
When your parser matches a variable declaration rule, add the variable name to the symbol table—only if it doesn't already exist. For example, if your grammar has a rule for variable declarations:
declaration: TYPE IDENTIFIER '=' expression ';' { String varName = $2.text; // $2 refers to the IDENTIFIER token, .text gets its string value if (declaredVars.contains(varName)) { reportSemanticError("Variable '" + varName + "' is redeclared"); } else { declaredVars.add(varName); } };
Here, $2 is the token object for the variable name—Java Bison exposes the token's string content via the text property.
Step 3: Check for Undeclared Variables in Usage Rules
Whenever your parser encounters a variable being used (like in an assignment or expression), verify it exists in the symbol table:
assignment: IDENTIFIER '=' expression ';' { String varName = $1.text; if (!declaredVars.contains(varName)) { reportSemanticError("Variable '" + varName + "' is undeclared"); } };
This will catch cases like your example where test2 is assigned without being declared first.
Step 4: Update the Parser's Return Logic
Modify your main method to account for both syntax and semantic errors. Since Java Bison's default parse() only checks syntax errors, you'll want to combine that with your semantic error flag:
public static void main(String args[]) throws IOException { EXAMPLELexer lexer = new EXAMPLELexer(System.in); EXAMPLE parser = new EXAMPLE(lexer); boolean syntaxValid = parser.parse(); boolean semanticValid = !parser.hasSemanticError; // Access the flag we added if (syntaxValid && semanticValid) { System.out.println("VALID FROM PARSER"); } else { System.out.println("ERROR FROM PARSER"); } }
Key Notes
- No need for %union: Java Bison doesn't support
%union, but you don't need it—you can directly access token properties liketextin rule actions. - Scope handling: If you need to support local scopes (e.g., variables inside functions), replace the
HashSetwith a stack ofSet<String>—push a new set when entering a scope, pop it when exiting. - Token access: Make sure your token definition for
IDENTIFIERis correctly set up in your JFlex.lfile—Java Bison will generate the appropriate token class with thetextproperty.
内容的提问来源于stack exchange,提问作者Chronicle

