Pliant talk forum

Pliant talk forum

Discussion: On the Pliant parsing mechanism

Message posted by marcus on 2002/05/31 21:19:23
I am currently studying/reviewing the documentation regarding the Pliant parsing
mechanism.

I have tried to add a new operator, called .myand., based on the source code
provided in the int.pli module. However, my program does not compile.

The code is

function '.myand.' a b -> r
  arg uInt a b r
  r:= a .and. b

operator '.myand.' 260h 1 1
      
function test
  if 1 .myand. 1
    console "Yes"
  else
    console "No"

test

My idea is to add a simple .page sample code which illustrates the idea to the
reader.

Please advise
Message posted by marcus on 2002/05/31 22:10:07
Hubert or Patrice,

Could you post here a line-by-line explanation of the the code for one of 
those parser filters, e.g., parse_bin, so that I can have a better idea of 
the whole process? And also an explanation of that piece of code that normal
 follow a parser filter, e.g., 

gvar ParserFilter bin_filter
bin_filter function :> the_function parse_bin ParserContext Str Address
constant 'pliant parser basic types' bin_filter
export 'pliant parser basic types'

Message posted by maybe Hubert Tonneau on 2002/06/01 09:25:09
Here is a working version of your sample:

module "/pliant/language/compiler.pli"
module "/pliant/language/parser.pli"

function '.myand.' a b -> r
  arg uInt a b r
  r:= a .and. b

operator '.myand.' 260h 1 1
      
function test
  if (1 .myand. 1)=2
    console "Yes"
  else
    console "No"

test
Message posted by maybe Hubert Tonneau on 2002/06/01 09:31:39
The general idea of the parser is that there are scanning functions that
recognize character sequences in the source code, and build tokens as
a result, and move the scanning cursor forward.

Now, the list of tokens is folded to a tree thanks to operators.
These are called according the the priority rules and will do what folding
they want. Most operators belong to well know classes of operator that
pick either none, one or all arguments on the left, and either none, one or
all on the right.

When write 'operator' instruction in your code, you are using the high end
service of Pliant that will build both a scanner function and a standard
operator as a result. It's defined in /pliant/language/parser/extend.pli
Message posted by maybe Hubert Tonneau on 2002/06/01 12:15:15
# Any parser filter (a parser filter is responsible for recognizing a
# character sequence in the source code, building the recognized item and
# forwarding the cursor) is an object with type 'ParserFilter'
gvar ParserFilter bin_filter

# The 'function' field in the 'ParserFilter' object must be set to point
# the actual parsing function. Of course, the prototype of such a function
# is well defined.
bin_filter function :> the_function parse_bin ParserContext Str Address

# All parser filters are ordered, and the order. The reason is that
# in a sequence '123h', the default integer filter will recognize '123'
# end the hex filter will recognize '123h', so we must be sure to call
# the hex filter first.
# The order is specified the following way:
# the 'pliant parser sections' global variable is a list of strings.
# the list will be scanned, and for each item, it will be used as a key
# in the Pliant global compiler dictionary to find various elements.
# The avantage of such a mechanism (as opposed to storing all parsers
# in a simple list) are:
# . the module inclusion mechanism will apply (a parser filter belonging to
#   a module you have not included will be ignore while scanning your module)
# . it's easier to insert a new parser filter at the right position (just
#   give it the name of the right class.
# If you want to see the name of various parser filter existing classes, search
# for 'C_parser_section' instrucations in /pliant/language/startup/startup.c:
# the 'C_parser_section' is used to fill the 'pliant parser sections' list
# at Pliant initialization time.
# So, the following line is recording the new 'ParserFilter' object as
# 'pliant parser basic types' in the Pliant global dictionary.
constant 'pliant parser basic types' bin_filter

# And finally, we export the new definition, so that it will now be used
# by any module including this one.
export 'pliant parser basic types'
Message posted by maybe Marcus on 2002/06/02 19:33:42
The parser filter prototype has a 'parameter' argument which is not used in
those parser filters in int.pli. 

Why is it used for?
Could you give me a reference of another parser filter which uses this para-
meter?

Thanks.
Message posted by maybe Hubert Tonneau on 2002/06/02 20:14:16
> The parser filter prototype has a 'parameter' argument which is not used in
> those parser filters in int.pli

It is used mainly in the C part of Pliant.
As I told before many parsing and operator functions look roughly the same,
so this parameter enable to have general ones that receive the details through
this parameter.

Think about as a call back function in C.
Generaly, the last argument will be (void *).

Message posted by maybe Marcus on 2002/06/02 21:17:51
Regarding that sample code mentioned earlier in this discussion, namely, the 
one involving the creation of a new operator, the function works when compiled
as a .pli. But if I try it as a .page program, it does not work.

Debug level 2 does not report any error when compiling the .pli version of
the code.

Below I quote the program and the respectice error message:

module "/pliant/language/compiler.pli" 
module "/pliant/language/parser.pli" 

function '.myand.' a b -> r
  arg uInt a b r
  r:= a .and. b

operator '.myand.' 260h 1 1

function test
  if (11 .myand. 11)=2
    text "Yes"
  else
    text "No"

test

------------------------------------------
There is a bug in the dynamic page /temp/t1.html. 

Failed to parse token .myand. 11)=2 (46)
  parse /temp/t1.page 9 10
  module /temp/t1.page
  service HTTP request

Message posted by maybe Hubert Tonneau on 2002/06/03 07:06:54
> the function works when compiled as a .pli. But if I try it as a .page program,
> it does not work.

Pliant compiler is doing parse, compile, then execute, then parse, compile,
then execute, etc
while compiling a module.
The compile, execute sequence is performed each time a full sequence has been
parsed (the next sequence is starting on a not idented new line, not starting
with a dual keyword (things like 'else'))

Now, when compiling a .page, the overall content is embedded in a single
function (a compiled .page is truely a function), so there will be a single
parse compile execute sequence. As a result, when the parser reaches your
new '.myand.' operator, the 'operator' instruction declaring it has not been
executed yet.
Message posted by maybe Marcus on 2002/06/03 18:39:13
Regarding the section 'pseudo parser filters' of the original 
pliant/language/parser/extend.page document, it mentions about 
those pseudo filters to parse expressions involving indentation (or {}).

Could you inform me where in the Pliant source I could find that code. I mean,
where those functions are used (I know they are defined in engine.c).

Thanks.


Message posted by maybe Hubert Tonneau on 2002/06/03 19:23:03
These functions are not called directly by other functions: they are recorded
in the parser filters pseudo list (as specified earlier, truely a list of strings,
each string beeing used as an entry to the general dictionary), so are called
from 'ParserContext_parse_one_token' which is scanning the pseudo list and
calling various parser filters.