Black Friday Black Friday
Black Friday výprodej! Až 80 % extra bodů zdarma! Více informací zde
Avatar
Elix Novel
Člen
Avatar
Elix Novel:13. října 17:11

Ahoj, píšu program, který analyzuje slova z textu a řadí je do jednotlivých sekcí. Takže když zjistí, že je to klíčové slovo napíše: keyword "jméne klíčového slova", když zjistí, že je to oddělovač, identifikátor cokoliv - stejný princip.
Ale chtěl bych, aby program dokázal zjistit, že toto číslo je v hexadeximální soustavě a vypsal: number_hex "požadové číslo" a nejlépe rovnou v decimální soustavě.

Zkusil jsem: Načítám soubor přes StringBuilder čtu řádek po řádku a pomocí enumerátorů zjišťuji kam dané slovo patří.

KEYWORD_RETURN("return"),
SEPARATOR_ROVNITKO("="),
NUMBER_DEC("\\d+(\\.\\d+)?"),
NUMBER_HEX("0x"),

Potom ho vypisuji do konzole. Vše mi funguje jen to nedokáže identifikovat, že číslo je v hexadecimální soustavě.

Chci docílit: Výsledek by měl být takový, že program přes prefix "0x" v enumerátoru zjistí, že je číslo v hexadecimální soustavě a na obrazovku vypíše: number_hex"číslo převedené do dec".

 
Odpovědět 13. října 17:11
Avatar
Jirka
Člen
Avatar
Odpovídá na Elix Novel
Jirka:13. října 17:27

Ahoj,
co zkusit regulární výraz, jako "\b[0-9A-F]+\b".

Nahoru Odpovědět  +1 13. října 17:27
Kdo nic nedělá, nic nezkazí.
Avatar
Samuel Kodytek
Šéfredaktor
Avatar
Samuel Kodytek:13. října 17:28

Ahoj,

Nevím jestli jsem pochopil přesně čeho chceš docílit, ale pokud chceš zjistit jestli řádek obsahuje 0x a k tomu nějaké číslo a to následně převést z hexadecimální soustavy do decimální, použil bych regex . Pokud ve tvém souboru, víš že všechny tvé hexadecimální čísla budou začínat na 0x tak tvůj regex by mohl vypadat nějak tak to:

0x([0-9A-Fa-f]+)

V Javě s tím pak můžeš pracovat nějak tak to:

String mujRadek = "0x1F";

String hexRegex = "0x([0-9A-Fa-f]+)";
Pattern r = Pattern.compile(hexRegex);
Matcher m = r.matcher(mujRadek);

if(m.find()) {
     String hex = m.group().substring(2);
     System.out.println("HEX: " + hex);
     System.out.println("DEC: " + Integer.parseInt(hex, 16));
}
Nahoru Odpovědět  +1 13. října 17:28
There is more than one way to screw it
Avatar
Jirka
Člen
Avatar
Odpovídá na Elix Novel
Jirka:13. října 19:05

Nebo co třeba něco jako:

package itn.forum;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public class Hex {
public static void main(String[] args) {
        List<String> los = new ArrayList<>();
        los.add(" 0x10 ");
        los.add(" 0x1f 0x16");
        los.add(" 0xzf ");
        los.add(" 0x0cblabla ");
        los.add(" 0x0c ");
        Pattern r = Pattern.compile("\\b0x([0-9A-Fa-f]{2,2})\\b");
        for(String s : los) {
                if(r.matcher(s).find()) { System.out.println(s + " => souhlasi"); }
        }
}
}
Nahoru Odpovědět  +1 13. října 19:05
Kdo nic nedělá, nic nezkazí.
Avatar
Elix Novel
Člen
Avatar
Elix Novel:16. října 11:05

Děkuji všem za pomoc, ale stále to není přesně to co hledám. Zkusím upřesnit svůj dotaz. Mám zadání naprogramovat lexikální analyzátor, kteýr bude zpracovávat text a pomocí tokenů vypisovat na obrazovku text.

  1. Musí rozeznávat klíčová slova (end,begin,if,whi­le,...)

2 ) Musí rozeznávat identifikátory (jakékoliv slovo)

  1. Musí rozeznávat DEC číslo
  2. Musí rozeznávat HEX číslo (s prefixem 0x) a převést ho ve výpisu do DEC
  3. Musí umět přeskakovat mezery (pokud jich je víc po sobě) - vždy zobrazí jen jednu
  4. Musí načítat jen slova s malým písmenem
  5. Délka klíčových slov a identifikátorů nesmí přesáhnout 32 znaků

Pustil jsem se do programování a myslím, že mi funguje vše kromě bodů: 4), 6), 7)..
Matlám se s tím strašně dlouho a pořád nic, tak jsem doufal, že tady mě to zachrání.

Main

    public static void main(String[] args) {
        try {
            Analyzator analyzator = new Analyzator("testFile.txt");
            while (!analyzator.jeVycerpano()) {
                System.out.printf("%s   %s\n", analyzator.currentToken(), analyzator.currentEnum());
                analyzator.cteniZnaku();
            }
        } catch (Exception e) {

        }
    }
}

Analyzator

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;

/**
 *
 * @author Radek
 */
public final class Analyzator {

    private final int MAXIMALNI_DELKA = 32;
    private Token token;
    private String enumy;
    private StringBuilder stringBuilder = new StringBuilder();
    private static final Set<Character> prazdnaMista = new HashSet<Character>();
    private boolean vycerpano = false;

    public Analyzator(String file) {
        try (Stream<String> stream = Files.lines(Paths.get(file))) {

            stream.forEach(stringBuilder::append);

        } catch (IOException e) {
        }

        cteniZnaku();
    }

    static {
        prazdnaMista.add((char) 8);
        prazdnaMista.add((char) 9);
        prazdnaMista.add((char) 11);
        prazdnaMista.add((char) 12);
        prazdnaMista.add((char) 32);
    }

    private void preskakujMezery() {
        int mezery = 0;

        while (prazdnaMista.contains(stringBuilder.charAt(mezery))) {
            mezery++;
        }

        if (mezery > 0) {
            stringBuilder.delete(1, mezery);
        }
    }

    public void cteniZnaku() {
        if (stringBuilder.length() == 0) {
            vycerpano = true;
            return;
        }
        preskakujMezery();
        dalsiZnak();

    }

    private boolean dalsiZnak() {
        for (Token t : Token.values()) {
            int end = t.konecCteni(stringBuilder.toString());

            if (end != 0) {
                {
                    token = t;
                    enumy = stringBuilder.substring(0, end);
                    stringBuilder.delete(0, end);
                    return true;
                }
            }
        }

        return false;
    }

    public Token currentToken() {
        return token;
    }

    public String currentEnum() {
        return enumy;
    }

    public boolean jeVycerpano() {
        return vycerpano;
    }

}

Tokeny

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Radek
 */
public enum Token {
    KEYWORD_BEGIN("begin{0,33}"),
    KEYWORD_END("end{0,33}"),
    KEYWORD_FOR("for{0,33}"),
    KEYWORD_IF("if{0,33}"),
    KEYWORD_THEN("then{0,33}"),
    KEYWORD_ELSE("else{0,33}"),
    KEYWORD_WHILE("while{0,33}"),
    KEYWORD_RETURN("return{0,33}"),
    SEPARATOR_ROVNITKO("="),
    SEPARATOR_CARKA(","),
    SEPARATOR_DVOJTECKA(":"),
    SEPARATOR_STREDNIK(";"),
    NUMBER_DEC("\\d+"),
    NUMBER_HEX("\\b0x[0-9A-F]"),
    BLANK("\\s"),
    IDENTIFIER("\\w{0,33}");

    private final Pattern pattern;

    Token(String regex) {
        pattern = Pattern.compile("^" + regex);
    }

    int konecCteni(String string) {
        Matcher matcher = pattern.matcher(string);

        if (matcher.find()) {
            return matcher.end();
        }

        return 0;
    }
}

A ještě přiložím soubor se kterým pracuji:
testFile.txt

begin;

a,b=100;

c=0x10;

end;

Tak pokud by byl někdo ochotný mi poradit a pomoc to dotáhnout do konce, byl bych vděčný.

 
Nahoru Odpovědět 16. října 11:05
Avatar
Unda
Člen
Avatar
Odpovídá na Elix Novel
Unda:16. října 17:47

V druháku jsem to vyřešil tím, že jsem to načítal po znaku, nikoliv řádku a zjišťoval co je za 0. :))

 
Nahoru Odpovědět 16. října 17:47
Avatar
patrik.valkovic
Šéfredaktor
Avatar
Odpovídá na Elix Novel
patrik.valkovic:16. října 18:25

Pokud máš napsat lexikální analyzátor, tak bych řekl že tě s regulárními výrazy pošlou někam. Lexikální analyzátor využívá zpravidla regulárních jazyků a tedy stavových automatů. I když lze každý regulární výraz převést na stavový automat, jejich použití je v lexikálním analyzátoru nevhodné, protože jsou příliš pomalé. Pouvažuj nad tím, jestli to nechceš napsat pořádně :D

Nahoru Odpovědět 16. října 18:25
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Elix Novel
Člen
Avatar
Elix Novel:18. října 10:25

Ale ve výsledku to vše funguje přesně podle zadání moc nerozumím jak bych to vlastně měl jinak přepsat. Koukám do toho každý den, ale bohužel jsem se moc neposunul..

 
Nahoru Odpovědět 18. října 10:25
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 8 zpráv z 8.