WIP LexAn
This commit is contained in:
		
						commit
						d88951c225
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
out/
 | 
			
		||||
							
								
								
									
										8
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
# Default ignored files
 | 
			
		||||
/shelf/
 | 
			
		||||
/workspace.xml
 | 
			
		||||
# Editor-based HTTP Client requests
 | 
			
		||||
/httpRequests/
 | 
			
		||||
# Datasource local storage ignored files
 | 
			
		||||
/dataSources/
 | 
			
		||||
/dataSources.local.xml
 | 
			
		||||
							
								
								
									
										12
									
								
								.idea/inspectionProfiles/Project_Default.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.idea/inspectionProfiles/Project_Default.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
<component name="InspectionProjectProfileManager">
 | 
			
		||||
  <profile version="1.0">
 | 
			
		||||
    <option name="myName" value="Project Default" />
 | 
			
		||||
    <inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
 | 
			
		||||
      <option name="ignoredIdentifiers">
 | 
			
		||||
        <list>
 | 
			
		||||
          <option value="tests.smoke.test_absences_sliding.TestAbsencesSliding.*" />
 | 
			
		||||
        </list>
 | 
			
		||||
      </option>
 | 
			
		||||
    </inspection_tool>
 | 
			
		||||
  </profile>
 | 
			
		||||
</component>
 | 
			
		||||
							
								
								
									
										6
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project version="4">
 | 
			
		||||
  <component name="ProjectRootManager" version="2" languageLevel="JDK_23" default="true" project-jdk-name="homebrew-23" project-jdk-type="JavaSDK">
 | 
			
		||||
    <output url="file://$PROJECT_DIR$/out" />
 | 
			
		||||
  </component>
 | 
			
		||||
</project>
 | 
			
		||||
							
								
								
									
										8
									
								
								.idea/modules.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.idea/modules.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project version="4">
 | 
			
		||||
  <component name="ProjectModuleManager">
 | 
			
		||||
    <modules>
 | 
			
		||||
      <module fileurl="file://$PROJECT_DIR$/pns.iml" filepath="$PROJECT_DIR$/pns.iml" />
 | 
			
		||||
    </modules>
 | 
			
		||||
  </component>
 | 
			
		||||
</project>
 | 
			
		||||
							
								
								
									
										11
									
								
								pns.iml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								pns.iml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<module type="JAVA_MODULE" version="4">
 | 
			
		||||
  <component name="NewModuleRootManager" inherit-compiler-output="true">
 | 
			
		||||
    <exclude-output />
 | 
			
		||||
    <content url="file://$MODULE_DIR$">
 | 
			
		||||
      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
 | 
			
		||||
    </content>
 | 
			
		||||
    <orderEntry type="inheritedJdk" />
 | 
			
		||||
    <orderEntry type="sourceFolder" forTests="false" />
 | 
			
		||||
  </component>
 | 
			
		||||
</module>
 | 
			
		||||
							
								
								
									
										6
									
								
								prg/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								prg/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
JAVA		= java --enable-preview
 | 
			
		||||
 | 
			
		||||
.PHONY  : %
 | 
			
		||||
%       : %.pins25
 | 
			
		||||
	$(JAVA) -classpath ../bin pins25.phase.LexAn $<
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								prg/test.pins
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								prg/test.pins
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
'a'
 | 
			
		||||
'\n'
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/.DS_Store
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/.DS_Store
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										7
									
								
								src/module-info.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/module-info.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Implementacija programskega jezika PINS'25.
 | 
			
		||||
 * 
 | 
			
		||||
 * @author bostjan.slivnik@fri.uni-lj.si
 | 
			
		||||
 */
 | 
			
		||||
module pins25 {
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/pins25/.DS_Store
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/pins25/.DS_Store
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										156
									
								
								src/pins25/common/Report.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								src/pins25/common/Report.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,156 @@
 | 
			
		||||
package pins25.common;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Izpis obvestil, opozoril in napak.
 | 
			
		||||
 */
 | 
			
		||||
public class Report {
 | 
			
		||||
 | 
			
		||||
	@SuppressWarnings({ "doclint:missing" })
 | 
			
		||||
	private Report() {
 | 
			
		||||
		throw new InternalError();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Opis lokacije v izvorni datoteki.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param begLine   Zacetna vrstica.
 | 
			
		||||
	 * @param begColumn Zacetni stolpec.
 | 
			
		||||
	 * @param endLine   Koncna vrstica.
 | 
			
		||||
	 * @param endColumn Koncni stolpec.
 | 
			
		||||
	 */
 | 
			
		||||
	public record Location(int begLine, int begColumn, int endLine, int endColumn) implements Locatable {
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari novo lokacijo, ki opisuje en sam znak izvorne datoteke.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param line   Vrstica znaka.
 | 
			
		||||
		 * @param column Stolpec znaka.
 | 
			
		||||
		 */
 | 
			
		||||
		public Location(int line, int column) {
 | 
			
		||||
			this(line, column, line, column);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari novo lokacijo, ki se razteza od ene do druge lokacije.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param beg Prva lokacija.
 | 
			
		||||
		 * @param end Druga lokacija.
 | 
			
		||||
		 */
 | 
			
		||||
		public Location(Locatable beg, Locatable end) {
 | 
			
		||||
			this(beg.location().begLine, beg.location().begColumn, end.location().endLine, end.location().endColumn);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String toString() {
 | 
			
		||||
			return "[" + (begLine + "." + begColumn) + ":" + (endLine + "." + endColumn) + "]";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public Location location() {
 | 
			
		||||
			return this;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Vmesnik, ki naj ga implementirajo razredi, katerih objekti predstavljajo dele
 | 
			
		||||
	 * izvorne datoteke.
 | 
			
		||||
	 */
 | 
			
		||||
	public interface Locatable {
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Vrne lokacijo dela izvorne datoteke, ki ga opisuje objekt.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @return Opis lokacije v izvorni datoteki.
 | 
			
		||||
		 */
 | 
			
		||||
		public Location location();
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Izpis splosnega obvestila.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param message Obvestilo.
 | 
			
		||||
	 */
 | 
			
		||||
	public static void info(final String message) {
 | 
			
		||||
		System.out.println(":-) " + message);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Izpis obvestila, ki je vezano na del izvorne datoteke.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param location Opis lokacije v izvorni datoteki.
 | 
			
		||||
	 * @param message  Obvestilo.
 | 
			
		||||
	 */
 | 
			
		||||
	public static void info(final Locatable location, final String message) {
 | 
			
		||||
		System.out.println(":-) " + location + " " + message);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Izpis splosnega opozorila.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param message Opozorilo.
 | 
			
		||||
	 */
 | 
			
		||||
	public static void warning(final String message) {
 | 
			
		||||
		System.out.println(":-o " + message);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Izpis opozorila, ki je vezano na del izvorne datoteke.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param location Opis lokacije v izvorni datoteki.
 | 
			
		||||
	 * @param message  Opozorilo.
 | 
			
		||||
	 */
 | 
			
		||||
	public static void warning(final Locatable location, final String message) {
 | 
			
		||||
		System.out.println(":-o " + location + " " + message);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Napaka.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * Objekt tega razreda se vrze v primeru, ko je program odkril napako v izvorni
 | 
			
		||||
	 * datoteki, zaradi katere ni vec mozno nadaljevati z izvajanjem.
 | 
			
		||||
	 */
 | 
			
		||||
	@SuppressWarnings("serial")
 | 
			
		||||
	public static class Error extends java.lang.Error {
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari novo napako.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param message Opis napake.
 | 
			
		||||
		 */
 | 
			
		||||
		public Error(final String message) {
 | 
			
		||||
			super(":-( " + message);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari novo napako, ki je veznana na del izvorne datoteke.
 | 
			
		||||
		 * 
 | 
			
		||||
		 * @param location Opis lokacije v izvorni datoteki.
 | 
			
		||||
		 * @param message  Opis napake.
 | 
			
		||||
		 */
 | 
			
		||||
		public Error(final Locatable location, final String message) {
 | 
			
		||||
			super(":-( " + "[" + location.location() + "] " + message);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Notranja napaka.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * Objekt tega razreda se vze v primeru, ko program zazna notranjo napako.
 | 
			
		||||
	 */
 | 
			
		||||
	@SuppressWarnings("serial")
 | 
			
		||||
	public static class InternalError extends Error {
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Ustvari novo notranjo napako.
 | 
			
		||||
		 */
 | 
			
		||||
		public InternalError() {
 | 
			
		||||
			super("Internal error.");
 | 
			
		||||
			this.printStackTrace();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										98
									
								
								src/pins25/common/Token.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/pins25/common/Token.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,98 @@
 | 
			
		||||
package pins25.common;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Leksikalni simbol.
 | 
			
		||||
 * 
 | 
			
		||||
 * @param location Lokacija simbola v izvornem programu.
 | 
			
		||||
 * @param symbol   Vrsta simbola.
 | 
			
		||||
 * @param lexeme   Znakovna predstavitev simbola.
 | 
			
		||||
 */
 | 
			
		||||
public record Token(Report.Location location, Symbol symbol, String lexeme) implements Report.Locatable {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Vrste leksikalnih simbolov.
 | 
			
		||||
	 */
 | 
			
		||||
	public enum Symbol {
 | 
			
		||||
		/** Konec datoteke. */
 | 
			
		||||
		EOF,
 | 
			
		||||
		/** Stevilo. */
 | 
			
		||||
		INTCONST,
 | 
			
		||||
		/** Znak. */
 | 
			
		||||
		CHARCONST,
 | 
			
		||||
		/** Niz znakov. */
 | 
			
		||||
		STRINGCONST,
 | 
			
		||||
		/** Ime. */
 | 
			
		||||
		IDENTIFIER,
 | 
			
		||||
		/** Kljucna beseda {@code fun}. */
 | 
			
		||||
		FUN,
 | 
			
		||||
		/** Kljucna beseda {@code var}. */
 | 
			
		||||
		VAR,
 | 
			
		||||
		/** Kljucna beseda {@code if}. */
 | 
			
		||||
		IF,
 | 
			
		||||
		/** Kljucna beseda {@code then}. */
 | 
			
		||||
		THEN,
 | 
			
		||||
		/** Kljucna beseda {@code else}. */
 | 
			
		||||
		ELSE,
 | 
			
		||||
		/** Kljucna beseda {@code while}. */
 | 
			
		||||
		WHILE,
 | 
			
		||||
		/** Kljucna beseda {@code do}. */
 | 
			
		||||
		DO,
 | 
			
		||||
		/** Kljucna beseda {@code let}. */
 | 
			
		||||
		LET,
 | 
			
		||||
		/** Kljucna beseda {@code in}. */
 | 
			
		||||
		IN,
 | 
			
		||||
		/** Kljucna beseda {@code end}. */
 | 
			
		||||
		END,
 | 
			
		||||
		/** Simbol {@code =}. */
 | 
			
		||||
		ASSIGN,
 | 
			
		||||
		/** Simbol {@code ,}. */
 | 
			
		||||
		COMMA,
 | 
			
		||||
		/** Simbol {@code &&}. */
 | 
			
		||||
		AND,
 | 
			
		||||
		/** Simbol {@code ||}. */
 | 
			
		||||
		OR,
 | 
			
		||||
		/** Simbol {@code !}. */
 | 
			
		||||
		NOT,
 | 
			
		||||
		/** Simbol {@code ==}. */
 | 
			
		||||
		EQU,
 | 
			
		||||
		/** Simbol {@code !=}. */
 | 
			
		||||
		NEQ,
 | 
			
		||||
		/** Simbol {@code >}. */
 | 
			
		||||
		GTH,
 | 
			
		||||
		/** Simbol {@code <}. */
 | 
			
		||||
		LTH,
 | 
			
		||||
		/** Simbol {@code >=}. */
 | 
			
		||||
		GEQ,
 | 
			
		||||
		/** Simbol {@code <=}. */
 | 
			
		||||
		LEQ,
 | 
			
		||||
		/** Simbol {@code +}. */
 | 
			
		||||
		ADD,
 | 
			
		||||
		/** Simbol {@code -}. */
 | 
			
		||||
		SUB,
 | 
			
		||||
		/** Simbol {@code *}. */
 | 
			
		||||
		MUL,
 | 
			
		||||
		/** Simbol {@code /}. */
 | 
			
		||||
		DIV,
 | 
			
		||||
		/** Simbol {@code %}. */
 | 
			
		||||
		MOD,
 | 
			
		||||
		/** Simbol {@code ^}. */
 | 
			
		||||
		PTR,
 | 
			
		||||
		/** Simbol {@code (}. */
 | 
			
		||||
		LPAREN,
 | 
			
		||||
		/** Simbol {@code )}. */
 | 
			
		||||
		RPAREN,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public String toString() {
 | 
			
		||||
		String lexeme = switch (symbol) {
 | 
			
		||||
		case INTCONST -> "(" + this.lexeme + ")";
 | 
			
		||||
		case CHARCONST -> "(" + this.lexeme + ")";
 | 
			
		||||
		case STRINGCONST -> "(" + this.lexeme + ")";
 | 
			
		||||
		case IDENTIFIER -> "(" + this.lexeme + ")";
 | 
			
		||||
		default -> "";
 | 
			
		||||
		};
 | 
			
		||||
		return location + " " + symbol + lexeme;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/pins25/common/package-info.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/pins25/common/package-info.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Koda, ki je skupna vecim fazam prevajalnika.
 | 
			
		||||
 * 
 | 
			
		||||
 * @author bostjan.slivnik@fri.uni-lj.si
 | 
			
		||||
 */
 | 
			
		||||
package pins25.common;
 | 
			
		||||
							
								
								
									
										318
									
								
								src/pins25/phase/LexAn.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										318
									
								
								src/pins25/phase/LexAn.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,318 @@
 | 
			
		||||
package pins25.phase;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
import pins25.common.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Leksikalni analizator.
 | 
			
		||||
 */
 | 
			
		||||
public class LexAn implements AutoCloseable {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Izvorna datoteka.
 | 
			
		||||
     */
 | 
			
		||||
    private final Reader srcFile;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Ustvari nov leksikalni analizator.
 | 
			
		||||
     *
 | 
			
		||||
     * @param srcFileName Ime izvorne datoteke.
 | 
			
		||||
     */
 | 
			
		||||
    public LexAn(final String srcFileName) {
 | 
			
		||||
        try {
 | 
			
		||||
            srcFile = new BufferedReader(new InputStreamReader(new FileInputStream(new File(srcFileName))));
 | 
			
		||||
            nextChar(); // Pripravi prvi znak izvorne datoteke (glej {@link nextChar}).
 | 
			
		||||
        } catch (FileNotFoundException __) {
 | 
			
		||||
            throw new Report.Error("Source file '" + srcFileName + "' not found.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void close() {
 | 
			
		||||
        try {
 | 
			
		||||
            srcFile.close();
 | 
			
		||||
        } catch (IOException __) {
 | 
			
		||||
            throw new Report.Error("Cannot close source file.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Trenutni znak izvorne datoteke (glej {@link nextChar}).
 | 
			
		||||
     */
 | 
			
		||||
    private int buffChar = -2;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Vrstica trenutnega znaka izvorne datoteke (glej {@link nextChar}).
 | 
			
		||||
     */
 | 
			
		||||
    private int buffCharLine = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Stolpec trenutnega znaka izvorne datoteke (glej {@link nextChar}).
 | 
			
		||||
     */
 | 
			
		||||
    private int buffCharColumn = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Prebere naslednji znak izvorne datoteke.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Izvorno datoteko beremo znak po znak. Trenutni znak izvorne datoteke je
 | 
			
		||||
     * shranjen v spremenljivki {@link buffChar}, vrstica in stolpec trenutnega
 | 
			
		||||
     * znaka izvorne datoteke sta shranjena v spremenljivkah {@link buffCharLine} in
 | 
			
		||||
     * {@link buffCharColumn}.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Zacetne vrednosti {@link buffChar}, {@link buffCharLine} in
 | 
			
		||||
     * {@link buffCharColumn} so {@code '\n'}, {@code 0} in {@code 0}: branje prvega
 | 
			
		||||
     * znaka izvorne datoteke bo na osnovi vrednosti {@code '\n'} spremenljivke
 | 
			
		||||
     * {@link buffChar} prvemu znaku izvorne datoteke priredilo vrstico 1 in stolpec
 | 
			
		||||
     * 1.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Pri branju izvorne datoteke se predpostavlja, da je v spremenljivki
 | 
			
		||||
     * {@link buffChar} ves "cas veljaven znak. Zunaj metode {@link nextChar} so vse
 | 
			
		||||
     * spremenljivke {@link buffChar}, {@link buffCharLine} in
 | 
			
		||||
     * {@link buffCharColumn} namenjene le branju.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Vrednost {@code -1} v spremenljivki {@link buffChar} pomeni konec datoteke
 | 
			
		||||
     * (vrednosti spremenljivk {@link buffCharLine} in {@link buffCharColumn} pa
 | 
			
		||||
     * nista ve"c veljavni).
 | 
			
		||||
     */
 | 
			
		||||
    private void nextChar() {
 | 
			
		||||
        try {
 | 
			
		||||
            switch (buffChar) {
 | 
			
		||||
                case -2: // Noben znak "se ni bil prebran.
 | 
			
		||||
                    buffChar = srcFile.read();
 | 
			
		||||
                    buffCharLine = buffChar == -1 ? 0 : 1;
 | 
			
		||||
                    buffCharColumn = buffChar == -1 ? 0 : 1;
 | 
			
		||||
                    return;
 | 
			
		||||
                case -1: // Konec datoteke je bil ze viden.
 | 
			
		||||
                    return;
 | 
			
		||||
                case '\n': // Prejsnji znak je koncal vrstico, zacne se nova vrstica.
 | 
			
		||||
                    buffChar = srcFile.read();
 | 
			
		||||
                    buffCharLine = buffChar == -1 ? buffCharLine : buffCharLine + 1;
 | 
			
		||||
                    buffCharColumn = buffChar == -1 ? buffCharColumn : 1;
 | 
			
		||||
                    return;
 | 
			
		||||
                case '\t': // Prejsnji znak je tabulator, ta znak je morda potisnjen v desno.
 | 
			
		||||
                    buffChar = srcFile.read();
 | 
			
		||||
                    while (buffCharColumn % 8 != 0)
 | 
			
		||||
                        buffCharColumn += 1;
 | 
			
		||||
                    buffCharColumn += 1;
 | 
			
		||||
                    return;
 | 
			
		||||
                default: // Prejsnji znak je brez posebnosti.
 | 
			
		||||
                    buffChar = srcFile.read();
 | 
			
		||||
                    buffCharColumn += 1;
 | 
			
		||||
            }
 | 
			
		||||
        } catch (IOException __) {
 | 
			
		||||
            throw new Report.Error("Cannot read source file.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Report.Location currentLocation() {
 | 
			
		||||
        return new Report.Location(buffCharLine, buffCharColumn);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Trenutni leksikalni simbol.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * "Ce vrednost spremenljivke {@code buffToken} ni {@code null}, je simbol "ze
 | 
			
		||||
     * prebran iz vhodne datoteke, ni pa "se predan naprej sintaksnemu analizatorju.
 | 
			
		||||
     * Ta simbol je dostopen z metodama {@link peekToken} in {@link takeToken}.
 | 
			
		||||
     */
 | 
			
		||||
    private Token buffToken = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Prebere naslednji leksikalni simbol, ki je nato dostopen preko metod
 | 
			
		||||
     * {@link peekToken} in {@link takeToken}.
 | 
			
		||||
     */
 | 
			
		||||
    private void nextToken() {
 | 
			
		||||
        while (buffChar == '\n') {
 | 
			
		||||
            nextChar();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        switch (buffChar) {
 | 
			
		||||
            case -1: // EOF
 | 
			
		||||
                buffToken = new Token(currentLocation(), Token.Symbol.EOF, null);
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            case '\'':
 | 
			
		||||
                charConst();
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            case '"':
 | 
			
		||||
                stringConst();
 | 
			
		||||
                return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (buffChar >= '0' && buffChar <= '9') {
 | 
			
		||||
            intConst();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        throw new Report.Error(currentLocation(), "Unrecognized character '" + (char) buffChar + "'.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean isDigit() {
 | 
			
		||||
        return buffChar >= '0' && buffChar <= '9';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean isChar() {
 | 
			
		||||
        return buffChar >= ' ' && buffChar <= '~';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean isHex() {
 | 
			
		||||
        return buffChar >= '0' && buffChar <= '9' || buffChar >= 'a' && buffChar <= 'f';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void intConst() {
 | 
			
		||||
        Report.Location startLocation = currentLocation();
 | 
			
		||||
        Report.Location endLocation = currentLocation();
 | 
			
		||||
        StringBuilder lexeme = new StringBuilder();
 | 
			
		||||
 | 
			
		||||
        if (buffChar == '0') {
 | 
			
		||||
            lexeme.append((char) buffChar);
 | 
			
		||||
            nextChar();
 | 
			
		||||
            if (isDigit()) {
 | 
			
		||||
                throw new Report.Error(startLocation, "Leading zero is not allowed.");
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            while (isDigit()) {
 | 
			
		||||
                lexeme.append((char) buffChar);
 | 
			
		||||
                endLocation = currentLocation();
 | 
			
		||||
                nextChar();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        buffToken = new Token(
 | 
			
		||||
                new Report.Location(startLocation, endLocation),
 | 
			
		||||
                Token.Symbol.INTCONST,
 | 
			
		||||
                lexeme.toString()
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void charConst() {
 | 
			
		||||
        Report.Location startLocation = currentLocation();
 | 
			
		||||
        StringBuilder lexeme = new StringBuilder();
 | 
			
		||||
 | 
			
		||||
        lexeme.append((char) buffChar);
 | 
			
		||||
        nextChar();
 | 
			
		||||
 | 
			
		||||
        if (!isChar()) {
 | 
			
		||||
            throw new Report.Error(startLocation, "Invalid character '" + (char) buffChar + "'.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        lexeme.append((char) buffChar);
 | 
			
		||||
        if (buffChar == '\\') {
 | 
			
		||||
            nextChar();
 | 
			
		||||
            lexeme.append((char) buffChar);
 | 
			
		||||
            if (buffChar == 'n' || buffChar == '\\' || buffChar == '\'') {
 | 
			
		||||
 | 
			
		||||
            } else if (isHex()) {
 | 
			
		||||
                nextChar();
 | 
			
		||||
                lexeme.append((char) buffChar);
 | 
			
		||||
                if (!isHex()) {
 | 
			
		||||
                    throw new Report.Error(currentLocation(), "Invalid ascii code '" + (char) buffChar + "'.");
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                throw new Report.Error(currentLocation(), "Invalid escaped character '" + (char) buffChar + "'.");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        nextChar();
 | 
			
		||||
        if (buffChar != '\'') {
 | 
			
		||||
            throw new Report.Error(new Report.Location(startLocation, currentLocation()), "Unterminated character.");
 | 
			
		||||
        }
 | 
			
		||||
        lexeme.append((char) buffChar);
 | 
			
		||||
 | 
			
		||||
        buffToken = new Token(
 | 
			
		||||
                new Report.Location(startLocation, currentLocation()),
 | 
			
		||||
                Token.Symbol.CHARCONST,
 | 
			
		||||
                lexeme.toString()
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        nextChar();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void stringConst() {
 | 
			
		||||
        Report.Location startLocation = currentLocation();
 | 
			
		||||
        StringBuilder lexeme = new StringBuilder();
 | 
			
		||||
 | 
			
		||||
        lexeme.append((char) buffChar);
 | 
			
		||||
        nextChar();
 | 
			
		||||
 | 
			
		||||
        while (buffChar != '"') {
 | 
			
		||||
            if (!isChar()) {
 | 
			
		||||
                throw new Report.Error(currentLocation(), "Invalid character '" + (char) buffChar + "'.");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            lexeme.append((char) buffChar);
 | 
			
		||||
            nextChar();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        lexeme.append((char) buffChar);
 | 
			
		||||
        buffToken = new Token(
 | 
			
		||||
                new Report.Location(startLocation, currentLocation()),
 | 
			
		||||
                Token.Symbol.STRINGCONST,
 | 
			
		||||
                lexeme.toString()
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        nextChar();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Vrne trenutni leksikalni simbol, ki ostane v lastnistvu leksikalnega
 | 
			
		||||
     * analizatorja.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Leksikalni simbol.
 | 
			
		||||
     */
 | 
			
		||||
    public Token peekToken() {
 | 
			
		||||
        if (buffToken == null)
 | 
			
		||||
            nextToken();
 | 
			
		||||
        return buffToken;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Vrne trenutni leksikalni simbol, ki preide v lastnistvo klicoce kode.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Leksikalni simbol.
 | 
			
		||||
     */
 | 
			
		||||
    public Token takeToken() {
 | 
			
		||||
        if (buffToken == null)
 | 
			
		||||
            nextToken();
 | 
			
		||||
        final Token thisToken = buffToken;
 | 
			
		||||
        buffToken = null;
 | 
			
		||||
        return thisToken;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
// --- ZAGON ---
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Zagon leksikalnega analizatorja kot samostojnega programa.
 | 
			
		||||
     *
 | 
			
		||||
     * @param cmdLineArgs Argumenti v ukazni vrstici.
 | 
			
		||||
     */
 | 
			
		||||
    public static void main(final String[] cmdLineArgs) {
 | 
			
		||||
        System.out.println("This is PINS'25 compiler (lexical analysis):");
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            if (cmdLineArgs.length == 0)
 | 
			
		||||
                throw new Report.Error("No source file specified in the command line.");
 | 
			
		||||
            if (cmdLineArgs.length > 1)
 | 
			
		||||
                Report.warning("Unused arguments in the command line.");
 | 
			
		||||
 | 
			
		||||
            try (LexAn lexAn = new LexAn(cmdLineArgs[0])) {
 | 
			
		||||
                while (lexAn.peekToken().symbol() != Token.Symbol.EOF)
 | 
			
		||||
                    System.out.println(lexAn.takeToken());
 | 
			
		||||
                System.out.println(lexAn.takeToken());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Upajmo, da kdaj pridemo to te tocke.
 | 
			
		||||
            // A zavedajmo se sledecega:
 | 
			
		||||
            // 1. Prevod je zaradi napak v programu lahko napacen :-o
 | 
			
		||||
            // 2. Izvorni program se zdalec ni tisto, kar je programer hotel, da bi bil ;-)
 | 
			
		||||
            Report.info("Done.");
 | 
			
		||||
        } catch (Report.Error error) {
 | 
			
		||||
            // Izpis opisa napake.
 | 
			
		||||
            System.err.println(error.getMessage());
 | 
			
		||||
            System.exit(1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/pins25/phase/package-info.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/pins25/phase/package-info.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Posamezne faze prevajalnika.
 | 
			
		||||
 * 
 | 
			
		||||
 * @author bostjan.slivnik@fri.uni-lj.si
 | 
			
		||||
 */
 | 
			
		||||
package pins25.phase;
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user