Skip to content
This repository has been archived by the owner on Feb 3, 2021. It is now read-only.

Commit

Permalink
Add some comments and documentation to hll-grammar.pir .
Browse files Browse the repository at this point in the history
  • Loading branch information
pmichaud committed Oct 19, 2009
1 parent 532f8aa commit eb3ae12
Showing 1 changed file with 96 additions and 1 deletion.
97 changes: 96 additions & 1 deletion src/cheats/hll-grammar.pir
@@ -1,3 +1,16 @@
# Copyright (C) 2009 Patrick R. Michaud

=head1 TITLE

src/cheats/hll-grammar.pir -- Additional HLL::Grammar methods

=head2 Methods

=over 4

=cut


.include 'cclass.pasm'

.sub '' :load :init
Expand All @@ -9,22 +22,65 @@

.namespace ['HLL';'Grammar']

=item O(spec [, save])

This subrule attaches operator precedence information to
a match object (such as an operator token). A typical
invocation for the subrule might be:

token infix:sym<+> { <sym> <O( q{ %additive, :pirop<add> } )> }

This says to add all of the attribute of the C<%addition> hash
(described below) and a C<pirop> entry into the match object
returned by the C<< infix:sym<+> >> token (as the C<O> named
capture). Note that this is a alphabetic 'O", not a digit zero.
Currently the C<O> subrule accepts a string argument describing
the hash to be stored. (Note the C< q{ ... } > above. Eventually
it may be possible to omit the 'q' such that an actual (constant)
hash constructor is passed as an argument to C<O>.
The hash built via the string argument to C<O> is cached, so that
subsequent parses of the same token re-use the hash built from
previous parses of the token, rather than building a new hash
on each invocation.
The C<save> argument is used to build "hash" aggregates that can
be referred to by subsequent calls to C<O>. For example,
NQP::Grammar.O(':prec<t=>, :assoc<left>', '%additive' );
specifies the values to be associated with later references to
"%additive". Eventually it will likely be possible to use true
hashes from a package namespace, but this works for now.
Currently the only pairs recognized have the form C< :pair >,
C< :!pair >, and C<< :pair<strval> >>.
=cut
.sub 'O' :method
.param string spec
.param string save :optional
.param int has_save :opt_flag
# First, get the hash cache. Right now we have one
# cache for all grammars; eventually we may need a way to
# separate them out by cursor type.
.local pmc ohash
ohash = get_global '%!ohash'
unless null ohash goto have_ohash
ohash = new ['Hash']
set_global '%!ohash', ohash
have_ohash:
# See if we've already created a Hash for the current
# specification string -- if so, use that.
.local pmc hash
hash = ohash[spec]
unless null hash goto hash_done

# Otherwise, we need to build a new one.
hash = new ['Hash']
.local int pos, eos
pos = 0
Expand All @@ -35,6 +91,9 @@
$S0 = substr spec, pos, 1
if $S0 == ',' goto spec_comma
if $S0 == ':' goto spec_pair

# If whatever we found doesn't start with a colon, treat it
# as a lookup of a previously saved hash to be merged in.
.local string lookup
.local int lpos
lpos = find_cclass .CCLASS_WHITESPACE, spec, pos, eos
Expand All @@ -53,24 +112,36 @@
lhash_done:
pos = lpos
goto spec_loop

# We just ignore commas between elements for now.
spec_comma:
inc pos
goto spec_loop

# If we see a colon, then we want to parse whatever
# comes next like a pair.
spec_pair:
# eat colon
inc pos
.local string name
.local pmc value
value = new ['Boolean']

# If the pair is of the form :!name, then reverse the value
# and skip the colon.
$S0 = substr spec, pos, 1
$I0 = iseq $S0, '!'
pos += $I0
$I0 = not $I0
value = $I0

# Get the name of the pair.
lpos = find_not_cclass .CCLASS_WORD, spec, pos, eos
$I0 = lpos - pos
name = substr spec, pos, $I0
pos = lpos

# Look for a <...> that follows.
$S0 = substr spec, pos, 1
unless $S0 == '<' goto have_value
inc pos
Expand All @@ -80,27 +151,40 @@
value = box $S0
pos = lpos + 1
have_value:
# Done processing the pair, store it in the hash.
hash[name] = value
goto spec_loop
spec_done:
# Done processing the spec string, cache the hash for later.
ohash[spec] = hash
hash_done:

# If we've been called as a subrule, then build a pass-cursor
# to indicate success and set the hash as the subrule's match object.
if has_save goto save_hash
($P0, $I0) = self.'!cursor_start'()
$P0.'!cursor_pass'($I0, '')
setattribute $P0, '$!match', hash
.return ($P0)

# save the hash under a new entry
save_hash:
ohash[save] = hash
.return ()
.return (self)

err_lookup:
self.'panic'('Unknown operator precedence specification "', lookup, '"')
.end


=item panic([args :slurpy])

Throw an exception at the current cursor location. If the message
doesn't end with a newline, also output the line number and offset
of the match.
=cut
.sub 'panic' :method
.param pmc args :slurpy
Expand All @@ -125,3 +209,14 @@
die message
.end
=back
=cut
# Local Variables:
# mode: pir
# fill-column: 100
# End:
# vim: expandtab shiftwidth=4 ft=pir:

0 comments on commit eb3ae12

Please sign in to comment.