fbcadcam-macro
Re: fbcadcam-macro
The technique I employ in fbcadcam is about as crude as it gets.
Simply said, I afford the use of 9 (each) 1d, 2d and 3d arrays OF (each) numeric data type (Boolean, Byte, Short, Long, Integer, Double etc..)
In the event the users program (test.bas) does a REDIM
I let FB do the REDIM of that user declared array.
There is no shuffling and of course there is no faster process.
Note: this problem is similar to and has been addressed by the developers of Relational Data Bases. And it is in my thoughts that I might attempt to employ their use for this issue but then fbcadcam-macro would not be independent so to speak.
Simply said, I afford the use of 9 (each) 1d, 2d and 3d arrays OF (each) numeric data type (Boolean, Byte, Short, Long, Integer, Double etc..)
In the event the users program (test.bas) does a REDIM
I let FB do the REDIM of that user declared array.
There is no shuffling and of course there is no faster process.
Note: this problem is similar to and has been addressed by the developers of Relational Data Bases. And it is in my thoughts that I might attempt to employ their use for this issue but then fbcadcam-macro would not be independent so to speak.
Re: fbcadcam-macro
Yes, fbcadcam-macro is crude at best. I'm not being humble, I'm speaking practically.
For example I say I afford the use of 9 arrays... Well, that's not exactly correct because my SUBS and FUNCTION sucks up (use) some of those available 9 arrays.
declare sub test(t(1) as integer)
dim as integer a(2),b(3),c(4),d(5),e(6),f(7),g(8),h(9) and that's all you get.
For example I say I afford the use of 9 arrays... Well, that's not exactly correct because my SUBS and FUNCTION sucks up (use) some of those available 9 arrays.
declare sub test(t(1) as integer)
dim as integer a(2),b(3),c(4),d(5),e(6),f(7),g(8),h(9) and that's all you get.
Re: fbcadcam-macro
imnsho everyone should learn oop if the language supports it
Re: fbcadcam-macro
It has been in the back of my mind that I would afford the user to use oop in the script (test.bas)
but as you can see i don't oop too much in fact the last thing i did regarding oop was to un-oop Ball collisions physics in the hope I could at the least, understand the physics.... but alas (LOL / IMNSHO/ ISIABSIMA)
but as you can see i don't oop too much in fact the last thing i did regarding oop was to un-oop Ball collisions physics in the hope I could at the least, understand the physics.... but alas (LOL / IMNSHO/ ISIABSIMA)
Re: fbcadcam-macro
oop to shorten your own parser :D
you're far ahead of a lot of programmers. so no big deal really.
i think if there were ever to be another sub-forum, it should be about oop
you're far ahead of a lot of programmers. so no big deal really.
i think if there were ever to be another sub-forum, it should be about oop
Re: fbcadcam-macro
I agree oop is awesome and if I ooped fbcadcam-macro.bas (which i probably will do eventually) then yes, it will shorten it from 30k LOC to something considerably less. I write code un-ooped for my benefit because it helps me keep things sorted (in my own mind). I'm kinda like an old dog that can't learn a new trick. That's not to say I can't write code with oop initially. I can. But if it's a complex (extensive bit of code) then un-oop works best for me.
so i was checking out the list of D.J.Peters FreeBASIC activities of the past 10 years which is absolutely impressive i might add
viewtopic.php?f=17&t=24043
and listed in his Tips and Tricks (source codes): another easy to understand EVAL() expression solver
viewtopic.php?f=7&t=16664
i was reminded about the precedence NEGATE and exponentiate
The correct precedence order is exponentiate first then negate.
ver. 6 had it backwards so i uploaded ver. 7 with this correction
http://fbcadcam.org/fbcadcam-macro/fbca ... ings-7.bas
so i was checking out the list of D.J.Peters FreeBASIC activities of the past 10 years which is absolutely impressive i might add
viewtopic.php?f=17&t=24043
and listed in his Tips and Tricks (source codes): another easy to understand EVAL() expression solver
viewtopic.php?f=7&t=16664
i was reminded about the precedence NEGATE and exponentiate
The correct precedence order is exponentiate first then negate.
ver. 6 had it backwards so i uploaded ver. 7 with this correction
http://fbcadcam.org/fbcadcam-macro/fbca ... ings-7.bas
Re: fbcadcam-macro
you don't have to oo the whole thing!
congrats on being able to keep track of all that
congrats on being able to keep track of all that
Re: fbcadcam-macro
Hi Owen,
dafhi is right, you don't need to rewrite the whole thing in OOP to be able to use objects effectively.
I took a look at your code. Uff. Seems that you would greatly benefit from some abstractions. First, you will find your code easier to write, easier to expand and hence, easier to maintain.
The first thing that I would recommend is that you split the lexing, parsing and evaluation phases of your scripting language. Then, it will be easier to add new features as you progress. Take a look at the following class, plucked from my Forth compiler/interpreter:
This is the first phase of compiling code, also called 'lexical analyzer' or 'lexer'. What this class does is splice a string into small units of syntax (called 'lexemes' or 'tokens'), so you work with one token at a time during the parsing phase. Two very simple usage examples (the code assumes that you saved the previous code in the file 'lexer.bi')
As you can see, the first example just prints the tokens (including delimiters). The second one does the same thing, but loads the input string from a file and filters the delimiters when printing. It greatly simplifies the construction of the parser.
If you also plan to compile the code to bytecode, you will have to code a Virtual Machine. Here's one link that will help you:
https://compilers.iecc.com/crenshaw/tutorfinal.pdf
It is a very well known tutorial on compiler construction that will help you immensely. The code the author presents in the book is in Turbo Pascal 4.0, and the assembler code is for the 68000 (the old Macs), but the concepts and the rantings are invaluable.
As for the parser, the example that you mention before (the EVAL() solver by D. J. Peters) is what's called a Recursive Descent Parser. They are very easy to implement and understand, but be aware that you can't parse the entire syntax of FB with it. However, you can implement only a subset of the language and get by just fine.
Best of luck! Feel free to shout if you need assistance.
Paul
dafhi is right, you don't need to rewrite the whole thing in OOP to be able to use objects effectively.
I took a look at your code. Uff. Seems that you would greatly benefit from some abstractions. First, you will find your code easier to write, easier to expand and hence, easier to maintain.
The first thing that I would recommend is that you split the lexing, parsing and evaluation phases of your scripting language. Then, it will be easier to add new features as you progress. Take a look at the following class, plucked from my Forth compiler/interpreter:
Code: Select all
/'
very simple lexical scanner class (a.k.a. lexer)
responsibility: splices a string into lexemes ('tokens') using single
character delimiters
mutability: immutable
this was originally used in a concurrent system, so it ought to be thread-safe
immutable classes are thread-safe by design
'/
type lexer
'' public interface for the class
public:
declare constructor( byref inpString as const string, byref del as const string )
declare function getToken() as string
'' private members for maintaining state
private:
as string m_lookChar '' the current char that m_charPos points to
as string m_delimiters '' delimiters that are used for string splicing
as string m_inputString '' the string to be spliced
as uinteger m_charPos '' current char position on string
as uinteger m_stringLen '' the input string length
'' helper functions
'' if one were to override these helpers in a derived classes, they should be declared protected
declare sub m_getChar()
declare function m_inString( byref srchString as string, byref strng as string ) as integer
declare function m_isDelimiter( byref c as string ) as integer
end type
constructor lexer( byref inpString as const string, byref del as const string )
/'
the constructor for the class
note that, as it is an immutable class, it makes no sense to create a default, empty
constructor, for it needs data to perform its function. This form of passing data to
immutable objects is called 'dependency injection'
'/
m_inputString = inpString
m_stringLen = len( m_inputString )
m_charPos = 0
m_lookChar = ""
m_delimiters = del
end constructor
function lexer.getToken() as string
/'
retrieves the next token on the input string
if there are no more tokens to retrieve, it returns an empty string to signal
that there are no more tokens to splice
'/
dim as string ret
'' feed a char to the current char if it's empty
if asc( m_lookChar ) = 0 then
m_getChar()
end if
/'
this is the only complicated piece of code of the class
it works like this:
IF the current char is a delimiter OR the char pos is beyond the string length THEN
get the next char to advance the char position to the beginning of the next token
(remember that, if there are no more chars in the string, getChar() returns an empty string)
return the delimiter
ELSE
IF the current char is not a delimiter AND the char pos is less than the string length THEN
WHILE the current character isn't a delimiter and the current character is not an empty string DO
assemble the current char into the token
get the next char
LOOP
return the assembled token
END IF
END IF
'/
if( m_isDelimiter( m_lookChar ) or m_charPos >= m_stringLen ) then
ret = m_lookChar
m_getChar()
return( ret )
else
if( not m_isDelimiter( m_lookChar ) and m_charPos < m_stringLen ) then
do while( not m_isDelimiter( m_lookChar ) and m_lookChar <> "" )
ret &= m_lookChar
m_getChar()
loop
return( ret )
end if
end if
end function
sub lexer.m_getChar()
'' if the char pos is still less than the input string length, read the next char
if m_charPos < len( m_inputString ) then
m_lookChar = chr( m_inputString[ m_charPos ] )
m_charPos += 1
else
'' if not, this will signal the end of the string (as there are no more chars to read)
m_lookChar = ""
end if
end sub
function lexer.m_inString( byref srchString as string, byref strng as string ) as integer
/'
returns -1 if srchString is within strng
note that this function and m_isDelimiter return numerical values because FB
issues warnings if you return 'proper' boolean values
'/
if( inStr( strng, srchString ) > 0 ) then
return( -1 )
else
return( 0 )
end if
end function
function lexer.m_isDelimiter( byref c as string ) as integer
'' returns true (any value but zero) if the string c is a delimiter
return( m_inString( c, this.m_delimiters ) )
end function
Code: Select all
'' simple lexer example 1: basic usage of the lexer class
#include once "lexer.bi"
'' use white space as delimiters: space, LF, CR and tab
dim as string delimiters = chr( 32 ) & chr( 10 ) & chr( 13 ) & chr( 9 )
dim as string inputString = "This is a test"
dim as string token
'' as lexer is an immutable class, you have to instantiate it like this
dim as lexer lx = lexer( inputString, delimiters )
'' always get the first token before starting the loop
token = lx.getToken()
'' get all tokens (including delimiters)
do while( token <> "" )
? token
token = lx.getToken()
loop
sleep()
Code: Select all
'' simple lexer example 2: lexing a file
#include once "lexer.bi"
function isWhiteSpace( byref s as const string ) as boolean
'' a simple helper function
'' returns true if the string c is a whitespace char
dim as string c = chr( 32 ) & chr( 10 ) & chr( 13 ) & chr( 9 )
return( iif( inStr( c, s ) > 0, true, false ) )
end function
'' use white space as delimiters: space, LF, CR and tab
dim as string delimiters = chr( 32 ) & chr( 10 ) & chr( 13 ) & chr( 9 )
dim as string inputString = ""
dim as string token
'' open a file
dim as integer fh = freeFile()
dim as string fileName = "SmallWorld-all.svg" '' replace it for the plain-text file of your choice
if( open( fileName for input as fh ) = 0 ) then
'' if the file was successfully opened, retrieve all tokens
do while( not eof( fh ) )
line input #fh, inputString
'' as lexer is an immutable class, you have to instantiate it like this
dim as lexer lx = lexer( inputString, delimiters )
token = lx.getToken()
'' get all tokens
do while( token <> "" )
'' print the token if it is not a delimiter (white space in this case)
if( isWhiteSpace( token ) = false ) then
? token
end if
token = lx.getToken()
loop
loop
end if
close( fh )
sleep()
If you also plan to compile the code to bytecode, you will have to code a Virtual Machine. Here's one link that will help you:
https://compilers.iecc.com/crenshaw/tutorfinal.pdf
It is a very well known tutorial on compiler construction that will help you immensely. The code the author presents in the book is in Turbo Pascal 4.0, and the assembler code is for the 68000 (the old Macs), but the concepts and the rantings are invaluable.
As for the parser, the example that you mention before (the EVAL() solver by D. J. Peters) is what's called a Recursive Descent Parser. They are very easy to implement and understand, but be aware that you can't parse the entire syntax of FB with it. However, you can implement only a subset of the language and get by just fine.
Best of luck! Feel free to shout if you need assistance.
Paul
Last edited by paul doe on Oct 06, 2017 21:49, edited 2 times in total.
Re: fbcadcam-macro
thank you very much for the info, i can use all the help i can get.
i understand what you are saying but haven't invested enough thought and time into the concept of writing the interpreter this way.
i purchased a book 3 weeks ago as is my intention of rewriting fbcadcam-macro this way in the near future.
i do want to continue working on coding it the way i'm doing it now, at least till i finish adding the string variable and concatenation operator.
i am very close to completing this goal. in the process of adding the string variable over the last few weeks, i have discovered and corrected many mistakes that existed in my previous version of fbcadcam-macro (without strings). after i have completed this one last thing then i need to beta test the strings variable in fbcadcam. if all checks out, then i will give it go and rewrite fbcadcam-macro the way you suggest.
thank you fb community in advance for all your advise.
i understand what you are saying but haven't invested enough thought and time into the concept of writing the interpreter this way.
i purchased a book 3 weeks ago as is my intention of rewriting fbcadcam-macro this way in the near future.
i do want to continue working on coding it the way i'm doing it now, at least till i finish adding the string variable and concatenation operator.
i am very close to completing this goal. in the process of adding the string variable over the last few weeks, i have discovered and corrected many mistakes that existed in my previous version of fbcadcam-macro (without strings). after i have completed this one last thing then i need to beta test the strings variable in fbcadcam. if all checks out, then i will give it go and rewrite fbcadcam-macro the way you suggest.
thank you fb community in advance for all your advise.
Re: fbcadcam-macro
Strings with concatenation ( +, & ) should be working now.
http://fbcadcam.org/fbcadcam-macro/fbca ... ngs-10.bas
http://fbcadcam.org/fbcadcam-macro/fbca ... ngs-10.bas
Re: fbcadcam-macro
I added my latest modifications of fbcadcam-macro (with strings) to fbcadcam and did a few tests:
For example I ran the following script to plot text into fbcadcam drawing.
dim as integer i
for i = 1 to 26
text 10,i*20,5,10,chr(i+64)
next
In an effort to document fbcadcam-macro I have updated my User's Guide. Take a peek if you like but there is a lot of documentation pending. I will try to link to the fb wiki as much as possible.
from about half way down the page to the bottom of the page is a description or fbcadcam-macro's usage.
http://fbcadcam.com/fbcadcam_users_guide.html
For example I ran the following script to plot text into fbcadcam drawing.
dim as integer i
for i = 1 to 26
text 10,i*20,5,10,chr(i+64)
next
In an effort to document fbcadcam-macro I have updated my User's Guide. Take a peek if you like but there is a lot of documentation pending. I will try to link to the fb wiki as much as possible.
from about half way down the page to the bottom of the page is a description or fbcadcam-macro's usage.
http://fbcadcam.com/fbcadcam_users_guide.html