11use std:: {
22 cell:: RefCell ,
3+ fmt:: Display ,
34 fs:: { File , OpenOptions , read_to_string} ,
45 io:: { self , Read , Seek , Write } ,
6+ ops:: Range ,
57 path:: PathBuf ,
68} ;
79use thiserror:: Error ;
810
11+ use crate :: {
12+ grammar_actions:: { DataType , TokenFloatLiteral , TokenIntLiteral , TokenStringLiteral } ,
13+ grammar_lexer:: log_error,
14+ } ;
15+
916#[ derive( Debug , Error ) ]
1017pub enum CompilerError {
1118 #[ error( "Parser internal error: {0:?}" ) ]
@@ -25,6 +32,7 @@ thread_local! {
2532 pub static LEXER_FILE : RefCell <Option <File >> = const { RefCell :: new( None ) } ;
2633 pub static PARSER_FILE : RefCell <Option <File >> = const { RefCell :: new( None ) } ;
2734 pub static SYMBOL_TABLE_FILE : RefCell <Option <File >> = const { RefCell :: new( None ) } ;
35+ pub static SYMBOL_TABLE : RefCell <Vec <SymbolTableElement >> = const { RefCell :: new( Vec :: new( ) ) }
2836}
2937
3038pub fn set_source_file_path ( path : PathBuf ) {
@@ -95,15 +103,34 @@ pub fn open_symbol_table_file() -> Result<(), io::Error> {
95103 } )
96104}
97105
98- pub fn write_to_symbol_table_file ( line : & str ) -> Result < ( ) , io:: Error > {
106+ pub fn dump_symbol_table_to_file ( ) -> Result < ( ) , io:: Error > {
99107 SYMBOL_TABLE_FILE . with ( |f| {
100108 if let Some ( mut file) = f. borrow_mut ( ) . as_ref ( ) {
101- writeln ! ( file, "{line}" ) ?;
109+ for symbol in SYMBOL_TABLE . take ( ) {
110+ writeln ! ( file, "{symbol}" ) ?;
111+ }
102112 }
103113 Ok ( ( ) )
104114 } )
105115}
106116
117+ pub fn log_error_and_exit (
118+ pos : Range < usize > ,
119+ error : CompilerError ,
120+ offset : usize ,
121+ trace : bool ,
122+ ) -> ! {
123+ dump_symbol_table_to_file ( ) . expect ( "Failed to write symbol table" ) ;
124+ log_error (
125+ pos,
126+ error,
127+ offset,
128+ & read_source_to_string ( ) . expect ( "Failed to print error location" ) ,
129+ trace,
130+ ) ;
131+ std:: process:: exit ( 1 )
132+ }
133+
107134pub fn read_source_to_string ( ) -> Result < String , CompilerError > {
108135 SOURCE_CODE_PATH . with ( |f| {
109136 if let Some ( path) = f. borrow ( ) . as_ref ( ) {
@@ -134,3 +161,79 @@ pub fn read_parser_file_to_string() -> Result<String, CompilerError> {
134161 }
135162 } )
136163}
164+
165+ #[ derive( Clone , Debug ) ]
166+ pub enum SymbolTableElement {
167+ VarDeclaration ( String , DataType , usize ) ,
168+ IntLiteral ( TokenIntLiteral ) ,
169+ FloatLiteral ( TokenFloatLiteral ) ,
170+ StringLiteral ( TokenStringLiteral ) ,
171+ }
172+
173+ impl Display for SymbolTableElement {
174+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
175+ match self {
176+ Self :: FloatLiteral ( float) => write ! (
177+ f,
178+ "{}|CONST_FLOAT|{}|{}" ,
179+ float. original,
180+ float. original,
181+ float. original. len( )
182+ ) ?,
183+ Self :: IntLiteral ( int) => {
184+ write ! ( f, "{}|CONST_INT|{}|{}" , int, int, int. to_string( ) . len( ) ) ?
185+ }
186+ Self :: StringLiteral ( string) => {
187+ write ! ( f, "{}|CONST_STRING|{}|{}" , string, string, string. len( ) ) ?
188+ }
189+ Self :: VarDeclaration ( token, r#type, length) => {
190+ write ! ( f, "{}|{}|-|{}" , token, r#type, length) ?
191+ }
192+ } ;
193+ Ok ( ( ) )
194+ }
195+ }
196+
197+ impl PartialEq for SymbolTableElement {
198+ fn eq ( & self , other : & Self ) -> bool {
199+ match ( self , other) {
200+ ( Self :: FloatLiteral ( token0) , Self :: FloatLiteral ( token1) ) => token0 == token1,
201+ ( Self :: IntLiteral ( token0) , Self :: IntLiteral ( token1) ) => token0 == token1,
202+ ( Self :: StringLiteral ( token0) , Self :: StringLiteral ( token1) ) => token0 == token1,
203+ ( Self :: VarDeclaration ( token0, _, _) , Self :: VarDeclaration ( token1, _, _) ) => {
204+ token0 == token1
205+ }
206+ _ => false ,
207+ }
208+ }
209+ }
210+
211+ impl From < TokenIntLiteral > for SymbolTableElement {
212+ fn from ( value : TokenIntLiteral ) -> Self {
213+ Self :: IntLiteral ( value)
214+ }
215+ }
216+
217+ impl From < TokenFloatLiteral > for SymbolTableElement {
218+ fn from ( value : TokenFloatLiteral ) -> Self {
219+ Self :: FloatLiteral ( value)
220+ }
221+ }
222+
223+ impl From < TokenStringLiteral > for SymbolTableElement {
224+ fn from ( value : TokenStringLiteral ) -> Self {
225+ Self :: StringLiteral ( value)
226+ }
227+ }
228+ pub fn push_to_symbol_table ( item : SymbolTableElement ) {
229+ SYMBOL_TABLE . with ( |table| {
230+ // Avoid pushing duplicate symbols to the symbol table
231+ if !symbol_exists ( & item) {
232+ table. borrow_mut ( ) . push ( item) ;
233+ }
234+ } )
235+ }
236+
237+ pub fn symbol_exists ( item : & SymbolTableElement ) -> bool {
238+ SYMBOL_TABLE . with ( |table| table. borrow ( ) . contains ( item) )
239+ }
0 commit comments