FreeBASIC version BYACC (compiler compiler)

User projects written in or related to FreeBASIC.
AGS
Posts: 1284
Joined: Sep 25, 2007 0:26
Location: the Netherlands

FreeBASIC version BYACC (compiler compiler)

Postby AGS » Jan 09, 2010 5:13

YACC/FB (Yet Another Compiler Compiler/FreeBASIC version)

I've downloaded BYACC and rewrote parts of routines/added some routines to BYACC so BYACC produces FreeBASIC syntax.

BYACC or Berkeley YACC is a public domain implementation of
AT&T YACC. YACC is a compiler compiler that, given an input
grammar + semantic actions, builds a LALR parser coded in C code.
It does not build a lexer (the programmer must supply one).

You can find a YACC manual here

http://dinosaur.compilertools.net/yacc/index.html

Extent of rewrite

No attempt has been made to rewrite the entire BYACC source code. Only
the parts that have to do with the output of C code have been rewritten.
The files that have (partly) been rewritten are:
- output.c;
- reader.c;
- skeleton.c

When running yacc the content of skeleton.c is combined with
the user code yielding source code that can be compiled using the
FreeBASIC compiler. For further details see YACC manual.

INSTALLATION

Provided are the YACC/FB source, a WIN32 binary and a copy of the
YACC manual.

A package containing the above can be downloaded from
http://www.sarmardar.nl/FreeBASIC/byacc_fb_02.zip


DIFFERENCES BETWEEN BYACC AND BYACC/FB

There are a some things you need to keep in mind when working with BYACC/FB.

- semantic actions

Code MUST be enclosed by { }. In some versions of YACC the use of
{ and } is not mandatory but BYACC/FB expects { at the start of
a semantic action and } at the end of a semantic action.


- comments

Comments within the FreeBASIC - only parts of the input file can contain
FreeBASIC style comments. In the parts of the input file that are
processed by YACC use of C style comments is
mandatory (example: /* some_comment */).

This means you can use FB style comments
- within semantic actions;
- within the %{ ... %} block;
- within the block after the final %%.

- command line options
The option -r does not produce usable code. The option has not been dropped (yet) from the YACC executable but running BYACC/FB with the option -r will produce non - usable output.

FINAL REMARKS

The shared variables found in BYACC\FB have been copied from the orginal C code. Why BYACC uses so many shared variables is unclear. More 'modern' implementations of LALR parsers (LEMON/BISON/others) tend to use less shared variables (if any). I'm hoping to rewrite BYACC\FB so it will not rely as much on Shared variables as it does now.

This is the very first release of BYACC/FB so you may expect bugs
in either BYACC/FB or the code it produces.

Below you find an example of an input file (a simple expression grammar). It expects it's input to be in "inin.txt" (this is hard coded).
Possible content of inin.txt (last line must have a newline at the end):

8 & 8 | 9 * 55
8 * ((7 & 2))
5 + 4 * 6 / 8
8 * 6 + 1


If the example is saved as expression.y then the following command line will yield a file called expression.bas (due to the -v option a description of the states produced will be written to y.output).

fbyacc -o expression.bas -v expression.y

Now you can run the fb compiler like so

fbc expression.bas

which will produce an expression parser (it will expect input to be in inin.txt).

Code: Select all

%{
#include "crt/stdio.bi"
#include "crt/ctype.bi"
#include "crt/time.bi"

Dim Shared regs(0 To 26) As Integer
Dim Shared base As Integer

%}

%start list

%token DIGIT
%token LETTER

%left "|"
%left "&"
%left "+" "-"
%left "*" "/" "%"
%left UMINUS   /* supplies precedence for unary minus */

%% /* beginning of rules section */

list  :  /* empty */
      |  list stat "\n"
      |  list error "\n"
            {  yyerrok }
      ;

stat  :  expr
            {  Print Using "#####";$1}
      |  LETTER "=" expr
            {  regs($1) = $3 }
      ;

expr  :  "(" expr ")"
            {  $$ = $2 }
      |  expr "+" expr
            {  $$ = $1 + $3 }
      |  expr "-" expr
            {  $$ = $1 - $3 }
      |  expr "*" expr
            {  $$ = $1 * $3 }
      |  expr "/" expr
            {  $$ = $1 / $3 }
      |  expr "%" expr
            {  $$ = $1 Mod $3 }
      |  expr "&" expr
            {  $$ = $1 And $3 }
      |  expr "|" expr
            {  $$ = $1 Or $3 }
      |  "-" expr %prec UMINUS
            {  $$ = - $2 }
      |  LETTER
            {  $$ = regs($1) }
      |  number
      ;

number:  DIGIT
         {  $$ = $1
            If ($1 = 0) Then
              base = 8
            Else
              base = 10
            End If
            /' comment '/
         }
      |  number DIGIT
         {  $$ = base * $1 + $2 }
      ;

%% /' start of programs '/

Dim Shared in_hndl As Integer

Sub main ()

    in_hndl = FreeFile()
   
    Open "inin.txt" For Input As #in_hndl
   
    Var t1 = clock()
    Do Until(EOF(in_hndl))
      yyparse()
    Loop
    Var t2 = clock()
    Print Using "Start = ###########";t1
    Print Using "End   = ###########";t2
    Close #in_hndl      

End Sub

Sub yyerror_(ByVal s As ZString Ptr)   
   Print *s
End Sub

#define ULA 97  'Asc("a")
#define ULZ 122 'Asc("z")
#define UD0 48  'Asc("0")
#define UD9 57  'Asc("9")
#define USPC 32 'Asc(" ")

Function yylex() As Integer

      /' lexical analysis routine '/
      /' returns LETTER for a lower case letter, yylval = 0 through 25 '/
      /' return DIGIT for a digit, yylval = 0 through 9 '/
      /' all other characters are returned immediately '/

      Dim c As UByte
     
      Get #in_hndl,,c
      While (c = USPC)
        Get #in_hndl,,c
      Wend     
     
     
      'C is not whitespace
      Select Case As Const(c)
      Case ULA To ULZ
        yylval = c - ULA            
        Return LETTER
      Case UD0 To UD9
        yylval = c - UD0
        Return DIGIT
      End Select
     
      Return(c)
     
End Function

main()
Last edited by AGS on Jan 16, 2010 16:27, edited 3 times in total.
AGS
Posts: 1284
Joined: Sep 25, 2007 0:26
Location: the Netherlands

Postby AGS » Jan 09, 2010 8:40

To get a good impression of what a compiler compiler is capable of it helps to take a look at languages built with the compiler compiler. So here are a couple of links to interesting projects built with some YACC clone (BYACC is a version of YACC as are BISON and LEMON).

First and foremost, the SDCC (Small Device C Compiler).
Link (links directly to grammar):
http://sdcc.svn.sourceforge.net/viewvc/ ... iew=markup

Then there is PCC, the Portable C Compiler.
The C grammar: http://pcc.zentus.com/cgi-bin/cvsweb.cg ... xt%2Fplain

The preprocessor grammar:
http://pcc.zentus.com/cgi-bin/cvsweb.cg ... xt%2Fplain

More BASIC oriented are

Yabasic
Source available from http://www.yabasic.de/download/yabasic-2.763.tar.gz (look for yabasic.bison for grammar).

Lemick
Some screenshots
http://lemick.sourceforge.net/cexamples.html

You can download it from
http://sourceforge.net/projects/lemick/ ... z/download

The file lemick.y (to be found in /src/lemc/) contains a BASIC like grammar of the language (think 'FreeBASIC with OOP').

Mole BASIC
This is a version of BASIC with line numbering.
http://www.xs4all.nl/~merty/mole/MOLE-Basic_0.7.tar.gz
File to look for: basic.y
McLovin
Posts: 82
Joined: Oct 21, 2008 1:15
Contact:

Postby McLovin » Jan 09, 2010 14:38

OMG AGS, I am working on a very similar project! Over Christmas I was porting LEMON parser to FB but got to the stage of building the tables and then I got a little lost in the C code. I am keeping most of the LEMON port but I am now combining it with BYacc code to create the tables. The resulting grammar syntax will be a combination fo all the good things from both LEMON and BYACC. The ultimate goal will be to then to model the FB grammar and output using the new parser generator. Cool little project that has my brain fascinated again.
aurelVZAB
Posts: 342
Joined: Jul 02, 2008 14:55
Location: Croatia
Contact:

Postby aurelVZAB » Jan 09, 2010 19:09

Hi guys...
I will ask one stupid question( becose i'm not sure if queation is right !?)
I never use any kind of grammar code becose i dont know how to use them.
And how i can create languge if i have grammar?
As i see grammar is not source code which i can compile to something
concrete?
AGS
Posts: 1284
Joined: Sep 25, 2007 0:26
Location: the Netherlands

Postby AGS » Jan 10, 2010 11:34

@McLovin

If you need some help porting Lemon just let me know.

@aurelVZAB

BYACC generates a LALR(1) parser. It takes the grammar you provide and turns it into something that's described here

Turning the grammar into a LALR(1) parser consists (largely) of creating a bunch of arrays. The source code you get after running

Code: Select all

fbyacc -o expression.bas expression.y


consists of:
- some macros;
- a bunch of arrays (initialized,static);
- a routine called yyparse that does the actual parsing;
- user defined code.

The user defined code consists of the following routines.

main
Keeps the parsing going by calling yyparse in a loop until EOF occurs (=no more input).

yylex
Returns tokens one token at a time. Gets called by yyparse.

The pieces of code between {} are what gets executed when the parser has recognized an entire rule. Example:

if
exp: exp * exp succeeds (in case input contains the line 9 * 10 or something similar) then the code
$$ = $1 * $3 gets executed. $1 refers to 9 and $3 refers to 10 ($2 = *).

$1 and $3 are on the value stack and after running fbyacc the above gets translated into this:
yyval = yyvsp[-2] * yyvsp[0]

A thorough description of the way LALR parsing works can be found here.

It deals with Bison which is not BYACC but it's close enough (Bison is an open source implementation of YACC).

I think you know top down, recursive descent parsing where the rules of the grammar are (more or less) represented by routines.

In (for example) FreeBASIC parsing starts with the top rule which is a routine called cProgram.

Code: Select all

function cProgram( ) as integer
 
     do
       if( cLine( ) = FALSE ) then
          exit do
       end if
     loop



If you want to see YACC like parsing 'in action' download the package
ultragram

http://www.ultragram.com/Download.aspx

The code producing part of ultragram will not work but testing of grammars by use of the built - in interpreter never stops working. I use ultragram myself every now and then to see if a certain grammar rule 'works'.
aston
Posts: 16
Joined: Nov 29, 2009 20:32

Postby aston » Jan 10, 2010 15:07

Thanks AGS it sounds very complicated ufff...
I will see...
AGS
Posts: 1284
Joined: Sep 25, 2007 0:26
Location: the Netherlands

Postby AGS » Jan 16, 2010 16:18

Update 16-01-2010
--------------------------

A new version is available for download.

In the latest version YYSTYPE can be used so you now can utilize the %union, %type and %token constructs.

To define YYSTYPE as a union use something like this (example):

Code: Select all

%{

Type first_type
  Dim a As Integer
  Dim b As Double
End Type

Type second_type
  Dim c As String
  Dim d As Double
End Type
%}

%union {
  Dim type_one As first_type
  Dim type_two As second_type
}

%%


The %union will end up in the source code as

Code: Select all

Union YYSTYPE
   Dim type_one As first_type
   Dim type_two As second_type
End Union


Further information on the use of %type and %token can be found in the manual.

Remark:
BYACC does not do a lot of checking on the union declaration (no syntax check). The FB compiler compiles the resulting code and the FBC will check the union declaration for syntax errors.

Next update I'll post a bigger example showing how to build a small BASIC interpreter using fbyacc.
AGS
Posts: 1284
Joined: Sep 25, 2007 0:26
Location: the Netherlands

Postby AGS » Nov 18, 2010 23:39

I'm going to be replacing byacc for freebasic with dparser for freebasic within a couple of weeks.
owen
Posts: 554
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Postby owen » Nov 19, 2010 0:16

ok, so not having ever heard of the term 'compiler compiler' i take a peek at your suggestion (look at bison for an example) and first off is the statement 'You need to be fluent in C or C++ programming in order to use Bison'

so what your doing here is making something for the freebasic community who might not be fluent in c or c++ ?
AGS
Posts: 1284
Joined: Sep 25, 2007 0:26
Location: the Netherlands

Postby AGS » Nov 21, 2010 18:04

I am basically making dparser produce basic code (not C). So no knowledge of C is required to use dparser.

I've already done a lot of the translation of the code producing part of dparser.

To give you an idea of the code generated by dparser (I think it's more readable than what byacc produces) I give you an example grammar that can recognize the sentence 'hello world'.

input (grammar)
{
type My_ParseNode
dim value as integer
end type

#define D_ParseNode_User My_ParseNode
}

start : 'hello world';


The part between the { } gets copied verbatim to the resulting file. My_ParseNode can be used to add info to the the parse nodes constructed by dparse. You must define it
(even when you are not using it).

The first rule defined in the grammar (in the above case it's the rule named start) is used as the starting rule of the grammar.

Given the above grammar dparser (freebasic version) produced the following freebasic code

Code: Select all

/'
  Generated by Make DParser Version 1.26
  Available at http://dparser.sf.net
'/

#line 1 "hello_world.g"

type My_ParseNode
  dim value as integer
end type

#define D_ParseNode_User My_ParseNode

#line 15 "hello_world.bas"
#include "dparse.bi"

dim d_reduction_0_gram as D_Reduction = (1, 0, NULL, NULL, 0, 0, 0, 0, -1, 0, NULL)
dim d_reduction_1_gram as D_Reduction = (1, 1, NULL, NULL, 0, 0, 0, 0, 0, 0, NULL)
dim d_shift_0_gram as D_Shift = (2, 1, 0, 0, 0, 0, NULL)

dim d_accepts_diff_0_0_gram(0 to ...) as D_Shift ptr = {0}
dim d_accepts_diff_0_gram(0 to ...) as D_Shift ptr ptr = {_
d_accepts_diff_0_0_gram _
}

dim d_scanner_0_0_0_gram(SCANNER_BLOCK_SIZE - 1) as unsigned byte  = {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 _
}

dim d_scanner_0_0_1_gram(SCANNER_BLOCK_SIZE - 1) as unsigned byte  = {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 _
}

dim d_scanner_0_1_1_gram(SCANNER_BLOCK_SIZE - 1) as unsigned byte  = {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 _
}

dim d_scanner_0_2_1_gram(SCANNER_BLOCK_SIZE - 1) as unsigned byte  = {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 _
}

dim d_scanner_0_3_1_gram(SCANNER_BLOCK_SIZE - 1) as unsigned byte  = {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 _
}

dim d_scanner_0_4_1_gram(SCANNER_BLOCK_SIZE - 1) as unsigned byte  = {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 _
}

dim d_scanner_0_5_0_gram(SCANNER_BLOCK_SIZE - 1) as unsigned byte  = {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 _
}

dim d_scanner_0_6_1_gram(SCANNER_BLOCK_SIZE - 1) as unsigned byte  = {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0 _
}

dim d_scanner_0_7_1_gram(SCANNER_BLOCK_SIZE - 1) as unsigned byte  = {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 _
}

dim d_scanner_0_8_1_gram(SCANNER_BLOCK_SIZE - 1) as unsigned byte  = {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 _
}

dim d_scanner_0_9_1_gram(SCANNER_BLOCK_SIZE - 1) as unsigned byte  = {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 _
}

dim d_scanner_0_10_1_gram(SCANNER_BLOCK_SIZE - 1) as unsigned byte  = {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  _
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 _
}

dim d_shift_0_11_gram(0 to ...) as D_Shift ptr = {@d_shift_0_gram,_
NULL _
}

dim d_scanner_0_gram(0 to 12 - 1) as SB_uint8 = {_
(NULL, {d_scanner_0_0_0_gram, d_scanner_0_0_1_gram _
 , d_scanner_0_0_0_gram, d_scanner_0_0_0_gram}),_
(NULL, {d_scanner_0_0_0_gram, d_scanner_0_1_1_gram _
 , d_scanner_0_0_0_gram, d_scanner_0_0_0_gram}),_
(NULL, {d_scanner_0_0_0_gram, d_scanner_0_2_1_gram _
 , d_scanner_0_0_0_gram, d_scanner_0_0_0_gram}),_
(NULL, {d_scanner_0_0_0_gram, d_scanner_0_3_1_gram _
 , d_scanner_0_0_0_gram, d_scanner_0_0_0_gram}),_
(NULL, {d_scanner_0_0_0_gram, d_scanner_0_4_1_gram _
 , d_scanner_0_0_0_gram, d_scanner_0_0_0_gram}),_
(NULL, {d_scanner_0_5_0_gram, d_scanner_0_0_0_gram _
 , d_scanner_0_0_0_gram, d_scanner_0_0_0_gram}),_
(NULL, {d_scanner_0_0_0_gram, d_scanner_0_6_1_gram _
 , d_scanner_0_0_0_gram, d_scanner_0_0_0_gram}),_
(NULL, {d_scanner_0_0_0_gram, d_scanner_0_7_1_gram _
 , d_scanner_0_0_0_gram, d_scanner_0_0_0_gram}),_
(NULL, {d_scanner_0_0_0_gram, d_scanner_0_8_1_gram _
 , d_scanner_0_0_0_gram, d_scanner_0_0_0_gram}),_
(NULL, {d_scanner_0_0_0_gram, d_scanner_0_9_1_gram _
 , d_scanner_0_0_0_gram, d_scanner_0_0_0_gram}),_
(NULL, {d_scanner_0_0_0_gram, d_scanner_0_10_1_gram _
 , d_scanner_0_0_0_gram, d_scanner_0_0_0_gram}),_
(d_shift_0_11_gram, {d_scanner_0_0_0_gram, d_scanner_0_0_0_gram _
 , d_scanner_0_0_0_gram, d_scanner_0_0_0_gram}) _
}

dim d_goto_valid_0_gram(0 to ...) as ubyte = {_
&h6}
dim d_reductions_1_gram(0 to ...) as D_Reduction ptr = {@d_reduction_1_gram _
}
dim d_gotos_gram(0 to 2 - 1) as ushort = {_
3,2}


dim d_states_gram(0 to ...) as D_State = {_
(d_goto_valid_0_gram, 1, {0, NULL}, {0, NULL}, {0, NULL}, 1, NULL, cast(any ptr,d_scanner_0_gram), sizeof(unsigned byte) , 0, D_SCAN_LONGEST, NULL, NULL, -1), _
(NULL, -2147483647, {1, d_reductions_1_gram}, {0, NULL}, {0, NULL}, 0, NULL, NULL, sizeof(unsigned byte) , 0, D_SCAN_ALL, NULL, NULL, -1), _
(NULL, -2147483647, {0, NULL}, {0, NULL}, {0, NULL}, 0, NULL, NULL, sizeof(unsigned byte) , 1, D_SCAN_ALL, NULL, NULL, -1)_
}

dim d_symbols_gram(0 to ...) as D_Symbol = {_
(D_SYMBOL_EBNF, @"0 Start", 7, -1),_
(D_SYMBOL_NTERM, @"start", 5, -1),_
(D_SYMBOL_STRING, @"hello world", 11) _
}

dim parser_tables_gram as D_ParserTables = (_
3, d_states_gram, d_gotos_gram, 0, 3, d_symbols_gram, NULL, 0, NULL, 0)



As you can see the grammar reappears at the end of the output (d_symbols_gram).

You can use the file hello_world.bas to parse some text

(assuming the code produced by dparser is in "hello_world.bas")

Code: Select all

#include "hello_world.bas"

dim p as D_Parser ptr
dim p_node as D_ParseNode ptr
dim buffer as string = "hello world"

p = new_D_Parser(@parser_tables_gram,1024)
'save the parsetree (dparser will create it 'automagically')
p->save_parse_tree = 1
pn = dparse(p, strptr(buffer), len(buffer))
'do something with pn


If no syntax errors were detected in buffer (indicated by p->syntax_errors = 0) the parse tree has been created and can be used (pn is at the root of the tree).

I'm not finished yet with the FB port of dparser. Thus far I have not come across big problems porting the code producing part of dparser to freebasic (and I don't think I'll run into any either).

dparser comes with a couple of grammars of which the C grammar (and the python grammar) are the most interesting.

Ultimately I want to be able to use dparser to parse:
- FreeBASIC code (pretty printing/source code 'changing' purposes);
- C code (semi - automagically translating C code to FB);
- other programming languages.

Return to “Projects”

Who is online

Users browsing this forum: No registered users and 5 guests