diff --git a/AlgebraicDataflowArchitectureModel/src/code/ast/Lexer.java b/AlgebraicDataflowArchitectureModel/src/code/ast/Lexer.java new file mode 100644 index 0000000..cd2974c --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/code/ast/Lexer.java @@ -0,0 +1,55 @@ +package code.ast; + +/** + * The Lexer class provides functionalities for parsing and iterating through + * a source string of text character by character. + * + * @author s-yamagiwa; + */ +public class Lexer { + private final String source; + private int position; + + public Lexer(String source) { + this.source = source; + this.position = 0; + } + + /** + * Retrieves the next character without advancing the position. + * + * @return The next character. + */ + public char peek() { + if (position >= source.length()) { + return '\0'; // End of line + } + + return source.charAt(position); + } + + /** + * Retrieves the next character after advancing the position. + * + * @return The next character. + */ + public char peekNext() { + if (position + 1 >= source.length()) { + return '\0'; // End of line + } + + return source.charAt(position + 1); + } + + /** + * Advances the position by one character. + * + * @return The character that was previously at the current position. + */ + public char advance() { + char current = peek(); + position++; + + return current; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/code/ast/NumberLiteral.java b/AlgebraicDataflowArchitectureModel/src/code/ast/NumberLiteral.java index 21ca1e3..c397e24 100644 --- a/AlgebraicDataflowArchitectureModel/src/code/ast/NumberLiteral.java +++ b/AlgebraicDataflowArchitectureModel/src/code/ast/NumberLiteral.java @@ -6,18 +6,54 @@ * @author s-yamagiwa */ public class NumberLiteral extends Expression { + /** + * Represents the raw string value of a numeric token in the source code. + * This variable stores the literal text that defines a numeric value, including + * any prefixes, suffixes, or delimiters used in the representation of the number. + */ private String tokenValue; + /** + * Constructs a new NumberLiteral instance with the specified token value. + * + * @param tokenValue - The literal text representing the numeric value in the source code. + */ public NumberLiteral(String tokenValue) { - this.tokenValue = tokenValue; + setTokenValue(tokenValue); } + /** + * Retrieves the raw string value of the numeric token in the source code. + * + * @return The raw string value of the numeric token. + */ public String getTokenValue() { return tokenValue; } + /** + * Sets the raw string value of the numeric token in the source code. + * + * @param tokenValue - The raw string value of the numeric token. + * @throws IllegalArgumentException if the specified token value is null, empty, or invalid number representation in Java source code. + */ public void setTokenValue(String tokenValue) { - this.tokenValue = tokenValue; + if (tokenValue == null) { + throw new IllegalArgumentException("Token value must not be null."); + } + + int length = tokenValue.length(); + if (length == 0) { + throw new IllegalArgumentException("Token value must not be empty."); + } + + // TODO: 0 check + // TODO: Binary number + // TODO: Octal number + + if (NumberUtil.isHexNumber(tokenValue)) { + this.tokenValue = tokenValue; + } } @Override diff --git a/AlgebraicDataflowArchitectureModel/src/code/ast/NumberUtil.java b/AlgebraicDataflowArchitectureModel/src/code/ast/NumberUtil.java new file mode 100644 index 0000000..7d07105 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/code/ast/NumberUtil.java @@ -0,0 +1,64 @@ +package code.ast; + +/** + * Utility class that provides methods for number-related operations. + * + * @author s-yamagiwa + */ +public class NumberUtil { + /** + * Determines whether the given string is a valid hexadecimal number. + * A valid hexadecimal number starts with "0x" or "0X", followed by a + * combination of digits (0-9), letters (a-f, A-F), or underscores ('_'), + * with restrictions on the positioning of underscores. + * + * @param token The string to be evaluated as a hexadecimal number. + * @return {@code true} if the given string represents a valid hexadecimal number, + * {@code false} otherwise. + * @apiNote This method returns {@code true} if the given token is a valid hexadecimal number representaion in Java source code. + * So make sure that the specification of this method is determined by Java language specification. + */ + public static boolean isHexNumber(String token) { + if (token == null) { + return false; + } + + int length = token.length(); + if (length < 3) { + return false; + } + + Lexer lexer = new Lexer(token.toLowerCase()); + + if (lexer.peek() != '0' || lexer.peekNext() != 'x') { + return false; + } + + lexer.advance(); // 0 + lexer.advance(); // x + + // Checks for cases like 0x or 0x_ (Invalid underscore position) + if (lexer.peek() == '\0' || lexer.peek() == '_') { + return false; + } + + char prev = lexer.peek(); + while (lexer.peek() != '\0') { + char c = lexer.advance(); + boolean isValidFormat = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c == '_'); + if (!isValidFormat) { + return false; + } + + // Save the previous character + prev = c; + } + + // Checks for cases like 0xFFFFF_ (Invalid underscore position) + if (prev == '_') { + return false; + } + + return true; + } +}