w wielu przypadkach w rozwiązaniach urządzeń z mikrokontrolerami przydatnym jest możliwość porozumienia z mikrokontrolerem. Swoisty dialog operatora/użytkownika z urządzeniem wymaga jednak stworzenia odpowiedniego języka. Taki kanał wymiany informacji pozwala na szerokie możliwości określenia szczegółów synergii ze stroną przeciwną. Podobną funkcjonalność może zapewnić odpowiednio rozbudowany frontpanel, chociaż właściwie należy uznać, że każdy taki panel będzie zbyt ubogi w swoich możliwościach w stosunku do realizacji prawdziwego dialogu. Jak dialog... to normalnym jest, że niezbędna jest jakaś techniczna platforma porozumienia. W przypadku komunikacji międzyludzkiej taką platformą jest narząd mowy i słuchu (czasem telepatia ). W przypadku urządzeń elektronicznych takim odpowiednikiem jest kanał transmisji szeregowej. Pozwala on na przesyłanie w obie strony ciągu znaków, taki odpowiednik ludzkich głosek. Z głosek (czyli liter) możliwe jest utworzenie fraktalnie wyższej warstwy, czyli wyrazów i zdań. Bez zbędnego rozbudowywania frontpaneli, przekazywanie via serial informacji daje nieograniczone możliwości. Można zaryzykować stwierdzenie, że potęga słowa jest nieskończona.
Podstawą takiej komunikacji jest odpowiedni język. Skoro język... to mamy zdania. Występuje tu operacja budowy zdań, do ich budowy niezbędne są kolejne detale. Takimi detalami są rzecz jasna wyrazy, liczby i różne znaki dodatkowe. Rozkładając proces analizy zdań na poszczególne elementy mamy przede wszystkim analizę leksykalną i analizę syntaktyczną. Analiza leksykalna jest zagadnieniem dotyczącym budowy poszczególnych składowych przekazywanych komunikatów. Nie trzeba nikogo przekonywać, że wyraz normalnie składa się z liter (w komunikacji z urządzeniami można rozszerzyć normy i ustalić, że wyraz jest ciągiem liter lub cyfr zaczynającym się od litery). Podobnie liczby składają się z ciągu znaków będących cyframi z ewentualnym dodatkiem znaku kropki jako separatora pomiędzy częścią całkowitą i ułamkową liczby (zakładając, że jest mowa jedynie o liczbach w systemie dziesiętnym). Reasumując, analiza leksykalna jest zogniskowana na budowie części składowych zdania jakimi są wyrazy i liczby natomiast nie zajmuje się analizą syntaktyczną (analizą składni zdania).
Przedstawiony moduł stanowi narzędzie do analizy leksykalnej. Jest skonstruowany w formie „otwartego” modułu. Ta „otwartość” przede wszystkim wyraża się tym, że moduł nie posiada własnej wbudowanej instancji a posiłkuje się instancją „obcą”. Pozwala to na utworzenie fraktalnie wyższych poziomów analizy, jednak każdy taki poziom jest oparty o analizę leksykalną.
Moduł „eksportuje” następujące typy i funkcje:
Kod: Zaznacz cały
typedef enum { LexicNoSy , // symbol nierozpoznany
LexicEndFileSy , // napotkano koniec pliku
LexicEndLineSy , // napotkano koniec wiersza
LexicEqSy , // napotkano znak '='
LexicPlusSy , // napotkano znak '+'
LexicMinusSy , // napotkano znak '-'
LexicMultSy , // napotkano '*'
LexicDivSy , // napotkano '/'
LexicLTSy , // napotkano '<'
LexicGTSy , // napotkano '>'
LexicLESy , // napotkano '<='
LexicGESy , // napotkano '>='
LexicAndSy , // napotkano '&'
LexicLParentSy , // napotkano '('
LexicRParentSy , // napotkano ')'
LexicLBrackSy , // napotkano '['
LexicRBrackSy , // napotkano ']'
LexicCommaSy , // napotkano ','
LexicPointSy , // napotkano '.'
LexicColonSy , // napotkano ':'
LexicSemiColonSy , // napotkano ';'
LexicHashSy , // napotkano '#'
LexicCConstSy , // naptkano stala calkowita
LexicRConstSy , // napotkano stala rzeczywista
LexicSConstSy , // napotkano stala tekstowa
LexicIdentSy } LexicSymbolType ; // napotkano identyfikator
- LexicNoSy – oznacza, że analizator „mówi”, że nie rozumie co to jest,
- LexicEndLineSy – (taki sztuczny element zdania) oznacza, że analizator dotarł do końca wiersza, czasami przydatne jest traktowanie końca linii za element leksykalny, czasami jest przydatna swoista przezroczystość końca wiersza (więcej przy okazji rozpatrywaniu pojęcie sektora),
- LexicEndFileSy – (taki sztuczny element zdania) oznacza, że analizator dotarł do końca pliku (końca zbioru wierszy, więcej przy okazji rozpatrywaniu pojęcie sektora),
- LexicCConstSy – oznacza, że analizator łyknął dziesiętną liczbę całkowitą,
- LexicRConstSy – oznacza, że analizator wczytał dziesiętną liczbę zmiennoprzecikową,
- LexicSConstSy – oznacza, że analizator rozpoznał stałą tekstową, jako dowolny łańcuch znaków ujęty w apostrofy (jako apostrof uważany jest znak ' lub ", z tym, że apostrof zamykający musi być identyczny jak otwierający),
- LexicIdentSy – oznacza, że analizator napotkał wyraz literowy (jako ciąg liter lub cyfr zaczynający się od litery), jednak nie rozpatruje znaczenia napotkanego wyrazu (to jest domena analizy syntaktycznej).
Kod: Zaznacz cały
typedef uint8_t SpellingType [ 16 ] ;
typedef uint8_t InpStringType [ 42 ] ;
- SpellingType – typ reprezentujący zmienną przechowującą „obraz” ostatnio wczytanego elementu leksykalnego (w szczególnym wypadku jest „tekst wyrazu literowego”),
- InpStringType – typ reprezentujący zmienną przechowująca wartość stałej łańcuchowej (bez użytych znaków apostrofów).
Kod: Zaznacz cały
typedef void ( * ListServiceProcT ) ( uint8_t /* Ch */ ,
void * /* CallParam */ ) ;
- typ „metody” związanej z raportowaniem analizowanych wierszy.
Kod: Zaznacz cały
struct _LexicalAnalysisInstanceType ;
typedef struct _LexicalAnalysisInstanceType * PtrLexicalAnalysisInstanceType ;
typedef uint16_t ( * LexicalAnalysisServPType ) ( PtrLexicalAnalysisInstanceType /* LexicalAnalysisInstance */ ) ;
typedef void ( * LexicalAnalysisRaportPType ) ( PtrLexicalAnalysisInstanceType /* LexicalAnalysisInstance */ ) ;
typedef struct _LexicalAnalysisInstanceType {
void * CallParam ;
ListServiceProcT ListService ;
LexicalAnalysisRaportPType RaportService ;
LexicalAnalysisServPType GetSectorServ ;
uint8_t * DataSector ;
uint8_t * SectorCh ;
uint8_t * BeginOfLine ;
uint8_t * EndOfLine ;
uint8_t RealEnable ;
uint8_t * CurrChar ;
uint8_t LineChar ;
uint8_t LineChar2 ;
uint8_t AutoReadLineFlag ;
uint8_t AutoEOFAnswer ;
uint16_t SectorChPos ;
uint32_t CInpValue ;
uint16_t LineCounter ;
uint16_t SectorSize ;
uint16_t LineSize ;
double RInpValue ;
uint16_t SpeelCt ;
SpellingType InpSpelling ;
InpStringType SInpValue ;
uint16_t ErrCodes [ MaxErr ] ;
SpellingType ErrSpell [ MaxErr ] ;
uint8_t ErrIndex ;
uint8_t EndOfLineReached ;
uint8_t EndOfFileReached ;
uint8_t ErrorPresent ;
uint8_t GlobalErrorPresent ;
} LexicalAnalysisInstanceType ;
Typ instancji używanej w module. Ciało instancji należy utworzyć w warstwie wyższej. Z pól instancji wybrane mają następujące znaczenie:
- void * CallParam – wskaźnik do dowolnej struktury, jako dodatkowe dane z warstwy wyższej przekazywane do wybranych metod,
- ListServiceProcT ListService – metoda do generowania pojedynczego wiersza raportu analizy leksykalnej,
- LexicalAnalysisRaportPType RaportService – metoda do generowania raportu z analizy, w standardowej implementacji jest przedrukiem analizowanych wierszy z dodaniem z przodu numeru wiersza,
- LexicalAnalysisServPType GetSectorServ – metoda do wczytania kolejnego sektora analizowanego tekstu,
- uint8_t * DataSector – wskaźnik do obszaru analizowanego sektora,
- uint16_t SectorSize – wielkość obszaru sektora w znakach (liczba znaków wskazywanych przez wskaźnik DataSector),
- uint8_t * SectorCh – wskaźnik w obszarze sektora,
- uint8_t * BeginOfLine – wskaźnik w obszarze sektora określający początek analizowanego wiersza,
- uint8_t * EndOfLine – wskaźnik w obszarze sektora określający koniec analizowanego wiersza,
- uint8_t RealEnable – flaga określająca, czy analizator będzie rozpatrywał liczby zmiennoprzecienkowe (należy sterować tą flagą w przypadku, gdy spodziewane jest wczytanie klasycznego zapisu adresu IP jako cztery liczby rozdzielone trzema znakami kropki),
- uint8_t * CurrChar – wskaźnik w obrębie wiersza, gdzie „znajduje się” aktualnie analizator leksykalny,
- uint8_t AutoReadLineFlag – flaga automatycznego przejścia do kolejnego wiersza (dla TRUE), lub „zawiśnięciu” na każdym końcu wiersza (FALSE),
- uint32_t CInpValue – wczytana liczba całkowita (przechowywana jako liczba 32-bitowa),
- double RInpValue – wczytana liczba zmiennoprzecinkowa podwójnej precyzji,
- InpStringType SInpValue – wczytana stała łańcuchowa (bez znaków apostrofów),
- SpellingType InpSpelling – „obraz” bieżąco wczytanego elementu leksykalnego,
- uint16_t ErrCodes [ MaxErr ] – zgłoszone dla wiersza kody błędów,
- SpellingType ErrSpell [ MaxErr ] – „synchronicznie” z ErrCodes „obraz” syntaktycznych elementów, które wygenerowały błąd,
- uint8_t ErrIndex – liczba błędów zgłoszonych dla wiersza (zerowana po każdym wczytaniu kolejnego wiersza)
- uint8_t ErrorPresent – flaga określająca, czy w danym wierszu wystąpiły błędy (zerowana po każdym wczytaniu kolejnego wiersza),
- uint8_t GlobalErrorPresent – flaga określająca, czy w danym pliku (zbiorze sektorów → zbiorze wierszy) wystąpiły błędy (czy wystąpił błąd gdziekolwiek).
Kod: Zaznacz cały
uint8_t ReadLine ( PtrLexicalAnalysisInstanceType /* LexicalAnalysisInstance */ ) ;
- funkcja do wczytania kolejnego wiersza z obszaru sektora,
Kod: Zaznacz cały
void AnalError ( uint16_t /* ErrorNo */ ,
PtrLexicalAnalysisInstanceType /* LexicalAnalysisInstance */ ) ;
- funkcja do zgłoszenia kodu błędu (do ErrSpell zostanie przeniesiona bieżąca zawartość Spelling),
Kod: Zaznacz cały
void AnalLCError ( uint16_t /* ErrorCode */ ,
uint32_t /* LCValue */ ,
PtrLexicalAnalysisInstanceType /* LexicalAnalysisInstance */ ) ;
void AnalCError ( uint16_t /* ErrorCode */ ,
uint16_t /* CValue */ ,
PtrLexicalAnalysisInstanceType /* LexicalAnalysisInstance */ ) ;
- funkcja do zgłoszenia kodu błędu (w ErrSpell zostanie umieszczona wartość CValue/LCValue),
Kod: Zaznacz cały
void AnalSError ( uint16_t /* ErrorCode */ ,
uint8_t * /* SValue */ ,
PtrLexicalAnalysisInstanceType /* LexicalAnalysisInstance */ ) ;
- funkcja do zgłoszenia kodu błędu (w ErrSpell zostanie umieszczona wartość SValue),
Kod: Zaznacz cały
LexicSymbolType ReadSymbol ( PtrLexicalAnalysisInstanceType /* LexicalAnalysisInstance */ ) ;
- funkcja do wczytania kolejnego elementu leksykalnego, wartość funkcji identyfikuje element leksykalny,
Kod: Zaznacz cały
void CheckEndOfLine ( PtrLexicalAnalysisInstanceType /* LexicalAnalysisInstance */ ,
uint16_t /* ErrorCode */ ) ;
- funkcja do zgłoszenia kodu błędu dla każdego elementu leksykalnego występującego przed końcem wiersza,
Kod: Zaznacz cały
LexicSymbolType AcceptSymbol ( PtrLexicalAnalysisInstanceType /* LexicalAnalysisInstance */ ,
LexicSymbolType /* ExpectedSymbol */ ,
uint16_t /* ErrorCode */ ) ;
- funkcja do wczytania kolejnego elementu leksykalnego i zgłoszenia błędy w sytuacji, gdy wczytany element leksykalny był inny niż oczekiwany,
Kod: Zaznacz cały
void OpenSectorAnalyser ( PtrLexicalAnalysisInstanceType /* LexicalAnalysisInstance */ ,
uint8_t * /* LinesBuffer */ ,
uint16_t /* LinesSize */ ,
ListServiceProcT /* TraceListService */ ,
void * /* CallParam */);
- funkcja do otwarcia analizy leksykalnej, ustawia wartości początkowe pól instancji, podłącza w instancji „standardowe” metody, podłącza pod analizator sektor obszaru /parametr LinesBuffer/ o określonej wielkości /parametr LinesSize/, wczytuje z sektora pierwszy wiersz.
Kod: Zaznacz cały
void CloseSectorAnalyser ( PtrLexicalAnalysisInstanceType /* LexicalAnalysisInstance */ ) ;
- funkcja do zamknięcia analizy leksykalnej dla danego sektora.