Jump to content

Compiler/lexical analyzer: Difference between revisions

m
→‎{{header|FreeBASIC}}: added sleep and changed "\" into chr(92)
m (Link to additional examples.)
m (→‎{{header|FreeBASIC}}: added sleep and changed "\" into chr(92))
Line 1,823:
=={{header|FreeBASIC}}==
Tested with FreeBASIC 1.05
<lang FreeBASIC>enum' Token_typechanged and added some lines marked with #change# and #added#
' the Rosetta Code highlighter does not like \"
' 27-10-2016
 
enum Token_type
tk_EOI
tk_Mul
Line 1,856 ⟶ 1,860:
tk_String
end enum
 
const NewLine = chr(10)
const DoubleQuote = chr(34)
 
' where we store keywords and variables
type Symbol
Line 1,865 ⟶ 1,869:
tok as Token_type
end type
 
dim shared symtab() as Symbol
 
dim shared cur_line as string
dim shared cur_ch as string
dim shared line_num as integer
dim shared col_num as integer
 
function is_digit(byval ch as string) as long
is_digit = (ch <> "") and ch >= "0" and ch <= "9"
end function
 
function is_alnum(byval ch as string) as long
is_alnum = (ch <> "") and ((UCaseucase(ch) >= "A" and UCaseucase(ch) <= "Z") or (is_digit(ch)))
end function
 
sub error_msg(byval eline as integer, byval ecol as integer, byval msg as string)
' print "("; eline; ":"; ecol; ")"; " "; msg
print "("; eline; ":"; ecol; ") "; msg ' #change#
print : print "Hit any to end program" ' #added#
sleep ' #added#
system
end sub
 
' add an identifier to the symbol table
function install(byval s_name as string, byval tok as Token_type) as integer
dim n as integer
 
n = ubound(symtab)
redim preserve symtab(n + 1)
n = ubound(symtab)
 
symtab(n).s_name = s_name
symtab(n).tok = tok
return n
end function
 
' search for an identifier in the symbol table
function lookup(byval s_name as string) as integer
dim i as integer
 
for i = lbound(symtab) to ubound(symtab)
if symtab(i).s_name = s_name then return i
Line 1,908 ⟶ 1,915:
return -1
end function
 
sub next_line() ' read the next line of input from the source file
cur_line = ""
Line 1,918 ⟶ 1,925:
col_num = 1
end sub
 
sub next_char() ' get the next char
cur_ch = ""
Line 1,925 ⟶ 1,932:
if col_num <= len(cur_line) then cur_ch = mid(cur_line, col_num, 1)
end sub
 
function follow(byval err_line as integer, byval err_col as integer, byval expect as string, byval ifyes as Token_type, byval ifno as Token_type) as Token_type
if cur_ch = expect then
Line 1,934 ⟶ 1,941:
return ifno
end function
 
sub gettok(byref err_line as integer, byref err_col as integer, byref tok as Token_type, byref v as string)
' skip whitespace
Line 1,940 ⟶ 1,947:
next_char()
loop
 
err_line = line_num
err_col = col_num
 
select case cur_ch
case "": tok = tk_eoi: exit sub
Line 1,976 ⟶ 1,983:
case "'": ' single char literals
next_char()
v = str(Ascasc(cur_ch))
if cur_ch = "'" then error_msg(err_line, err_col, "empty character constant")
' if cur_ch = "\" thenThen
if cur_ch = chr(92) then ' #change# ascii code for \ = 92
next_char()
if cur_ch = "n" then
v = "10"
' elseif cur_ch = "\" thenThen
elseif cur_ch = chr(92) vthen = Str(Asc("\"))' #change#
' v = Str(Asc("\"))
v = "92" ' #change#
else error_msg(err_line, err_col, "unknown escape sequence: " + cur_ch)
end if
Line 2,034 ⟶ 2,044:
end select
end sub
 
sub init_lex(byval filein as string)
install("else", tk_else)
Line 2,041 ⟶ 2,051:
install("putc", tk_putc)
install("while", tk_while)
 
open filein for input as #1
 
cur_line = ""
line_num = 0
Line 2,049 ⟶ 2,059:
next_char()
end sub
 
sub scanner()
dim err_line as integer
Line 2,056 ⟶ 2,066:
dim v as string
dim tok_list(tk_eoi to tk_string) as string
 
tok_list(tk_EOI ) = "End_of_input"
tok_list(tk_Mul ) = "Op_multiply"
Line 2,088 ⟶ 2,098:
tok_list(tk_Integer) = "Integer"
tok_list(tk_String ) = "String"
 
do
gettok(err_line, err_col, tok, v)
' print using "##### ##### \ \"; err_line; err_col; tok_list(tok);
' #change# in the next line the last \ (back slash) removed, and then added with chr(92)
print using "##### ##### \ " + chr(92); err_line; err_col; tok_list(tok);
if tok = tk_integer orelse tok = tk_ident orelse tok = tk_string then print " " + v;
print
loop until tok = tk_eoi
end sub
 
sub main()
' if command(1) = "" then print "filename required" : system
if command(1) = "" then print "filename required" : exit sub ' #change#
init_lex(command(1))
scanner()
end sub
 
main()
print : print "Hit any to end program" ' #added#
sleep ' #added#
system</lang>
 
{{out|case=test case 3}}
<b>
<pre> 5 16 Keyword_print
<pre>
5 16 Keyword_print
5 40 Op_subtract
6 16 Keyword_putc
Line 2,142 ⟶ 2,155:
21 26 Integer 92
22 26 Integer 32
22 30 End_of_input</pre>
</pre>
</b>
 
457

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.