使用 Java 从文件中读取算术表达式中的自然数
Reading a natural number in a arithmetic expression from a file with Java
我正在 java 中构建一个词法分析器。这就是我现在拥有的:
import java.io.*;
enum TokenType{ NUM,SOMA, MULT,APar,FPar, EOF}
class Token{
char lexema;
TokenType token;
Token (char l, TokenType t)
{ lexema=l;token = t;}
}
class AnaliseLexica {
BufferedReader arquivo;
AnaliseLexica(String a) throws Exception
{
this.arquivo = new BufferedReader(new FileReader(a));
}
Token getNextToken() throws Exception
{
Token token;
int eof = -1;
char currchar;
int currchar1;
do{
currchar1 = arquivo.read();
currchar = (char) currchar1;
} while (currchar == '\n' || currchar == ' ' || currchar =='\t' || currchar == '\r');
if(currchar1 != eof && currchar1 !=10)
{
if (currchar >= '0' && currchar <= '9')
return (new Token (currchar, TokenType.NUM));
else
switch (currchar){
case '(':
return (new Token (currchar,TokenType.APar));
case ')':
return (new Token (currchar,TokenType.FPar));
case '+':
return (new Token (currchar,TokenType.SOMA));
case '*':
return (new Token (currchar,TokenType.MULT));
default: throw (new Exception("Caractere inválido: " + ((int) currchar)));
}
}
arquivo.close();
return (new Token(currchar,TokenType.EOF));
}
使用这段代码,我可以使用这部分代码读取从“0”到“9”的数字以及“*”、“+”等运算符:
do{
currchar1 = arquivo.read();
currchar = (char) currchar1;
} while (currchar == '\n' || currchar == ' ' || currchar =='\t' || currchar == '\r');
如何从文件中读取自然数并继续读取算术运算符?
由于空格是标记的有效分隔符,因此您可以简化代码。默认情况下,扫描器 class 将用空格分隔读取的值。你只需要一一阅读。当扫描器没有更多数据要读取时,我们将其关闭并 return 一个 EOF 令牌。
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class AnalisadorLexico {
public enum TokenType {
NUM,
SOMA,
MULT,
APar,
FPar,
EOF
}
public class Token {
String lexema;
TokenType token;
Token( String l, TokenType t ) {
lexema = l;
token = t;
}
Token( char l, TokenType t ) {
lexema = String.valueOf( l );
token = t;
}
@Override
public String toString() {
return lexema + " (" + token + ")";
}
}
private Scanner fileReader;
private boolean scannerClosed;
public AnalisadorLexico( String filePath ) throws IOException {
fileReader = new Scanner( new FileReader( filePath ) );
}
public Token getNextToken() throws IOException {
if ( !scannerClosed && fileReader.hasNext() ) {
String currentData = fileReader.next();
try {
Integer.parseInt( currentData );
return new Token( currentData, TokenType.NUM );
} catch ( NumberFormatException exc ) {
}
switch ( currentData ) {
case "(":
return new Token( currentData,TokenType.APar );
case ")":
return new Token( currentData,TokenType.FPar );
case "+":
return new Token( currentData,TokenType.SOMA );
case "*":
return new Token( currentData,TokenType.MULT );
}
} else {
scannerClosed = true;
fileReader.close();
return new Token( "", TokenType.EOF );
}
return null;
}
public static void main( String[] args ) throws IOException {
AnalisadorLexico al = new AnalisadorLexico( "testAL.txt" );
Token t = null;
while ( ( t = al.getNextToken() ).token != TokenType.EOF ) {
System.out.println( t );
}
System.out.println( al.getNextToken() );
System.out.println( al.getNextToken() );
System.out.println( al.getNextToken() );
System.out.println( al.getNextToken() );
}
}
如果您不能使用 class 扫描仪,您可以继续使用 BufferedReader,标记其数据:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class AnalisadorLexico2 {
public enum TokenType {
NUM,
SOMA,
MULT,
APar,
FPar,
EOF
}
public class Token {
String lexema;
TokenType token;
Token( String l, TokenType t ) {
lexema = l;
token = t;
}
Token( char l, TokenType t ) {
lexema = String.valueOf( l );
token = t;
}
@Override
public String toString() {
return lexema + " (" + token + ")";
}
}
private BufferedReader fileReader;
private boolean fileReaderClosed;
public AnalisadorLexico2( String filePath ) throws IOException {
fileReader = new BufferedReader( new FileReader( filePath ) );
}
public Token getNextToken() throws IOException {
String currentData = nextBufferedReaderToken();
if ( currentData != null ) {
try {
Integer.parseInt( currentData );
return new Token( currentData, TokenType.NUM );
} catch ( NumberFormatException exc ) {
}
switch ( currentData ) {
case "(":
return new Token( currentData,TokenType.APar );
case ")":
return new Token( currentData,TokenType.FPar );
case "+":
return new Token( currentData,TokenType.SOMA );
case "*":
return new Token( currentData,TokenType.MULT );
}
} else {
if ( !fileReaderClosed ) {
fileReaderClosed = true;
fileReader.close();
}
return new Token( "", TokenType.EOF );
}
return null;
}
public String nextBufferedReaderToken() throws IOException {
boolean started = false;
String data = null;
while ( !fileReaderClosed ) {
int d = fileReader.read();
char c = (char) d;
if ( d != -1 ) {
if ( c == '\n' || c == ' ' || c == '\t' || c == '\r' ) {
if ( !started ) {
// discard...
} else {
break;
}
} else {
if ( !started ) {
data = "";
started = true;
}
data += c;
}
} else {
break;
}
}
return data;
}
public static void main( String[] args ) throws IOException {
AnalisadorLexico2 al = new AnalisadorLexico2( "testAL.txt" );
Token t = null;
while ( ( t = al.getNextToken() ).token != TokenType.EOF ) {
System.out.println( t );
}
System.out.println( al.getNextToken() );
System.out.println( al.getNextToken() );
System.out.println( al.getNextToken() );
System.out.println( al.getNextToken() );
}
}
我的 testAL.txt
文件内容是:
1234 + 5 * 65 + ( 44 * 55555 ) * 444 + ( 2354 * ( 34 + 44 ) )
1234 + 5 * 65 + ( 44 * 55555 ) * 444 + ( 2354 * ( 34 + 44 ) )
1234 + 5 * 65 + ( 44 * 55555 ) * 444 + ( 2354 * ( 34 + 44 ) )
1234 + 5 * 65 + ( 44 * 55555 ) * 444 + ( 2354 * ( 34 + 44 ) )
我正在 java 中构建一个词法分析器。这就是我现在拥有的:
import java.io.*;
enum TokenType{ NUM,SOMA, MULT,APar,FPar, EOF}
class Token{
char lexema;
TokenType token;
Token (char l, TokenType t)
{ lexema=l;token = t;}
}
class AnaliseLexica {
BufferedReader arquivo;
AnaliseLexica(String a) throws Exception
{
this.arquivo = new BufferedReader(new FileReader(a));
}
Token getNextToken() throws Exception
{
Token token;
int eof = -1;
char currchar;
int currchar1;
do{
currchar1 = arquivo.read();
currchar = (char) currchar1;
} while (currchar == '\n' || currchar == ' ' || currchar =='\t' || currchar == '\r');
if(currchar1 != eof && currchar1 !=10)
{
if (currchar >= '0' && currchar <= '9')
return (new Token (currchar, TokenType.NUM));
else
switch (currchar){
case '(':
return (new Token (currchar,TokenType.APar));
case ')':
return (new Token (currchar,TokenType.FPar));
case '+':
return (new Token (currchar,TokenType.SOMA));
case '*':
return (new Token (currchar,TokenType.MULT));
default: throw (new Exception("Caractere inválido: " + ((int) currchar)));
}
}
arquivo.close();
return (new Token(currchar,TokenType.EOF));
}
使用这段代码,我可以使用这部分代码读取从“0”到“9”的数字以及“*”、“+”等运算符:
do{
currchar1 = arquivo.read();
currchar = (char) currchar1;
} while (currchar == '\n' || currchar == ' ' || currchar =='\t' || currchar == '\r');
如何从文件中读取自然数并继续读取算术运算符?
由于空格是标记的有效分隔符,因此您可以简化代码。默认情况下,扫描器 class 将用空格分隔读取的值。你只需要一一阅读。当扫描器没有更多数据要读取时,我们将其关闭并 return 一个 EOF 令牌。
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class AnalisadorLexico {
public enum TokenType {
NUM,
SOMA,
MULT,
APar,
FPar,
EOF
}
public class Token {
String lexema;
TokenType token;
Token( String l, TokenType t ) {
lexema = l;
token = t;
}
Token( char l, TokenType t ) {
lexema = String.valueOf( l );
token = t;
}
@Override
public String toString() {
return lexema + " (" + token + ")";
}
}
private Scanner fileReader;
private boolean scannerClosed;
public AnalisadorLexico( String filePath ) throws IOException {
fileReader = new Scanner( new FileReader( filePath ) );
}
public Token getNextToken() throws IOException {
if ( !scannerClosed && fileReader.hasNext() ) {
String currentData = fileReader.next();
try {
Integer.parseInt( currentData );
return new Token( currentData, TokenType.NUM );
} catch ( NumberFormatException exc ) {
}
switch ( currentData ) {
case "(":
return new Token( currentData,TokenType.APar );
case ")":
return new Token( currentData,TokenType.FPar );
case "+":
return new Token( currentData,TokenType.SOMA );
case "*":
return new Token( currentData,TokenType.MULT );
}
} else {
scannerClosed = true;
fileReader.close();
return new Token( "", TokenType.EOF );
}
return null;
}
public static void main( String[] args ) throws IOException {
AnalisadorLexico al = new AnalisadorLexico( "testAL.txt" );
Token t = null;
while ( ( t = al.getNextToken() ).token != TokenType.EOF ) {
System.out.println( t );
}
System.out.println( al.getNextToken() );
System.out.println( al.getNextToken() );
System.out.println( al.getNextToken() );
System.out.println( al.getNextToken() );
}
}
如果您不能使用 class 扫描仪,您可以继续使用 BufferedReader,标记其数据:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class AnalisadorLexico2 {
public enum TokenType {
NUM,
SOMA,
MULT,
APar,
FPar,
EOF
}
public class Token {
String lexema;
TokenType token;
Token( String l, TokenType t ) {
lexema = l;
token = t;
}
Token( char l, TokenType t ) {
lexema = String.valueOf( l );
token = t;
}
@Override
public String toString() {
return lexema + " (" + token + ")";
}
}
private BufferedReader fileReader;
private boolean fileReaderClosed;
public AnalisadorLexico2( String filePath ) throws IOException {
fileReader = new BufferedReader( new FileReader( filePath ) );
}
public Token getNextToken() throws IOException {
String currentData = nextBufferedReaderToken();
if ( currentData != null ) {
try {
Integer.parseInt( currentData );
return new Token( currentData, TokenType.NUM );
} catch ( NumberFormatException exc ) {
}
switch ( currentData ) {
case "(":
return new Token( currentData,TokenType.APar );
case ")":
return new Token( currentData,TokenType.FPar );
case "+":
return new Token( currentData,TokenType.SOMA );
case "*":
return new Token( currentData,TokenType.MULT );
}
} else {
if ( !fileReaderClosed ) {
fileReaderClosed = true;
fileReader.close();
}
return new Token( "", TokenType.EOF );
}
return null;
}
public String nextBufferedReaderToken() throws IOException {
boolean started = false;
String data = null;
while ( !fileReaderClosed ) {
int d = fileReader.read();
char c = (char) d;
if ( d != -1 ) {
if ( c == '\n' || c == ' ' || c == '\t' || c == '\r' ) {
if ( !started ) {
// discard...
} else {
break;
}
} else {
if ( !started ) {
data = "";
started = true;
}
data += c;
}
} else {
break;
}
}
return data;
}
public static void main( String[] args ) throws IOException {
AnalisadorLexico2 al = new AnalisadorLexico2( "testAL.txt" );
Token t = null;
while ( ( t = al.getNextToken() ).token != TokenType.EOF ) {
System.out.println( t );
}
System.out.println( al.getNextToken() );
System.out.println( al.getNextToken() );
System.out.println( al.getNextToken() );
System.out.println( al.getNextToken() );
}
}
我的 testAL.txt
文件内容是:
1234 + 5 * 65 + ( 44 * 55555 ) * 444 + ( 2354 * ( 34 + 44 ) )
1234 + 5 * 65 + ( 44 * 55555 ) * 444 + ( 2354 * ( 34 + 44 ) )
1234 + 5 * 65 + ( 44 * 55555 ) * 444 + ( 2354 * ( 34 + 44 ) )
1234 + 5 * 65 + ( 44 * 55555 ) * 444 + ( 2354 * ( 34 + 44 ) )