fbcadcam-macro

User projects written in or related to FreeBASIC.
owen
Posts: 512
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: fbcadcam-macro

Postby owen » Oct 04, 2017 23:21

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.
owen
Posts: 512
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: fbcadcam-macro

Postby owen » Oct 04, 2017 23:35

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.
dafhi
Posts: 1238
Joined: Jun 04, 2005 9:51

Re: fbcadcam-macro

Postby dafhi » Oct 04, 2017 23:42

imnsho everyone should learn oop if the language supports it
owen
Posts: 512
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: fbcadcam-macro

Postby owen » Oct 04, 2017 23:57

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)
dafhi
Posts: 1238
Joined: Jun 04, 2005 9:51

Re: fbcadcam-macro

Postby dafhi » Oct 05, 2017 10:52

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
owen
Posts: 512
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: fbcadcam-macro

Postby owen » Oct 05, 2017 13:03

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
dafhi
Posts: 1238
Joined: Jun 04, 2005 9:51

Re: fbcadcam-macro

Postby dafhi » Oct 06, 2017 3:22

you don't have to oo the whole thing!

congrats on being able to keep track of all that
paul doe
Posts: 915
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: fbcadcam-macro

Postby paul doe » Oct 06, 2017 16:27

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:

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



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')

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()



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
Last edited by paul doe on Oct 06, 2017 21:49, edited 2 times in total.
owen
Posts: 512
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: fbcadcam-macro

Postby owen » Oct 06, 2017 16:59

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.
Image

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.
owen
Posts: 512
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: fbcadcam-macro

Postby owen » Oct 07, 2017 2:40

Strings with concatenation ( +, & ) should be working now.

http://fbcadcam.org/fbcadcam-macro/fbca ... ngs-10.bas
owen
Posts: 512
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: fbcadcam-macro

Postby owen » Oct 08, 2017 6:02

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

Return to “Projects”

Who is online

Users browsing this forum: No registered users and 0 guests