在SQR中使用Break逻辑

本文介绍了SQR程序中如何使用Break逻辑来处理数据变化,包括On-Break选项的不同限定词及其应用实例。同时,还讲解了如何使SQR程序APIWare以支持进程调度器的状态更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


在报表中,当一列值改变时,也就是出现break时,通常会做一些特殊处理,比如跳过一行、在break之前或之后执行某个procedure、打印小计等等。

不使用Break逻辑

如下例,针对选择的每一个员工,打印该员工的姓名、公司和员工薪水。该例不使用任何break逻辑:

!****************************
!An employee list program that uses no break logic
!****************************
Begin-Program
!****************************
Do List_Employees
End-Program
!****************************
Begin-Heading 2
!****************************
Print 'Company' (1,1)
Print 'Paygroup' (,+2)
Print 'Emplid' (,+2)
Print 'Name ' (,+4)
Print 'Annual Salary' (,+15)
Print ' ' (2,1)
End-Heading
!*****************************************
Begin-Procedure List_Employees
!*****************************************
Begin-Select
B.Company (,1,7)
B.Paygroup (,+2,8)
A.Emplid (,+2,8)
A.Name (,+2,20)
B.Annual_Rt (,+2,12) Edit $,$$$,$$$.00
Position (+1)
From PS_Personal_Data A, PS_Job B
Where A.Emplid=B.Emplid
And B.Effdt=(Select Max(D.Effdt) From PS_Job D
Where D.Effdt<=Sysdate
And D.Emplid=B.Emplid
And D.Empl_Rcd=B.Empl_Rcd)
And B.Effseq = (Select Max(C.Effseq) from PS_Job C
Where C.Emplid=B.Emplid
And C.Empl_Rcd = B.Empl_Rcd
And C.Effdt=B.Effdt)
Order By B.Company, B.Paygroup, A.Emplid

End-Select
End-Procedure
!****************************
该SQR报表输出如下:


使用Print命令的On-Break选项

当某个输出字段的值改变时,On-Break选项会触发指定的操作。可以指定 On-Break 选项的一些限定词(qualifier),这些限定词定义了当break出现时要采取的操作。使用最频繁的限定词是Print(不要与Print命令搞混了)。Print 限定词是On-Break选项的默认限定词。当制定On-Break选项时不必指定该限定词。当使用On-break 选项的 Print 限定词时,可以指定 break 字段何时被打印或不被打印:

  • Always      总是打印Break 字段。
  • Change     只有当break字段的值改变时才打印。默认为Change。
  • Change/Top-Page     1.当break字段的值改变时打印 2.在每一页的顶部时打印
  • Never        break字段永远不打印

如下例:

!****************************
!Using break logic in the employee list program
!****************************
Begin-Program
!****************************
Do List_Employees
End-Program
!****************************
Begin-Heading 2
!****************************
Print 'Company' (1,1)
Print 'Paygroup' (,+2)
Print 'Emplid' (,+2)
Print 'Name ' (,+4)
Print 'Annual Salary' (,+15)
Print ' ' (2,1)
End-Heading
!*****************************************
Begin-Procedure List_Employees
!*****************************************
Begin-Select
! We use the On-Break option below:
B.Company (,1,7) On-Break Print=Change/Top-Page Skiplines=1
B.Paygroup (,+2,8)
A.Emplid (,+2,8)
A.Name (,+2,20)
B.Annual_Rt (,+2,12) edit $,$$$,$$$.00
          Position (+1)
From PS_Personal_Data A, PS_Job B
Where A.Emplid=B.Emplid
And B.Effdt=(Select Max(D.Effdt) From PS_Job D
Where D.Effdt<=Sysdate
And D.Emplid=B.Emplid
And D.Empl_Rcd=B.Empl_Rcd)
And B.Effseq = (Select Max(C.Effseq) from PS_Job C
Where C.Emplid=B.Emplid
And C.Empl_Rcd = B.Empl_Rcd
And C.Effdt=B.Effdt)
Order By B.Company, B.Paygroup, A.Emplid
End-Select
End-Procedure
!****************************

输出结果如下:

1.当break字段的值改变时打印:



2.在每一页的顶部时打印



在上面的例子中,我将Company字段作为一个break字段,对其使用On-Break选项。除了Pritn限定词外,还是用了另外一个限定词Skiplines。该限定词指定当出现break时应该跳过多少行。

使SQR程序API Ware

要想在进程调度器中执行SQR程序,且又要使进程调度器能够更新SQR程序的运行状态,就必须要使SQR程序API Ware。也就是说必须在SQR成添加一些能够将SQR程序的状态返回给进程调度器的代码,从而让Process Monitor能够反应程序的当前状态。可以通过#Include命令包含PeopleSoft 自带的一些SQC文件。如上例,因为没有#include任何SQC文件,所以在进程监控器中出现如下结果:


可见程序已经成功Posted,但是状态却为Error。

修改TEST10B.SQR程序:

!****************************
!TEST10B.SQR
!Using break logic in the employee list program
!****************************

#Include 'setenv.sqc' !Set environment
begin-setup
#Include 'setupdb.sqc'
end-setup

Begin-Program
   Do Stdapi-Init
   
   Do List_Employees

   Do Stdapi-Term
End-Program
!****************************
Begin-Heading 2
!****************************
Print 'Company' (1,1)
Print 'Paygroup' (,+2)
Print 'Emplid' (,+2)
Print 'Name ' (,+4)
Print 'Annual Salary' (,+15)
Print ' ' (2,1)
End-Heading
!*****************************************
Begin-Procedure List_Employees
!*****************************************
Begin-Select
! We use the On-Break option below:
B.Company (,1,7) On-Break Print=Change/Top-Page Skiplines=1
B.Paygroup (,+2,8)
A.Emplid (,+2,8)
A.Name (,+2,20)
B.Annual_Rt (,+2,12) edit $,$$$,$$$.00
          Position (+1)
From PS_Personal_Data A, PS_Job B
Where A.Emplid=B.Emplid
And B.Effdt=(Select Max(D.Effdt) From PS_Job D
Where D.Effdt<=Sysdate
And D.Emplid=B.Emplid
And D.Empl_Rcd=B.Empl_Rcd)
And B.Effseq = (Select Max(C.Effseq) from PS_Job C
Where C.Emplid=B.Emplid
And C.Empl_Rcd = B.Empl_Rcd
And C.Effdt=B.Effdt)
Order By B.Company, B.Paygroup, A.Emplid
End-Select
End-Procedure
!****************************
#Include 'datetime.sqc' !Routines for date and time formatting
#Include 'stdapi.sqc'


运行结果如下:








import java.io.*; import java.util.*; import java.util.function.*; import java.util.stream.*; import java.util.regex.*; public class BasicToJavaCompiler { /********************** 词法分析相关代码 ************************/ // 定义词法单元类型 private enum TokenType { KEYWORD, IDENTIFIER, NUMBER, STRING, OPERATOR, PUNCTUATION, NEWLINE, EOF, COMMENT } // 定义词法单元类,用于存储词法单元信息 private static class Token { TokenType type; // 词法单元类型 String value; // 词法单元值 int lineNumber; // 词法单元所在行号 public Token(TokenType type, String value, int lineNumber) { this.type = type; this.value = value; this.lineNumber = lineNumber; } public String getValue() { return value; } public TokenType getType() { return type; } } // 扫描器类,用于将源代码转换为词法单元序列 private static class Scanner { private String source; // 源代码 private int current; // 当前位置 private int start; // 当前词法单元起始位置 private int line; // 当前行号 private List<Token> tokens; // 存储生成的词法单元 private int errorCount; // 错误计数 private static final Set<String> keywords = new HashSet<>(); static { // 初始化关键字集合 keywords.add("IF"); keywords.add("THEN"); keywords.add("ELSE"); keywords.add("ELSEIF"); keywords.add("ENDIF"); keywords.add("WHILE"); keywords.add("DO"); keywords.add("LOOP"); keywords.add("FOR"); keywords.add("TO"); keywords.add("STEP"); keywords.add("NEXT"); keywords.add("SUB"); keywords.add("FUNCTION"); keywords.add("RETURN"); keywords.add("DIM"); keywords.add("CONST"); keywords.add("AS"); keywords.add("INTEGER"); keywords.add("DOUBLE"); keywords.add("STRING"); keywords.add("BOOLEAN"); keywords.add("CHAR"); keywords.add("DATE"); keywords.add("ARRAY"); keywords.add("TRUE"); keywords.add("FALSE"); keywords.add("PRINT"); keywords.add("INPUT"); keywords.add("CLASS"); keywords.add("PUBLIC"); keywords.add("PRIVATE"); keywords.add("END"); keywords.add("AND"); keywords.add("OR"); keywords.add("NOT"); keywords.add("REDIM"); keywords.add("CONCAT"); keywords.add("LEN"); keywords.add("MID"); keywords.add("LEFT"); keywords.add("RIGHT"); keywords.add("CHR"); keywords.add("ASC"); keywords.add("VAL"); keywords.add("STR"); keywords.add("ABS"); keywords.add("SQR"); keywords.add("SIN"); keywords.add("COS"); keywords.add("TAN"); keywords.add("EXP"); keywords.add("LOG"); keywords.add("RND"); keywords.add("NEW"); keywords.add("NULL"); keywords.add("THIS"); } public Scanner(String source) { this.source = source; this.current = 0; this.start = 0; this.line = 1; this.tokens = new ArrayList<>(); this.errorCount = 0; } // 扫描源代码并生成词法单元列表 public List<Token> scanTokens() { while (!isAtEnd()) { start = current; scanToken(); } // 添加文件结束符 tokens.add(new Token(TokenType.EOF, "", line)); return tokens; } // 扫描单个词法单元 private void scanToken() { char c = advance(); switch (c) { // 标点符号处理 case '(': addToken(TokenType.PUNCTUATION, "("); break; case ')': addToken(TokenType.PUNCTUATION, ")"); break; case '{': addToken(TokenType.PUNCTUATION, "{"); break; case '}': addToken(TokenType.PUNCTUATION, "}"); break; case '[': addToken(TokenType.PUNCTUATION, "["); break; case ']': addToken(TokenType.PUNCTUATION, "]"); break; case ',': addToken(TokenType.PUNCTUATION, ","); break; case '.': addToken(TokenType.PUNCTUATION, "."); break; case ';': addToken(TokenType.PUNCTUATION, ";"); break; // 运算符处理 case '+': addToken(TokenType.OPERATOR, "+"); break; case '-': addToken(TokenType.OPERATOR, "-"); break; case '*': addToken(TokenType.OPERATOR, "*"); break; case '/': addToken(TokenType.OPERATOR, "/"); break; case '%': addToken(TokenType.OPERATOR, "%"); break; case '=': addToken(TokenType.OPERATOR, "="); break; case '!': addToken(TokenType.OPERATOR, "!"); break; case '<': addToken(TokenType.OPERATOR, "<"); break; case '>': addToken(TokenType.OPERATOR, ">"); break; // 字符串处理 case '"': string(); break; // 注释处理 case '\'': comment(); break; // 换行处理 case '\n': line++; break; // 忽略空白字符 case ' ': case '\r': case '\t': break; // 数字处理 default: if (isDigit(c)) { number(); } // 标识符或关键字处理 else if (isAlpha(c)) { identifier(); } // 其他非法字符处理 else { addError("Unexpected character: " + c); } } } // 处理注释 private void comment() { while (peek() != '\n' && !isAtEnd()) { advance(); } String commentText = source.substring(start, current); addToken(TokenType.COMMENT, commentText.trim()); } // 处理字符串 private void string() { while (peek() != '"' && !isAtEnd()) { if (peek() == '\n') line++; advance(); } if (isAtEnd()) { addError("Unterminated string."); return; } advance(); String value = source.substring(start + 1, current - 1); addToken(TokenType.STRING, value); } // 处理数字 private void number() { while (isDigit(peek())) advance(); if (peek() == '.' && isDigit(peekNext())) { advance(); while (isDigit(peek())) advance(); } String value = source.substring(start, current); addToken(TokenType.NUMBER, value); } // 处理标识符和关键字 private void identifier() { while (isAlphaNumeric(peek())) advance(); String value = source.substring(start, current); if (keywords.contains(value.toUpperCase())) { addToken(TokenType.KEYWORD, value.toUpperCase()); } else { addToken(TokenType.IDENTIFIER, value); } } // 辅助函数:获取当前位置字符 private char peek() { if (isAtEnd()) return '\0'; return source.charAt(current); } // 辅助函数:获取下一个字符 private char peekNext() { if (current + 1 >= source.length()) return '\0'; return source.charAt(current + 1); } // 辅助函数:检查是否为字母 private boolean isAlpha(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; } // 辅助函数:检查是否为字母或数字 private boolean isAlphaNumeric(char c) { return isAlpha(c) || isDigit(c); } // 辅助函数:检查是否为数字 private boolean isDigit(char c) { return c >= '0' && c <= '9'; } // 辅助函数:检查是否到达文件末尾 private boolean isAtEnd() { return current >= source.length(); } // 辅助函数:获取下一个字符并移动位置 private char advance() { return source.charAt(current++); } // 辅助函数:添加词法单元 private void addToken(TokenType type, String value) { tokens.add(new Token(type, value, line)); } // 辅助函数:报告错误 private void addError(String message) { errorCount++; System.err.println("错误发生在第 " + line + " 行: " + message); } } /********************** 语法分析相关代码 ************************/ // 解析器类,用于将词法单元序列转换为抽象语法树 private static class Parser { private List<Token> tokens; // 词法单元列表 private int current; // 当前位置 private int line; // 当前行号 public Parser(List<Token> tokens) { this.tokens = tokens; this.current = 0; this.line = 1; } // 开始解析 public void parse() { while (!isAtEnd()) { parseStatement(); } } // 解析语句 private void parseStatement() { if (match(TokenType.KEYWORD, "IF")) { parseIfStatement(); } else if (match(TokenType.KEYWORD, "WHILE")) { parseWhileStatement(); } else if (match(TokenType.KEYWORD, "FOR")) { parseForStatement(); } else if (match(TokenType.KEYWORD, "SUB")) { parseSubRoutine(); } else if (match(TokenType.KEYWORD, "FUNCTION")) { parseFunction(); } else if (match(TokenType.KEYWORD, "CLASS")) { parseClass(); } else if (match(TokenType.KEYWORD, "DIM")) { parseVariableDeclaration(); } else if (match(TokenType.KEYWORD, "CONST")) { parseConstantDeclaration(); } else if (match(TokenType.KEYWORD, "PRINT")) { parsePrintStatement(); } else if (match(TokenType.KEYWORD, "INPUT")) { parseInputStatement(); } else if (match(TokenType.KEYWORD, "RETURN")) { parseReturnStatement(); } else if (match(TokenType.KEYWORD, "REDIM")) { parseRedimStatement(); } else { parseExpressionStatement(); } } // 解析IF语句 private void parseIfStatement() { consume(TokenType.KEYWORD, "IF"); parseExpression(); consume(TokenType.KEYWORD, "THEN"); parseBlock(); while (match(TokenType.KEYWORD, "ELSEIF")) { consume(TokenType.KEYWORD, "IF"); parseExpression(); consume(TokenType.KEYWORD, "THEN"); parseBlock(); } if (match(TokenType.KEYWORD, "ELSE")) { parseBlock(); } consume(TokenType.KEYWORD, "ENDIF"); } // 解析WHILE语句 private void parseWhileStatement() { consume(TokenType.KEYWORD, "WHILE"); parseExpression(); parseBlock(); consume(TokenType.KEYWORD, "END", "WHILE"); } // 解析FOR语句 private void parseForStatement() { consume(TokenType.KEYWORD, "FOR"); parseVariableDeclaration(); consume(TokenType.KEYWORD, "TO"); parseExpression(); if (match(TokenType.KEYWORD, "STEP")) { parseExpression(); } parseBlock(); consume(TokenType.KEYWORD, "NEXT"); } // 解析SUB过程 private void parseSubRoutine() { consume(TokenType.KEYWORD, "SUB"); String name = consume(TokenType.IDENTIFIER).value; parseParameters(); parseBlock(); consume(TokenType.KEYWORD, "END", "SUB"); } // 解析FUNCTION函数 private void parseFunction() { consume(TokenType.KEYWORD, "FUNCTION"); String name = consume(TokenType.IDENTIFIER).value; parseParameters(); parseReturnType(); parseBlock(); consume(TokenType.KEYWORD, "END", "FUNCTION"); } // 解析返回类型 private void parseReturnType() { if (match(TokenType.KEYWORD, "AS")) { consume(TokenType.KEYWORD, "AS"); consume(TokenType.KEYWORD); } } // 解析类定义 private void parseClass() { consume(TokenType.KEYWORD, "CLASS"); String name = consume(TokenType.IDENTIFIER).value; parseBlock(); consume(TokenType.KEYWORD, "END", "CLASS"); } // 解析变量声明 private void parseVariableDeclaration() { consume(TokenType.KEYWORD, "DIM"); String name = consume(TokenType.IDENTIFIER).value; parseVariableType(); parseVariableInitializer(); if (match(TokenType.PUNCTUATION, "(")) { parseArrayDimensions(); consume(TokenType.PUNCTUATION, ")"); } consume(TokenType.PUNCTUATION, ";"); } // 解析变量类型 private void parseVariableType() { if (match(TokenType.KEYWORD, "AS")) { consume(TokenType.KEYWORD, "AS"); consume(TokenType.KEYWORD); } } // 解析变量初始化 private void parseVariableInitializer() { if (match(TokenType.OPERATOR, "=")) { parseExpression(); } } // 解析常量声明 private void parseConstantDeclaration() { consume(TokenType.KEYWORD, "CONST"); String name = consume(TokenType.IDENTIFIER).value; consume(TokenType.OPERATOR, "="); parseExpression(); consume(TokenType.PUNCTUATION, ";"); } // 解析数组维度 private void parseArrayDimensions() { do { parseExpression(); } while (match(TokenType.PUNCTUATION, ",")); } // 解析数组重新定义 private void parseRedimStatement() { consume(TokenType.KEYWORD, "REDIM"); String name = consume(TokenType.IDENTIFIER).value; consume(TokenType.PUNCTUATION, "("); parseArrayDimensions(); consume(TokenType.PUNCTUATION, ")"); consume(TokenType.PUNCTUATION, ";"); } // 解析PRINT语句 private void parsePrintStatement() { consume(TokenType.KEYWORD, "PRINT"); parseExpression(); consume(TokenType.PUNCTUATION, ";"); } // 解析INPUT语句 private void parseInputStatement() { consume(TokenType.KEYWORD, "INPUT"); String prompt = ""; if (match(TokenType.STRING)) { prompt = consume(TokenType.STRING).value; } consume(TokenType.PUNCTUATION, ","); String variable = consume(TokenType.IDENTIFIER).value; consume(TokenType.PUNCTUATION, ";"); } // 解析RETURN语句 private void parseReturnStatement() { consume(TokenType.KEYWORD, "RETURN"); if (!match(TokenType.PUNCTUATION, ";")) { parseExpression(); } consume(TokenType.PUNCTUATION, ";"); } // 解析表达式语句 private void parseExpressionStatement() { parseExpression(); consume(TokenType.PUNCTUATION, ";"); } // 解析代码块 private void parseBlock() { if (match(TokenType.PUNCTUATION, "{")) { while (!check(TokenType.PUNCTUATION, "}") && !isAtEnd()) { parseStatement(); } consume(TokenType.PUNCTUATION, "}"); } else { parseStatement(); } } // 解析参数列表 private void parseParameters() { if (match(TokenType.PUNCTUATION, "(")) { while (!check(TokenType.PUNCTUATION, ")")) { String name = consume(TokenType.IDENTIFIER).value; parseVariableType(); if (!match(TokenType.PUNCTUATION, ")")) { consume(TokenType.PUNCTUATION, ","); } } consume(TokenType.PUNCTUATION, ")"); } } // 解析表达式 private void parseExpression() { parseAssignment(); } // 解析赋值表达式 private void parseAssignment() { parseOr(); if (match(TokenType.OPERATOR, "=")) { parseExpression(); } } // 解析逻辑或表达式 private void parseOr() { parseAnd(); while (match(TokenType.KEYWORD, "OR")) { parseAnd(); } } // 解析逻辑与表达式 private void parseAnd() { parseEquality(); while (match(TokenType.KEYWORD, "AND")) { parseEquality(); } } // 解析等于表达式 private void parseEquality() { parseComparison(); while (match(TokenType.OPERATOR, "==", "!=")) { parseComparison(); } } // 解析比较表达式 private void parseComparison() { parseTerm(); while (match(TokenType.OPERATOR, "<", ">", "<=", ">=")) { parseTerm(); } } // 解析乘除表达式 private void parseTerm() { parseFactor(); while (match(TokenType.OPERATOR, "+", "-")) { parseFactor(); } } // 解析因子 private void parseFactor() { parseUnary(); while (match(TokenType.OPERATOR, "*", "/", "%")) { parseUnary(); } } // 解析一元运算符 private void parseUnary() { if (match(TokenType.OPERATOR, "-", "+", "NOT")) { parseUnary(); } else { parsePrimary(); } } // 解析主表达式 private void parsePrimary() { if (match(TokenType.NUMBER)) { // 数字字面量 } else if (match(TokenType.STRING)) { // 字符串字面量 } else if (match(TokenType.IDENTIFIER)) { // 变量或函数调用 if (match(TokenType.PUNCTUATION, "(")) { parseArguments(); consume(TokenType.PUNCTUATION, ")"); } } else if (match(TokenType.PUNCTUATION, "(")) { parseExpression(); consume(TokenType.PUNCTUATION, ")"); } else if (match(TokenType.KEYWORD, "TRUE", "FALSE")) { // 布尔字面量 } else { addError("Expect expression."); } } // 解析参数列表 private void parseArguments() { if (!check(TokenType.PUNCTUATION, ")")) { do { parseExpression(); } while (match(TokenType.PUNCTUATION, ",")); } } // 辅助函数:匹配指定词法单元 private boolean match(TokenType type, String... values) { if (isAtEnd()) return false; Token token = tokens.get(current); if (token.type != type) return false; if (values.length > 0 && !Arrays.asList(values).contains(token.value)) return false; current++; line = token.lineNumber; return true; } // 辅助函数:检查当前词法单元 private boolean check(TokenType type, String value) { if (isAtEnd()) return false; Token token = tokens.get(current); return token.type == type && token.value.equals(value); } // 辅助函数:消耗指定词法单元 private Token consume(TokenType type) { if (check(type, null)) { return advance(); } addError("Expect " + type + "."); return null; } // 辅助函数:消耗指定词法单元 private Token consume(TokenType type, String value) { if (check(type, value)) { return advance(); } addError("Expect " + value + "."); return null; } // 辅助函数:消耗指定词法单元(多个可能的值) private Token consume(TokenType type, String... values) { if (isAtEnd()) return null; Token token = tokens.get(current); if (token.type != type) { addError("Expect " + type + "."); return null; } if (values.length > 0 && !Arrays.asList(values).contains(token.value)) { addError("Expect one of: " + String.join(", ", values) + "."); return null; } return advance(); } // 辅助函数:前进到下一个词法单元 private Token advance() { if (!isAtEnd()) current++; return previous(); } // 辅助函数:获取上一个词法单元 private Token previous() { return tokens.get(current - 1); } // 辅助函数:检查是否到达文件末尾 private boolean isAtEnd() { return current >= tokens.size() || tokens.get(current).getType() == TokenType.EOF; } // 辅助函数:报告错误 private void addError(String message) { Token token = peek(); System.err.println("错误发生在第 " + token.lineNumber + " 行: " + message); } // 辅助函数:获取当前词法单元 private Token peek() { return tokens.get(current); } } /********************** 代码生成相关代码 ************************/ // 代码生成器类,用于将抽象语法树转换为Java代码 private static class CodeGenerator { private PrintWriter writer; private int indentation; private StringBuilder currentLine; private Map<String, String> symbolTable; private Map<String, String> typeTable; private boolean inClass; private boolean inMethod; private List<Token> tokens; private int current; public CodeGenerator(PrintWriter writer) { this.writer = writer; this.indentation = 0; this.currentLine = new StringBuilder(); this.symbolTable = new HashMap<>(); this.typeTable = new HashMap<>(); this.inClass = false; this.inMethod = false; this.tokens = new ArrayList<>(); this.current = 0; } public void generate(List<Token> tokens) { try { this.tokens = tokens; writer.println("// Generated Java code from BASIC"); writer.println("import java.util.Scanner;"); writer.println("import java.util.ArrayList;"); writer.println("import java.util.List;"); writer.println("import java.time.LocalDate;"); writer.println("public class BasicProgram {"); indent(); // 生成main方法 writer.println("public static void main(String[] args) {"); indent(); // 处理词法单元 for (Token token : tokens) { switch (token.getType()) { case KEYWORD: generateKeyword(token.getValue()); break; case IDENTIFIER: generateIdentifier(token.getValue()); break; case NUMBER: generateNumber(token.getValue()); break; case STRING: generateString(token.getValue()); break; case OPERATOR: generateOperator(token.getValue()); break; case PUNCTUATION: generatePunctuation(token.getValue()); break; case NEWLINE: writer.println(currentLine.toString()); currentLine = new StringBuilder(); break; case COMMENT: currentLine.append("// ").append(token.getValue().trim()); break; } } // 关闭main方法 outdent(); writer.println("}"); // 关闭类 outdent(); writer.println("}"); writer.close(); } catch (Exception e) { System.err.println("代码生成错误: " + e.getMessage()); } } private void generateKeyword(String value) { switch (value.toUpperCase()) { case "IF": currentLine.append("if ("); break; case "THEN": currentLine.append(") {"); indent(); break; case "ELSE": outdent(); currentLine.append("} else {"); indent(); break; case "ELSEIF": outdent(); currentLine.append("} else if ("); break; case "ENDIF": outdent(); writer.println(currentLine.toString()); currentLine = new StringBuilder(); writer.println("}"); break; case "WHILE": currentLine.append("while ("); break; case "DO": currentLine.append(") {"); indent(); break; case "LOOP": outdent(); writer.println(currentLine.toString()); currentLine = new StringBuilder(); writer.println("}"); break; case "FOR": currentLine.append("for ("); break; case "TO": currentLine.append("; "); break; case "STEP": currentLine.append(";"); break; case "NEXT": outdent(); writer.println(currentLine.toString()); currentLine = new StringBuilder(); writer.println("}"); break; case "SUB": outdent(); outdent(); String subName = getPreviousIdentifier(); currentLine.append("public static void ").append(subName).append("("); parseParameterList(); writer.println(currentLine.toString() + ") {"); indent(); indent(); inMethod = true; break; case "FUNCTION": outdent(); outdent(); String returnType = getPreviousType(); String funcName = getPreviousIdentifier(); currentLine.append("public static ").append(mapBasicTypeToJava(returnType)).append(" ").append(funcName).append("("); parseParameterList(); writer.println(currentLine.toString() + ") {"); indent(); indent(); inMethod = true; break; case "RETURN": currentLine.append("return"); if (!lookahead(TokenType.PUNCTUATION, ";")) { parseExpression(); } writer.println(currentLine.toString() + ";"); currentLine = new StringBuilder(); break; case "DIM": outdent(); outdent(); String varType = ""; if (lookahead(TokenType.KEYWORD, "AS")) { advance(); varType = mapBasicTypeToJava(consume(TokenType.KEYWORD).getValue()); } String varName = getPreviousIdentifier(); currentLine.append(varType).append(" ").append(varName); if (lookahead(TokenType.OPERATOR, "=")) { advance(); currentLine.append(" = "); parseExpression(); } writer.println(currentLine.toString() + ";"); currentLine = new StringBuilder(); break; case "CONST": String constType = ""; if (lookahead(TokenType.KEYWORD, "AS")) { advance(); constType = mapBasicTypeToJava(consume(TokenType.KEYWORD).getValue()); } String constName = getPreviousIdentifier(); currentLine.append("final ").append(constType).append(" ").append(constName).append(" = "); parseExpression(); writer.println(currentLine.toString() + ";"); currentLine = new StringBuilder(); break; case "PRINT": currentLine.append("System.out.print("); break; case "INPUT": currentLine.append("Scanner scanner = new Scanner(System.in);\n"); currentLine.append("String input = scanner.nextLine();"); break; case "CLASS": outdent(); outdent(); writer.println("class " + getPreviousIdentifier() + " {"); indent(); inClass = true; break; case "END": String endType = consume(TokenType.KEYWORD).getValue(); switch (endType.toUpperCase()) { case "SUB": case "FUNCTION": outdent(); outdent(); writer.println("}"); inMethod = false; break; case "CLASS": outdent(); writer.println("}"); inClass = false; break; } break; case "TRUE": currentLine.append("true"); break; case "FALSE": currentLine.append("false"); break; case "REDIM": String arrayName = getPreviousIdentifier(); currentLine.append(arrayName).append(" = new ArrayList<>();"); writer.println(currentLine.toString()); currentLine = new StringBuilder(); break; case "ARRAY": if (lookahead(TokenType.PUNCTUATION, "(")) { advance(); currentLine.append("new ArrayList<>(Arrays.asList("); while (!lookahead(TokenType.PUNCTUATION, ")")) { parseExpression(); if (lookahead(TokenType.PUNCTUATION, ",")) { currentLine.append(", "); advance(); } } advance(); currentLine.append("))"); } break; } } private String mapBasicTypeToJava(String basicType) { switch (basicType.toUpperCase()) { case "INTEGER": return "int"; case "DOUBLE": return "double"; case "STRING": return "String"; case "BOOLEAN": return "boolean"; case "CHAR": return "char"; case "DATE": return "LocalDate"; case "ARRAY": return "ArrayList<Object>"; default: return "Object"; } } private void parseParameterList() { if (lookahead(TokenType.PUNCTUATION, "(")) { advance(); while (!lookahead(TokenType.PUNCTUATION, ")")) { String type = getPreviousType(); String name = getPreviousIdentifier(); currentLine.append(mapBasicTypeToJava(type)).append(" ").append(name); if (lookahead(TokenType.PUNCTUATION, ",")) { currentLine.append(", "); advance(); } } advance(); } } private void parseExpression() { while (!lookahead(TokenType.PUNCTUATION, ";") && !lookahead(TokenType.PUNCTUATION, ")")) { while (lookahead(TokenType.OPERATOR, "+", "-", "*", "/", "%")) { currentLine.append(" ").append(previousOperator()).append(" "); } while (lookahead(TokenType.OPERATOR, "==", "!=")) { currentLine.append(" ").append(previousOperator()).append(" "); } while (lookahead(TokenType.OPERATOR, "<", ">", "<=", ">=")) { currentLine.append(" ").append(previousOperator()).append(" "); } while (lookahead(TokenType.KEYWORD, "AND", "OR")) { currentLine.append(" ").append(previousOperator()).append(" "); } if (lookahead(TokenType.IDENTIFIER)) { currentLine.append(previousIdentifier()); } if (lookahead(TokenType.NUMBER)) { currentLine.append(previousNumber()); } if (lookahead(TokenType.STRING)) { currentLine.append(previousString()); } if (lookahead(TokenType.KEYWORD, "TRUE", "FALSE")) { currentLine.append(previousOperator()); } advance(); } } private String previousOperator() { if (current > 0) { current--; String op = tokens.get(current).getValue(); current++; return op; } return ""; } private String previousIdentifier() { if (current > 0) { current--; String id = tokens.get(current).getValue(); current++; return id; } return ""; } private String getPreviousIdentifier() { return tokens.get(Math.max(0, current - 1)).getValue(); } private String getPreviousType() { return tokens.get(Math.max(0, current - 1)).getValue(); } private String previousNumber() { if (current > 0) { current--; String num = tokens.get(current).getValue(); current++; return num; } return ""; } private String previousString() { if (current > 0) { current--; String str = tokens.get(current).getValue(); current++; return str; } return ""; } private void generateIdentifier(String value) { currentLine.append(value); } private void generateNumber(String value) { currentLine.append(value); } private void generateString(String value) { currentLine.append("\"").append(value).append("\""); } private void generateOperator(String value) { switch (value) { case "=": currentLine.append(" = "); break; case "+": currentLine.append(" + "); break; case "-": currentLine.append(" - "); break; case "*": currentLine.append(" * "); break; case "/": currentLine.append(" / "); break; case "==": currentLine.append(" == "); break; case "!=": currentLine.append(" != "); break; case "<": currentLine.append(" < "); break; case ">": currentLine.append(" > "); break; case "<=": currentLine.append(" <= "); break; case ">=": currentLine.append(" >= "); break; case "AND": currentLine.append(" && "); break; case "OR": currentLine.append(" || "); break; case "NOT": currentLine.append(" !"); break; } } private void generatePunctuation(String value) { switch (value) { case "(": currentLine.append("("); break; case ")": currentLine.append(")"); break; case "{": currentLine.append("{"); indent(); break; case "}": outdent(); currentLine.append("}"); break; case ",": currentLine.append(","); break; case ";": writer.println(currentLine.toString()); currentLine = new StringBuilder(); break; } } private void indent() { indentation++; } private void outdent() { if (indentation > 0) indentation--; } // 重载 lookahead 方法以支持多种参数情况 private boolean lookahead(TokenType type, String... values) { if (current >= tokens.size()) return false; Token token = tokens.get(current); if (token.getType() != type) return false; if (values.length == 0) return true; // 只检查类型 return Arrays.stream(values).anyMatch(value -> token.getValue().equals(value)); } private void advance() { if (current < tokens.size()) { current++; } } private Token consume(TokenType type) { if (current >= tokens.size()) { return new Token(TokenType.EOF, "", -1); } return tokens.get(current++); } } /********************** 主程序相关代码 ************************/ // 主程序入口 public static void main(String[] args) { if (args.length != 1) { System.err.println("错误: 参数数量不正确。正确用法: java BasicToJavaCompiler <输入文件.bas>"); System.exit(1); } String inputFilePath = args[0]; String outputFilePath = inputFilePath.replace(".bas", ".java"); try { // 读取输入文件 StringBuilder source = new StringBuilder(); BufferedReader reader = new BufferedReader(new FileReader(inputFilePath)); String line; while ((line = reader.readLine()) != null) { source.append(line).append("\n"); } reader.close(); // 扫描词法单元 Scanner scanner = new Scanner(source.toString()); List<Token> tokens = scanner.scanTokens(); // 解析并生成代码 PrintWriter writer = new PrintWriter(outputFilePath); CodeGenerator generator = new CodeGenerator(writer); generator.generate(tokens); System.out.println("编译成功。输出已写入 " + outputFilePath); writer.close(); } catch (IOException e) { System.err.println("文件操作错误: " + e.getMessage()); } } } 优化完善,能在java1.8下运行,能处理转换下面的Basic代码input.bas ' 变量声明示例 DIM x AS INTEGER = 10 DIM y AS DOUBLE = 3.14 DIM name AS STRING = "John Doe" DIM isStudent AS BOOLEAN = TRUE DIM isName AS BOOLEAN isName = FALSE ' 常量声明示例 CONST PI AS DOUBLE = 3.14159 CONST APP_NAME AS STRING = "My Basic Program" ' 数组声明示例 DIM numbers(5) AS INTEGER DIM matrix(3, 3) AS DOUBLE DIM fruits(3) AS STRING = ARRAY("Apple", "Banana", "Cherry") ' 函数和过程示例 FUNCTION add(a AS INTEGER, b AS INTEGER) AS INTEGER RETURN a + b END FUNCTION SUB greet(name AS STRING) PRINT "Hello, " + name + "!" END SUB SUB MySub() ' 条件语句示例 IF x > 10 THEN PRINT "x is greater than 10" ELSEIF x == 10 THEN PRINT "x is equal to 10" ELSE PRINT "x is less than 10" ENDIF ' 循环语句示例 FOR i = 1 TO 10 STEP 2 PRINT i NEXT i WHILE x < 20 x = x + 1 PRINT x LOOP END SUB ' 注释示例 ' 这是一个单行注释 ' 下面的代码计算两个数的和 DIM sum AS INTEGER = add(5, 3) ' 这行代码调用add函数
04-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值