.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{ . if \nF \{ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Marpa::R2::Progress 3pm" .TH Marpa::R2::Progress 3pm "2015-03-06" "perl v5.20.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Marpa::R2::Progress \- Progress reports on your parse .SH "About this document" .IX Header "About this document" This document describes the progress reports for Marpa's \s-1SLIF\s0 interface. These allow an application to know exactly where it is in the parse at any point. For parse locations of the user's choosing, progress reports list all the rules in play, and indicate the location at which the rule started, and how far into the rule parsing has progressed. .PP Progress reports are extremely useful in debugging grammars and the detailed example in this document is a debugging situation. Readers specifically interested in debugging a grammar should read the document on tracing problems before reading this document. .SH "Introduction to Earley items" .IX Header "Introduction to Earley items" To read the \&\f(CW\*(C`show_progress\*(C'\fR output, it is important to have a basic idea of what Earley items are, and of what the information in them means. Everything that the user needs to know is explained in this section. .SS "Dotted rules" .IX Subsection "Dotted rules" Marpa is based on Jay Earley's algorithm for parsing. The idea behind Earley's algorithm is that you can parse by building a table of rules and where you are in those rules. \&\*(L"Where\*(R" means two things: location in the rule relative to the rule's symbols, and location relative to the parse's input stream. .PP Let's look at an example of a rule in a context-free grammar. Here's the rule for assignment from the Perl distribution's \f(CW\*(C`perly.y\*(C'\fR .PP \&\f(CW\*(C`\ \ \ \ termbinop\ \->\ term\ ASSIGNOP\ term\*(C'\fR .PP \&\f(CW\*(C`ASSIGNOP\*(C'\fR is \f(CW\*(C`perly.y\*(C'\fR's internal name for the assignment operator. In plain Perl terms, this is the "\f(CW\*(C`=\*(C'\fR" character. .PP In parsing this rule, we can be at any of four possible locations. One location is at the beginning, before all of the symbols. The other three locations are immediately after each of the rule's three symbols. .PP Within a rule, position relative to the symbols of the rule is traditionally indicated with a dot. In fact, the symbol-relative rule position is very often called the \fBdot location\fR. Taken as a pair, a rule and a dot location are called a \fBdotted rule\fR. .PP Here's our rule with a dot location indicated: .PP \&\f(CW\*(C`\ \ \ \ termbinop\ \->\ X\ term\ ASSIGNOP\ term\*(C'\fR .PP The dot location in this dotted rule is at the beginning. A dot location at the beginning of a dotted rule means that we have not recognized any symbols in the rule yet. All we are doing is predicting that the rule will occur. A dotted rule with the dot before all of its symbols is called a \fBprediction\fR or a \fBpredicted rule\fR. .PP Here's another dotted rule: .PP \&\f(CW\*(C`\ \ \ \ termbinop\ \->\ term\ X\ ASSIGNOP\ term\*(C'\fR .PP In this dotted rule, we are saying we have seen a \f(CW\*(C`term\*(C'\fR, but have not yet recognized an \f(CW\*(C`ASSIGNOP\*(C'\fR. .PP There's another special kind of dotted rule, a completion. A \fBcompletion\fR (also called a \fBcompleted rule\fR) is a dotted rule with the dot after all of the symbols. Here is the completion for the rule that we have been using as an example: .PP \&\f(CW\*(C`\ \ \ \ termbinop\ \->\ term\ ASSIGNOP\ term\ X\*(C'\fR .PP A completion indicates that a rule has been fully recognized. .SS "Earley items" .IX Subsection "Earley items" The dotted rules contain all but one piece of the information that Marpa needs to track. The missing piece is the second of the two \*(L"wheres\*(R": where in the input stream. To associate input stream location and dotted rules, Marpa uses what are now called Earley items. .PP A convenient way to think of an \fBEarley item\fR is as a triple, or 3\-tuple, consisting of dotted rule, origin and current location. The \fBorigin\fR is the location in the input stream where the dotted rule starts. The \fBcurrent location\fR (also called the \fBdot location\fR) is the location in the input stream which corresponds to the dot position. .PP In Marpa terms, G1 location is location in terms of the G1 subgrammar's Earley sets. When the term \*(L"location\*(R" is used in this document, it means G1 location unless otherwise indicated. .PP A user often finds it much more convenient to think in terms of line and column position in the input stream, instead of G1 location. Every G1 location corresponds to a range of positions in the input stream. When the term \*(L"position\*(R" is used in this document, it means input stream position, unless otherwise indicated. .PP Two noteworthy consequences follow from the way in which origin and current G1 location are defined. First, if a dotted rule is a prediction, then origin and current location will always be the same. Second, the input stream location where a rule ends is not tracked unless the dotted rule is a completion. In other cases, an Earley item does not tell us if a rule will ever be completed, much less at which location. .SH "The problem" .IX Header "The problem" For this example of debugging, I have taken a very simple prototype of a string expression calculator and deliberately introduced a problem. I've commented out one of the correct rules: .PP .Vb 1 \& # ::= variable \*(Aq=\*(Aq .Ve .PP and replaced it with a altered one: .PP .Vb 1 \& ::= variable \*(Aq=\*(Aq expression .Ve .PP For those readers who like to look ahead (and I encourage you to be one of those readers) all of the code and outputs for this example are collected in the \*(L"Appendix\*(R". .PP This altered rule contains an mistake of the kind that is easy to make in actual practice. (In this case, a unlucky choice of naming conventions may have contributed.) The altered version will cause problems. In what follows, we'll pretend we don't already know where the problem is, and that in desk-checking the grammar our eye does not spot the mistake, so that we need to use the Marpa diagnostics and tracing facilities to \*(L"discover\*(R" it. .SH "The example" .IX Header "The example" The example we will use is a prototype string calculator. It's extremely simple, to make the example easy to follow. But it can be seen as a realistic example, if it is thought of as a very early stage in the incremental development of something useful. .PP .Vb 5 \& :default ::= action => ::array bless => ::lhs \& :start ::= statements \& statements ::= statement * \& statement ::= assignment | \& assignment ::= \*(Aqset\*(Aq variable \*(Aqto\*(Aq expression \& \& # This is a deliberate error in the grammar \& # The next line should be: \& # ::= variable \*(Aq=\*(Aq \& # I have changed the to which \& # will cause problems. \& ::= variable \*(Aq=\*(Aq expression \& \& expression ::= \& variable | string \& || \*(Aqstring\*(Aq \*(Aq(\*(Aq \*(Aq)\*(Aq \& || expression \*(Aq+\*(Aq expression \& ::= \& variable | number \& || \*(Aq+\*(Aq \& || \*(Aq*\*(Aq \& variable ~ [\ew]+ \& number ~ [\ed]+ \& string ~ [\*(Aq] [\*(Aq] \& ~ [^\*(Aq\ex{0A}\ex{0B}\ex{0C}\ex{0D}\ex{0085}\ex{2028}\ex{2029}]+ \& :discard ~ whitespace \& whitespace ~ [\es]+ .Ve .PP At this stage of developing our string calculator, we have assignment, variables, constants, concatenation and conversion of numerics. For numerics, we have assignment, variables, constants, multiplication and addition. .PP We decide that, since string expressions and variables are the \*(L"default\*(R", that in the grammar we'll make the symbol names for numeric assignment and expressions explicit: \&\f(CW\*(C`\*(C'\fR and \f(CW\*(C`\*(C'\fR. But since strings are the default, we decide to call our string expressions simply \f(CW\*(C`\*(C'\fR, and to call our string assignments simply \f(CW\*(C`\*(C'\fR. This seems like a good idea, but it is also likely to cause confusion. For the sake of our example we will pretend that it did. .SH "The error message" .IX Header "The error message" If we try the following input, .PP .Vb 1 \& my $test_input = \*(Aqa = 8675309 + 42 * 711\*(Aq; .Ve .PP we will get this error message, .PP .Vb 5 \& Error in SLIF parse: No lexemes accepted at line 1, column 18 \& Rejected lexeme #0: Lexer "L0"; \*(Aq*\*(Aq; value="*"; length = 1 \& * String before error: a = 8675309 + 42\es \& * The error was at line 1, column 18, and at character 0x002a \*(Aq*\*(Aq, ... \& * here: * 711 .Ve .PP The error message indicates that Marpa rejected the "\f(CW\*(C`*\*(C'\fR" operator. .SH "The value of the parse" .IX Header "The value of the parse" In debugging this issue, we'll look at the value of the parse first. The parse value differs from the other debugging aids we'll discuss. Every other debugging tool we will describe is always available, no matter how badly the parse failed. But if you have a problem parsing, you often won't get a parse value. .PP Our luck holds. Here's a dump of the parse value at the point of failure. It's a nice to way to see what Marpa thinks the parse was so far. .PP .Vb 10 \& \ebless( [ \& bless( [ \& bless( [ \& \*(Aqa\*(Aq, \& \*(Aq=\*(Aq, \& bless( [ \& bless( [ \& \*(Aq8675309\*(Aq \& ], \*(AqMy_Nodes::expression\*(Aq ), \& \*(Aq+\*(Aq, \& bless( [ \& \*(Aq42\*(Aq \& ], \*(AqMy_Nodes::expression\*(Aq ) \& ], \*(AqMy_Nodes::expression\*(Aq ) \& ], \*(AqMy_Nodes::numeric_assignment\*(Aq ) \& ], \*(AqMy_Nodes::statement\*(Aq ) \& ], \*(AqMy_Nodes::statements\*(Aq ); .Ve .PP If we were perceptive, we might spot the error here. Our parse is not quite right, and that shows up in the outer \f(CW\*(C`My_Nodes::expression\*(C'\fR \*(-- it should be \&\f(CW\*(C`My_Nodes::numeric_expression\*(C'\fR. We'll assume that we don't notice this. .PP In fact, in the following, we'll pretend we haven't seen the dump of the parse value. We can't always get a parse value, so we don't want to rely on it. .SH "Output from \fItrace_terminals()\fP" .IX Header "Output from trace_terminals()" You can rely on getting the output from \&\f(CW\*(C`trace_terminals\*(C'\fR, and it is a good next place to check. Typically, you will be interested in the last tokens to be accepted. Sometimes that information alone is enough to make it clear where the problem is. .PP The full \&\f(CW\*(C`trace_terminals\*(C'\fR output for this example is in the Appendix. We see that the recognizer accepts the input as far as the multiplication sign ("\f(CW\*(C`*\*(C'\fR\*(L"), which it rejects. In Marpa, a lexeme is \*(R"acceptable" if it fits the grammar and the input so far. A lexeme is rejected if it is not acceptable. .PP The last two lines of the \f(CW\*(C`trace_terminals\*(C'\fR output are: .PP .Vb 2 \& Lexer "L0" discarded lexeme L1c17: whitespace \& Lexer "L0" rejected lexeme L1c18: \*(Aq*\*(Aq; value="*" .Ve .PP A note in passing: Marpa shows the input string position of the tokens it accepts, discard and rejects. \&\f(CW\*(C`\*(C'\fR is supposed to be discarded and that was what happened at line 1, column 17. But the \f(CW\*(Aq*\*(Aq\fR that was next in the input was rejected, and that was not supposed to happen. .SH "Output from \fIshow_progress()\fP" .IX Header "Output from show_progress()" Marpa's most powerful tool for debugging grammars is its progress report, which shows the Earley items being worked on. In the Appendix, progress reports for the entire parse are shown. Our example in this document is a very small one, so that producing progress reports for the entire parse is a reasonable thing to do in this case. If a parse is at all large, you will usually need to be selective. .PP The progress report that is usually of most interest is the one for the Earley set that you were working on when the error occurred. This is called the \fBcurrent location\fR. In our example the current location is G1 location 5. By default, \&\f(CW\*(C`show_progress\*(C'\fR prints out only the progress reports for the current location. .PP Here are the progress reports for the current location, location 5, from our example. .PP .Vb 10 \& P0 @0\-5 L1c1\-16 statements \-> . statement * \& F0 @0\-5 L1c1\-16 statements \-> statement * . \& P1 @5\-5 L1c15\-16 statement \-> . assignment \& P2 @5\-5 L1c15\-16 statement \-> . \& F2 @0\-5 L1c1\-16 statement \-> . \& P3 @5\-5 L1c15\-16 assignment \-> . \*(Aqset\*(Aq variable \*(Aqto\*(Aq expression \& P4 @5\-5 L1c15\-16 \-> . variable \*(Aq=\*(Aq expression \& F4 @0\-5 L1c1\-16 \-> variable \*(Aq=\*(Aq expression . \& F5 @2\-5 L1c3\-16 expression \-> expression . \& F7 @4\-5 L1c13\-16 expression \-> expression . \& F8 @4\-5 L1c13\-16 expression \-> variable . \& R11:1 @2\-5 L1c3\-16 expression \-> expression . \*(Aq+\*(Aq expression \& F11 @2\-5 L1c3\-16 expression \-> expression \*(Aq+\*(Aq expression . \& F19 @0\-5 L1c1\-16 :start \-> statements . .Ve .SS "Progress report lines" .IX Subsection "Progress report lines" .Vb 1 \& F19 @0\-5 L1c1\-16 :start \-> statements . .Ve .PP The last field of each progress report line shows, in fully expanded form, the dotted rule we were working on. Prefixed to the dotted rule are three fields. In the example just above they are "\f(CW\*(C`F0 @0\-5 L1c1\-16\*(C'\fR\*(L". The \*(R"\f(CW\*(C`F0\*(C'\fR" says that this is a completed or \fBfinal\fR rule, and that it is rule number 0. The rule number is a convenient way to refer to a rule and is used when displaying the whole rule would take too much space. .PP The "\f(CW\*(C`@0\-5\*(C'\fR\*(L" describes the G1 locations of the dotted rule in the parse. In its simplest form, the location field is two G1 location numbers, separated by a hyphen. The first G1 location number is the origin, the place where Marpa first started recognizing the rule. The last G1 location number is the dot location, the G1 location of the dot in a dotted rule. \&\*(R"\f(CW\*(C`@0\-3\*(C'\fR" says that this rule began at G1 location 0, and that the dot is at G1 location 3. .PP Following the G1 location is the range of positions in the input string: "\f(CW\*(C`L1c1\-16\*(C'\fR". This indicates that the origin of dotted rule is at line 1, column 1, and that its dot position is after line 1, column 16. .PP The current location is also just after line 1, column 16, and at G1 location 5, and this is no coincidence. Whenever we are displaying the progress report for a G1 location, all the progress report lines will have their dot location at that G1 location. .PP As an aside, notice that the left hand side symbol is \f(CW\*(C`:start\*(C'\fR. That is the start pseudo-symbol. The presence of a completed start rule in our progress report indicates that if our input had ended at location 5, it would be a valid sentence in the language of our grammar. (And it is because the input at G1 location 5 was a valid sentence of the grammar, that we were able to look at the value of the parse at location 5 for debugging purposes.) .PP Let's look at another progress report line: .PP .Vb 1 \& R11:2 @2\-4 L1c3\-13 expression \-> expression \*(Aq+\*(Aq . expression .Ve .PP Here the "\f(CW\*(C`R12:2\*(C'\fR\*(L" indicates that this is rule number 12 (the \*(R"\f(CW\*(C`R\*(C'\fR" stands for rule number) and that its dot position is after the second symbol on the right hand side. Symbol positions are numbered using the ordinal of the symbol just before the position. Symbols are numbered starting with 1, and symbol position 2 is the position immediately after symbol 2. .PP Predicted rules also appear in progress reports: .PP .Vb 1 \& P2 @3\-3 L1c5\-11 statement \-> . .Ve .PP Here the "\f(CW\*(C`P\*(C'\fR\*(L" in the summary field means \*(R"predicted". Notice that in the predicted rule, the origin is the same as the dot location. This will always be the case with predicted rules. .SS "\s-1OK\s0! Now to find the bug" .IX Subsection "OK! Now to find the bug" If we look again are progress reports at the location 5, the location where things went wrong: We see that we have completed rules for \&\f(CW\*(C`\*(C'\fR, \&\f(CW\*(C`\*(C'\fR, \&\f(CW\*(C`\*(C'\fR, \&\f(CW\*(C`\*(C'\fR, as expected. We also see two Earley items that show that we are in the process of building another \f(CW\*(C`\*(C'\fR, and that it is expecting a '\f(CW\*(C`+\*(C'\fR' symbol. .PP What we want to know is, why is the recognizer \fBnot\fR expecting an '\f(CW\*(C`*\*(C'\fR' symbol? Looking back at the grammar, we see that only one rule uses the '\f(CW\*(C`*\*(C'\fR' symbol. Here it is as part of a prioritized rule in the \s-1DSL:\s0 .PP .Vb 4 \& ::= \& variable | number \& || \*(Aq+\*(Aq \& || \*(Aq*\*(Aq .Ve .PP Here it is from the \f(CW\*(C`show_rules()\*(C'\fR listing: .PP .Vb 1 \& G1 R18 ::= \*(Aq*\*(Aq .Ve .PP It's rule 19 in subgrammar G1, and for convenience we will call it R19. The next step is to look at the Earley items for this rule. But there is a problem. We don't find any. .PP Next, we ask ourselves, what is the earliest place R19 should be appearing? The answer is that there should be a prediction of R19 at location 0. So we look at the predictions at location 0. .PP .Vb 6 \& P0 @0\-0 L0c0 statements \-> . statement * \& P1 @0\-0 L0c0 statement \-> . assignment \& P2 @0\-0 L0c0 statement \-> . \& P3 @0\-0 L0c0 assignment \-> . \*(Aqset\*(Aq variable \*(Aqto\*(Aq expression \& P4 @0\-0 L0c0 \-> . variable \*(Aq=\*(Aq expression \& P19 @0\-0 L0c0 :start \-> . statements .Ve .PP No R19 predicted at G1 location 0. Next we look through the the entire progress report, at all G1 locations, to see if R19 is predicted anywhere. No R19. Not anywhere. .PP The \s-1LHS\s0 of R19 is \f(CW\*(C`\*(C'\fR. We look in the progress report for dotted rules where \&\f(CW\*(C`\*(C'\fR is expected \*(-- that is, dotted rules where \f(CW\*(C`\*(C'\fR is the post-dot symbol. There are none. .PP Next we look for places in the progress reports where \&\f(CW\*(C`\*(C'\fR occurs at all, whether post-dot or not. In the progress reports, \&\f(CW\*(C`\*(C'\fR occurs in only two dotted rule instances. Here they are: .PP .Vb 1 \& P10 @2\-2 L1c3 expression \-> . \*(Aqstring\*(Aq \*(Aq(\*(Aq \*(Aq)\*(Aq .Ve .PP .Vb 1 \& P10 @4\-4 L1c13 expression \-> . \*(Aqstring\*(Aq \*(Aq(\*(Aq \*(Aq)\*(Aq .Ve .PP In both cases these are predictions of a string operator, the operator we plan to use for converting numerics to strings. They are just predictions, predictions which go no further because there is no \&'\f(CW\*(C`string\*(C'\fR' operator in our input. That's fine, but why no other, more relevant, occurrences of \f(CW\*(C`\*(C'\fR? .PP We look back at the grammar. Aside for the rule for the '\f(CW\*(C`string\*(C'\fR' operator, \&\f(CW\*(C`\*(C'\fR occurs on a \s-1RHS\s0 in two places. One is in the prioritized rule which defines \&\f(CW\*(C`\*(C'\fR. .PP .Vb 4 \& ::= \& variable | number \& || \*(Aq+\*(Aq \& || \*(Aq*\*(Aq .Ve .PP This rule will never put \&\f(CW\*(C`\*(C'\fR into the Earley items unless there is a \f(CW\*(C`\*(C'\fR already there. But that is not its job. This rule is just fine and does not need fixing. .PP That leaves one rule to look at. .PP .Vb 1 \& ::= variable \*(Aq=\*(Aq expression .Ve .PP This rule is one that should lead to the prediction of a new \&\f(CW\*(C`\*(C'\fR in our example. And now we see our problem. This rule is never leading to the prediction of a new \&\f(CW\*(C`\*(C'\fR, because there is no \&\f(CW\*(C`\*(C'\fR on its \s-1RHS,\s0 or for that matter anywhere else in it. On the \s-1RHS,\s0 where we wrote \f(CW\*(C`\*(C'\fR, we should have written \&\f(CW\*(C`\*(C'\fR. Change that and the problem is fixed. .SH "Complications" .IX Header "Complications" We have finished our main example. This section discusses some aspects of debugging which did not arise in the example, and which might be unexpected. .SS "Empty rules" .IX Subsection "Empty rules" When a symbol is nulled in your parse, \&\f(CW\*(C`show_progress\*(C'\fR show only the nulled symbol. It does not show the symbols expansion into rules, or any of its nulled child symbols. This reduces clutter, and usually one does not notice the missing nulled rules and symbols. Not showing these seems to be the intuitive way to treat them. .SS "Input string ranges" .IX Subsection "Input string ranges" G1 locations run in a monotonic sequence, starting with 0. G1 locations never run backwards, they are never visited twice, and they leave no gaps. .PP Input string positions, on the other hand, can do all of these things. An application is allowed to jump around in the input. An input string position may be encountered more than once. It is quite possible to write your application so that it encounters, for example, line 42 before line 7. And your application does not have to visit line 42 on its way from line 41 to line 43. For that matter, an application does not ever have to visit any position in its input. .PP How does Marpa deal with this when reporting input string ranges? Marpa always reports the minimum range that includes all the input string positions visited in the dotted rule. The range is always reported in increasing numeric order, even when the position at the end of the range was visited before the input string position at the beginning of the range. And, if necessary to include all visited input string positions, the range may include input string positions which were not visited. .PP Most applications move forward continuously in the input string, and if yours is one of them, you don't have to worry about these issues. But if you do unusual things when reading the input, it helps to be aware of how input string ranges are reported by Marpa when tracing and debugging. .SS "Multiple instances of dotted rules" .IX Subsection "Multiple instances of dotted rules" It does not happen in our main example for this document, but a dotted rule can appear in the same Earley set more than once. In fact, this happens frequently. When it does happen, the lines in the progress report will look like these .PP .Vb 1 \& F11 x13 @0...40\-41 L1c1\-L2c40 \-> \*(Aqx\*(Aq \*(Aq=\*(Aq expression . .Ve .PP .Vb 1 \& F1 x20 @0...38\-41 L1c1\-L2c40 expression \-> assignment . .Ve .PP .Vb 1 \& F6 x12 @0...38\-41 L1c1\-L2c40 assignment \-> . .Ve .PP These are some of the progress report lines for an indirect right recursion, one that recurses from a \f(CW\*(C`\*(C'\fR symbol to an \f(CW\*(C`\*(C'\fR symbol, and then to an \f(CW\*(C`\*(C'\fR symbol, before completing the recursion by returning to a \f(CW\*(C`\*(C'\fR. .PP In each of the three lines, notice that a new field appears second. This second field is variously "\f(CW\*(C`x13\*(C'\fR\*(L", \*(R"\f(CW\*(C`x20\*(C'\fR\*(L" or \*(R"\f(CW\*(C`x12\*(C'\fR". These are counts, indicating the number of instances of that dotted rule at the dotted rule's G1 dot location. Every dotted rule instance will have the same G1 location, but the instances may have many different origins \*(-- hundreds or even more. In each of the three report lines above, the G1 dot location is 41. .PP Note that when parsing, Marpa handles the long series of Earley items generated by right recursions very efficiently. It uses a technique invented by Joop Leo to memoize and eliminate them. When a progress report is requested at a G1 location, the Leo-memoization is unfolded, and the full list of Earley items is reported. .PP Each instance may have its own span in the input string, and the input string range will include them all. When there are many instances of a dotted rule at a single location, the origins in the location field are shown as a range, with the earliest separated from the most recent by a "\f(CW\*(C`...\*(C'\fR\*(L". For example, above, where the first four fields were \&\*(R"\f(CW\*(C`F7 x12 @0...38\-41 L1c1\-L2c40\*(C'\fR", that tells us that the dotted rule is rule 7, which has 12 instances. All 12 instances have their dot location at G1 location 41, but their origins are in the range from G1 location 0 to G1 location 38. .PP The last field in "\f(CW\*(C`F7 x12 @0...38\-41 L1c1\-L2c40\*(C'\fR\*(L" is an input string range. \&\*(R"\f(CW\*(C`L1c1\-L2c40\*(C'\fR" says that input string positions visited by the the 12 instances start at line 1, column 1, and end at line 2, column 40. The reported input string range will be the shortest range that includes all of the input string positions visited by any of the dotted rule instances. .PP If there are only a few origins, Marpa may explicitly list them all. In the follow example, there are only 2 instances of this rule, both with a dot location of 41. Their origins are at G1 locations 8 and 18. The range of input string positions is from line 1, column 17 to line 2, column 40. .PP .Vb 1 \& F2 x2 @8,18\-41 L1c17\-L2c40 assignment \-> . .Ve .ie n .SH "Access to the ""raw"" progress report information" .el .SH "Access to the ``raw'' progress report information" .IX Header "Access to the raw progress report information" This section deals with the \f(CW\*(C`progress()\*(C'\fR recognizer method, which allows access to the raw progress report information. This method is not needed for typical debugging and tracing situations. It is intended for applications which want to leverage Marpa's \*(L"situational awareness\*(R" in innovative ways. .SS "\fIprogress()\fP" .IX Subsection "progress()" .Vb 1 \& my $report0 = $slr\->progress(0); .Ve .PP .PP .Vb 1 \& my $latest_report = $slr\->progress(); .Ve .PP Given the G1 location (Earley set \s-1ID\s0) as its argument, the \f(CW\*(C`progress()\*(C'\fR recognizer method returns a reference to an array of \*(L"report items\*(R". The G1 location may be given as a negative number. An argument of \fI\-X\fR will be interpreted as G1 location \fIN+X+1\fR, where \fIN\fR is the latest Earley set. This means that an argument of \-1 indicates the latest Earley set, an argument of \-2 indicates the Earley set just before the latest one, etc. .PP Each report item is a triple: an array of three elements. The three elements are, in order, rule \s-1ID,\s0 dot position, and origin. The data returned by the two displays above, as well as the data for the other G1 locations in our example, are shown below. .PP The rule \s-1ID\s0 is the same number that Marpa uses to identify rules in tracing and debugging output. Given a rule \s-1ID,\s0 an application can expand it into its \s-1LHS\s0 and \s-1RHS\s0 symbols using the \s-1SLIF\s0 grammar's \f(CW\*(C`rule_expand()\*(C'\fR method. Given a symbol \s-1ID,\s0 its name and other information can be found using other \s-1SLIF\s0 grammar methods. .PP Dot position is \-1 for completions, and 0 for predictions. Where the report item is not for a completion or a prediction, dot position is \fIN\fR, where \fIN\fR is the number of \s-1RHS\s0 symbols successfully recognized at the G1 location of the progress report. .PP Origin is the G1 location (Earley set \s-1ID\s0) at which the rule application reported by the report item began. For a prediction, origin will always be the same as the G1 location of the parse report. .SS "Progress reports and efficiency" .IX Subsection "Progress reports and efficiency" When progress reports are used for production parsing, instead of just for debugging and tracing, efficiency considerations become significant. Progress reports themselves are implemented in optimized C, and that logic is very fast. However, the use of progress reports usually implies considerable post-processing in Perl. It is almost always possible to use Marpa's named events instead of progress reports, and solutions using named events are usually better targeted, simpler and faster. .PP If you do decide to use progress reports in an application, you should be aware of the efficiency considerations when there are right recursions in the grammar. For most purposes, Marpa optimizes right recursions, so that they run in linear time. However, to create a progress report every potential right recursion must be fully unfolded, and at each G1 location the number of these grows linearly with the length of the recursion. If you are creating progress reports for more than a limited number of G1 locations, this means processing that can be quadratic in the length of the recursion. When a right recursion is lengthy, the impact on speed can be be very serious. .PP If lengthy right recursions are being expanded, this will be evident from the parse report itself, which will contain one report item for every completion in the right-recursive chain of completions. Note that the efficiency consideration just mentioned for following right recursions is never an issue for left recursions. Left recursions only produce at most two report items per G1 location and are extremely fast to process. It is also not an issue for Marpa's sequence rules, because sequence rules are implemented internally as left recursions. .SH "Appendix" .IX Header "Appendix" Below are the code, the trace outputs and the progress report for the example used in this document. .SS "Code" .IX Subsection "Code" .Vb 6 \& my $slif_debug_source = <<\*(AqEND_OF_SOURCE\*(Aq; \& :default ::= action => ::array bless => ::lhs \& :start ::= statements \& statements ::= statement * \& statement ::= assignment | \& assignment ::= \*(Aqset\*(Aq variable \*(Aqto\*(Aq expression \& \& # This is a deliberate error in the grammar \& # The next line should be: \& # ::= variable \*(Aq=\*(Aq \& # I have changed the to which \& # will cause problems. \& ::= variable \*(Aq=\*(Aq expression \& \& expression ::= \& variable | string \& || \*(Aqstring\*(Aq \*(Aq(\*(Aq \*(Aq)\*(Aq \& || expression \*(Aq+\*(Aq expression \& ::= \& variable | number \& || \*(Aq+\*(Aq \& || \*(Aq*\*(Aq \& variable ~ [\ew]+ \& number ~ [\ed]+ \& string ~ [\*(Aq] [\*(Aq] \& ~ [^\*(Aq\ex{0A}\ex{0B}\ex{0C}\ex{0D}\ex{0085}\ex{2028}\ex{2029}]+ \& :discard ~ whitespace \& whitespace ~ [\es]+ \& END_OF_SOURCE \& \& my $slg = Marpa::R2::Scanless::G\->new( \& { \& bless_package => \*(AqMy_Nodes\*(Aq, \& source => \e$slif_debug_source, \& }); .Ve .PP .Vb 5 \& my $slr = Marpa::R2::Scanless::R\->new( \& { grammar => $slg, \& trace_terminals => 1, \& trace_values => 1, \& } ); \& \& my $test_input = \*(Aqa = 8675309 + 42 * 711\*(Aq ; \& my $eval_error = $EVAL_ERROR if not eval { $slr\->read( \e$test_input ); 1 }; \& \& $progress_report = $slr\->show_progress( 0, \-1 ); .Ve .SS "Error message" .IX Subsection "Error message" .Vb 5 \& Error in SLIF parse: No lexemes accepted at line 1, column 18 \& Rejected lexeme #0: Lexer "L0"; \*(Aq*\*(Aq; value="*"; length = 1 \& * String before error: a = 8675309 + 42\es \& * The error was at line 1, column 18, and at character 0x002a \*(Aq*\*(Aq, ... \& * here: * 711 .Ve .SS "Parse value at error location" .IX Subsection "Parse value at error location" Note that when there is a parse error, there will not always be a parse value. But sometimes the parse is \*(L"successful\*(R" enough, in a technical sense, to produce a value, and in those cases examining the value can be helpful in determining what the parser thinks it has seen so far. .PP .Vb 10 \& my $value_ref = $slr\->value(); \& my $expected_output = \ebless( [ \& bless( [ \& bless( [ \& \*(Aqa\*(Aq, \& \*(Aq=\*(Aq, \& bless( [ \& bless( [ \& \*(Aq8675309\*(Aq \& ], \*(AqMy_Nodes::expression\*(Aq ), \& \*(Aq+\*(Aq, \& bless( [ \& \*(Aq42\*(Aq \& ], \*(AqMy_Nodes::expression\*(Aq ) \& ], \*(AqMy_Nodes::expression\*(Aq ) \& ], \*(AqMy_Nodes::numeric_assignment\*(Aq ) \& ], \*(AqMy_Nodes::statement\*(Aq ) \& ], \*(AqMy_Nodes::statements\*(Aq ); .Ve .SS "Trace output" .IX Subsection "Trace output" .Vb 10 \& Setting trace_terminals option \& Setting trace_values option \& Lexer "L0" accepted lexeme L1c1: variable; value="a" \& Lexer "L0" discarded lexeme L1c2: whitespace \& Lexer "L0" accepted lexeme L1c3: \*(Aq=\*(Aq; value="=" \& Lexer "L0" discarded lexeme L1c4: whitespace \& Lexer "L0" rejected lexeme L1c5\-11: number; value="8675309" \& Lexer "L0" accepted lexeme L1c5\-11: variable; value="8675309" \& Lexer "L0" discarded lexeme L1c12: whitespace \& Lexer "L0" rejected lexeme L1c13: \*(Aq+\*(Aq; value="+" \& Lexer "L0" accepted lexeme L1c13: \*(Aq+\*(Aq; value="+" \& Lexer "L0" discarded lexeme L1c14: whitespace \& Lexer "L0" rejected lexeme L1c15\-16: number; value="42" \& Lexer "L0" accepted lexeme L1c15\-16: variable; value="42" \& Lexer "L0" discarded lexeme L1c17: whitespace \& Lexer "L0" rejected lexeme L1c18: \*(Aq*\*(Aq; value="*" .Ve .SS "\fIshow_progress()\fP output" .IX Subsection "show_progress() output" .Vb 10 \& P0 @0\-0 L0c0 statements \-> . statement * \& P1 @0\-0 L0c0 statement \-> . assignment \& P2 @0\-0 L0c0 statement \-> . \& P3 @0\-0 L0c0 assignment \-> . \*(Aqset\*(Aq variable \*(Aqto\*(Aq expression \& P4 @0\-0 L0c0 \-> . variable \*(Aq=\*(Aq expression \& P19 @0\-0 L0c0 :start \-> . statements \& R4:1 @0\-1 L1c1 \-> variable . \*(Aq=\*(Aq expression \& R4:2 @0\-2 L1c1\-3 \-> variable \*(Aq=\*(Aq . expression \& P5 @2\-2 L1c3 expression \-> . expression \& P6 @2\-2 L1c3 expression \-> . expression \& P7 @2\-2 L1c3 expression \-> . expression \& P8 @2\-2 L1c3 expression \-> . variable \& P9 @2\-2 L1c3 expression \-> . string \& P10 @2\-2 L1c3 expression \-> . \*(Aqstring\*(Aq \*(Aq(\*(Aq \*(Aq)\*(Aq \& P11 @2\-2 L1c3 expression \-> . expression \*(Aq+\*(Aq expression \& P0 @0\-3 L1c1\-11 statements \-> . statement * \& F0 @0\-3 L1c1\-11 statements \-> statement * . \& P1 @3\-3 L1c5\-11 statement \-> . assignment \& P2 @3\-3 L1c5\-11 statement \-> . \& F2 @0\-3 L1c1\-11 statement \-> . \& P3 @3\-3 L1c5\-11 assignment \-> . \*(Aqset\*(Aq variable \*(Aqto\*(Aq expression \& P4 @3\-3 L1c5\-11 \-> . variable \*(Aq=\*(Aq expression \& F4 @0\-3 L1c1\-11 \-> variable \*(Aq=\*(Aq expression . \& F5 @2\-3 L1c3\-11 expression \-> expression . \& F6 @2\-3 L1c3\-11 expression \-> expression . \& F7 @2\-3 L1c3\-11 expression \-> expression . \& F8 @2\-3 L1c3\-11 expression \-> variable . \& R11:1 @2\-3 L1c3\-11 expression \-> expression . \*(Aq+\*(Aq expression \& F19 @0\-3 L1c1\-11 :start \-> statements . \& P7 @4\-4 L1c13 expression \-> . expression \& P8 @4\-4 L1c13 expression \-> . variable \& P9 @4\-4 L1c13 expression \-> . string \& P10 @4\-4 L1c13 expression \-> . \*(Aqstring\*(Aq \*(Aq(\*(Aq \*(Aq)\*(Aq \& R11:2 @2\-4 L1c3\-13 expression \-> expression \*(Aq+\*(Aq . expression \& P0 @0\-5 L1c1\-16 statements \-> . statement * \& F0 @0\-5 L1c1\-16 statements \-> statement * . \& P1 @5\-5 L1c15\-16 statement \-> . assignment \& P2 @5\-5 L1c15\-16 statement \-> . \& F2 @0\-5 L1c1\-16 statement \-> . \& P3 @5\-5 L1c15\-16 assignment \-> . \*(Aqset\*(Aq variable \*(Aqto\*(Aq expression \& P4 @5\-5 L1c15\-16 \-> . variable \*(Aq=\*(Aq expression \& F4 @0\-5 L1c1\-16 \-> variable \*(Aq=\*(Aq expression . \& F5 @2\-5 L1c3\-16 expression \-> expression . \& F7 @4\-5 L1c13\-16 expression \-> expression . \& F8 @4\-5 L1c13\-16 expression \-> variable . \& R11:1 @2\-5 L1c3\-16 expression \-> expression . \*(Aq+\*(Aq expression \& F11 @2\-5 L1c3\-16 expression \-> expression \*(Aq+\*(Aq expression . \& F19 @0\-5 L1c1\-16 :start \-> statements . .Ve .SS "\fIshow_rules()\fP output" .IX Subsection "show_rules() output" This is the G1 portion of the \f(CW\*(C`show_rules()\*(C'\fR output at verbosity level 3. In ordinary work, you'd use verbosity level 1 (the default), but the more verbose output is included here to illustrate the example. .PP .Vb 10 \& G1 Rules: \& G1 R0 statements ::= statement * \& Symbol IDs: <16> ::= <17> \& Internal symbols: ::= \& G1 R1 statement ::= assignment \& Symbol IDs: <17> ::= <18> \& Internal symbols: ::= \& G1 R2 statement ::= \& Symbol IDs: <17> ::= <19> \& Internal symbols: ::= \& G1 R3 assignment ::= \*(Aqset\*(Aq variable \*(Aqto\*(Aq expression \& Symbol IDs: <18> ::= <1> <20> <2> <21> \& Internal symbols: ::= <[Lex\-0]> <[Lex\-1]> \& G1 R4 ::= variable \*(Aq=\*(Aq \& Symbol IDs: <19> ::= <20> <3> <22> \& Internal symbols: ::= <[Lex\-2]> \& G1 R5 expression ::= expression \& Internal rule top priority rule for \& Symbol IDs: <21> ::= <10> \& Internal symbols: ::= \& G1 R6 expression ::= expression \& Internal rule for symbol priority transition from 0 to 1 \& Symbol IDs: <10> ::= <11> \& Internal symbols: ::= \& G1 R7 expression ::= expression \& Internal rule for symbol priority transition from 1 to 2 \& Symbol IDs: <11> ::= <12> \& Internal symbols: ::= \& G1 R8 expression ::= variable \& Symbol IDs: <12> ::= <20> \& Internal symbols: ::= \& G1 R9 expression ::= string \& Symbol IDs: <12> ::= <23> \& Internal symbols: ::= \& G1 R10 expression ::= \*(Aqstring\*(Aq \*(Aq(\*(Aq \*(Aq)\*(Aq \& Symbol IDs: <11> ::= <4> <5> <22> <6> \& Internal symbols: ::= <[Lex\-3]> <[Lex\-4]> <[Lex\-5]> \& G1 R11 expression ::= expression \*(Aq+\*(Aq expression \& Symbol IDs: <10> ::= <10> <7> <11> \& Internal symbols: ::= <[Lex\-6]> \& G1 R12 ::= \& Internal rule top priority rule for \& Symbol IDs: <22> ::= <13> \& Internal symbols: ::= \& G1 R13 ::= \& Internal rule for symbol priority transition from 0 to 1 \& Symbol IDs: <13> ::= <14> \& Internal symbols: ::= \& G1 R14 ::= \& Internal rule for symbol priority transition from 1 to 2 \& Symbol IDs: <14> ::= <15> \& Internal symbols: ::= \& G1 R15 ::= variable \& Symbol IDs: <15> ::= <20> \& Internal symbols: ::= \& G1 R16 ::= number \& Symbol IDs: <15> ::= <24> \& Internal symbols: ::= \& G1 R17 ::= \*(Aq+\*(Aq \& Symbol IDs: <14> ::= <14> <8> <15> \& Internal symbols: ::= <[Lex\-7]> \& G1 R18 ::= \*(Aq*\*(Aq \& Symbol IDs: <13> ::= <13> <9> <14> \& Internal symbols: ::= <[Lex\-8]> \& G1 R19 :start ::= statements \& Symbol IDs: <0> ::= <16> \& Internal symbols: <[:start]> ::= \& Lex (L0) Rules: \& L0 R0 \*(Aqset\*(Aq ::= [s] [e] [t] \& Internal rule for single\-quoted string \*(Aqset\*(Aq \& Symbol IDs: <2> ::= <27> <21> <28> \& Internal symbols: <[Lex\-0]> ::= <[[s]]> <[[e]]> <[[t]]> \& L0 R1 \*(Aqto\*(Aq ::= [t] [o] \& Internal rule for single\-quoted string \*(Aqto\*(Aq \& Symbol IDs: <3> ::= <28> <25> \& Internal symbols: <[Lex\-1]> ::= <[[t]]> <[[o]]> \& L0 R2 \*(Aq=\*(Aq ::= [\e=] \& Internal rule for single\-quoted string \*(Aq=\*(Aq \& Symbol IDs: <4> ::= <16> \& Internal symbols: <[Lex\-2]> ::= <[[\e=]]> \& L0 R3 \*(Aqstring\*(Aq ::= [s] [t] [r] [i] [n] [g] \& Internal rule for single\-quoted string \*(Aqstring\*(Aq \& Symbol IDs: <5> ::= <27> <28> <26> <23> <24> <22> \& Internal symbols: <[Lex\-3]> ::= <[[s]]> <[[t]]> <[[r]]> <[[i]]> <[[n]]> <[[g]]> \& L0 R4 \*(Aq(\*(Aq ::= [\e(] \& Internal rule for single\-quoted string \*(Aq(\*(Aq \& Symbol IDs: <6> ::= <12> \& Internal symbols: <[Lex\-4]> ::= <[[\e(]]> \& L0 R5 \*(Aq)\*(Aq ::= [\e)] \& Internal rule for single\-quoted string \*(Aq)\*(Aq \& Symbol IDs: <7> ::= <13> \& Internal symbols: <[Lex\-5]> ::= <[[\e)]]> \& L0 R6 \*(Aq+\*(Aq ::= [\e+] \& Internal rule for single\-quoted string \*(Aq+\*(Aq \& Symbol IDs: <8> ::= <15> \& Internal symbols: <[Lex\-6]> ::= <[[\e+]]> \& L0 R7 \*(Aq+\*(Aq ::= [\e+] \& Internal rule for single\-quoted string \*(Aq+\*(Aq \& Symbol IDs: <9> ::= <15> \& Internal symbols: <[Lex\-7]> ::= <[[\e+]]> \& L0 R8 \*(Aq*\*(Aq ::= [\e*] \& Internal rule for single\-quoted string \*(Aq*\*(Aq \& Symbol IDs: <10> ::= <14> \& Internal symbols: <[Lex\-8]> ::= <[[\e*]]> \& L0 R9 variable ::= [\ew] + \& Symbol IDs: <29> ::= <19> \& Internal symbols: ::= <[[\ew]]> \& L0 R10 number ::= [\ed] + \& Symbol IDs: <30> ::= <17> \& Internal symbols: ::= <[[\ed]]> \& L0 R11 string ::= [\*(Aq] [\*(Aq] \& Symbol IDs: <31> ::= <11> <32> <11> \& Internal symbols: ::= <[[\*(Aq]]> <[[\*(Aq]]> \& L0 R12 ::= [^\*(Aq\ex{0A}\ex{0B}\ex{0C}\ex{0D}\ex{0085}\ex{2028}\ex{2029}] + \& Symbol IDs: <32> ::= <20> \& Internal symbols: ::= <[[^\*(Aq\ex{0A}\ex{0B}\ex{0C}\ex{0D}\ex{0085}\ex{2028}\ex{2029}]]> \& L0 R13 :discard ::= whitespace \& Discard rule for \& Symbol IDs: <0> ::= <33> \& Internal symbols: <[:discard]> ::= \& L0 R14 whitespace ::= [\es] + \& Symbol IDs: <33> ::= <18> \& Internal symbols: ::= <[[\es]]> \& L0 R15 :start_lex ::= :discard \& Internal lexical start rule for <[:discard]> \& Symbol IDs: <1> ::= <0> \& Internal symbols: <[:start_lex]> ::= <[:discard]> \& L0 R16 :start_lex ::= \*(Aqset\*(Aq \& Internal lexical start rule for <[Lex\-0]> \& Symbol IDs: <1> ::= <2> \& Internal symbols: <[:start_lex]> ::= <[Lex\-0]> \& L0 R17 :start_lex ::= \*(Aqto\*(Aq \& Internal lexical start rule for <[Lex\-1]> \& Symbol IDs: <1> ::= <3> \& Internal symbols: <[:start_lex]> ::= <[Lex\-1]> \& L0 R18 :start_lex ::= \*(Aq=\*(Aq \& Internal lexical start rule for <[Lex\-2]> \& Symbol IDs: <1> ::= <4> \& Internal symbols: <[:start_lex]> ::= <[Lex\-2]> \& L0 R19 :start_lex ::= \*(Aqstring\*(Aq \& Internal lexical start rule for <[Lex\-3]> \& Symbol IDs: <1> ::= <5> \& Internal symbols: <[:start_lex]> ::= <[Lex\-3]> \& L0 R20 :start_lex ::= \*(Aq(\*(Aq \& Internal lexical start rule for <[Lex\-4]> \& Symbol IDs: <1> ::= <6> \& Internal symbols: <[:start_lex]> ::= <[Lex\-4]> \& L0 R21 :start_lex ::= \*(Aq)\*(Aq \& Internal lexical start rule for <[Lex\-5]> \& Symbol IDs: <1> ::= <7> \& Internal symbols: <[:start_lex]> ::= <[Lex\-5]> \& L0 R22 :start_lex ::= \*(Aq+\*(Aq \& Internal lexical start rule for <[Lex\-6]> \& Symbol IDs: <1> ::= <8> \& Internal symbols: <[:start_lex]> ::= <[Lex\-6]> \& L0 R23 :start_lex ::= \*(Aq+\*(Aq \& Internal lexical start rule for <[Lex\-7]> \& Symbol IDs: <1> ::= <9> \& Internal symbols: <[:start_lex]> ::= <[Lex\-7]> \& L0 R24 :start_lex ::= \*(Aq*\*(Aq \& Internal lexical start rule for <[Lex\-8]> \& Symbol IDs: <1> ::= <10> \& Internal symbols: <[:start_lex]> ::= <[Lex\-8]> \& L0 R25 :start_lex ::= number \& Internal lexical start rule for \& Symbol IDs: <1> ::= <30> \& Internal symbols: <[:start_lex]> ::= \& L0 R26 :start_lex ::= string \& Internal lexical start rule for \& Symbol IDs: <1> ::= <31> \& Internal symbols: <[:start_lex]> ::= \& L0 R27 :start_lex ::= variable \& Internal lexical start rule for \& Symbol IDs: <1> ::= <29> \& Internal symbols: <[:start_lex]> ::= .Ve .SS "\fIshow_symbols()\fP output" .IX Subsection "show_symbols() output" .Vb 10 \& G1 Symbols: \& G1 S0 :start \-\- Internal G1 start symbol \& Internal name: <[:start]> \& G1 S1 \*(Aqset\*(Aq \-\- Internal lexical symbol for "\*(Aqset\*(Aq" \& /* terminal */ \& Internal name: <[Lex\-0]> \& SLIF name: \*(Aqset\*(Aq \& G1 S2 \*(Aqto\*(Aq \-\- Internal lexical symbol for "\*(Aqto\*(Aq" \& /* terminal */ \& Internal name: <[Lex\-1]> \& SLIF name: \*(Aqto\*(Aq \& G1 S3 \*(Aq=\*(Aq \-\- Internal lexical symbol for "\*(Aq=\*(Aq" \& /* terminal */ \& Internal name: <[Lex\-2]> \& SLIF name: \*(Aq=\*(Aq \& G1 S4 \*(Aqstring\*(Aq \-\- Internal lexical symbol for "\*(Aqstring\*(Aq" \& /* terminal */ \& Internal name: <[Lex\-3]> \& SLIF name: \*(Aqstring\*(Aq \& G1 S5 \*(Aq(\*(Aq \-\- Internal lexical symbol for "\*(Aq(\*(Aq" \& /* terminal */ \& Internal name: <[Lex\-4]> \& SLIF name: \*(Aq(\*(Aq \& G1 S6 \*(Aq)\*(Aq \-\- Internal lexical symbol for "\*(Aq)\*(Aq" \& /* terminal */ \& Internal name: <[Lex\-5]> \& SLIF name: \*(Aq)\*(Aq \& G1 S7 \*(Aq+\*(Aq \-\- Internal lexical symbol for "\*(Aq+\*(Aq" \& /* terminal */ \& Internal name: <[Lex\-6]> \& SLIF name: \*(Aq+\*(Aq \& G1 S8 \*(Aq+\*(Aq \-\- Internal lexical symbol for "\*(Aq+\*(Aq" \& /* terminal */ \& Internal name: <[Lex\-7]> \& SLIF name: \*(Aq+\*(Aq \& G1 S9 \*(Aq*\*(Aq \-\- Internal lexical symbol for "\*(Aq*\*(Aq" \& /* terminal */ \& Internal name: <[Lex\-8]> \& SLIF name: \*(Aq*\*(Aq \& G1 S10 expression \-\- at priority 0 \& Internal name: \& SLIF name: expression \& G1 S11 expression \-\- at priority 1 \& Internal name: \& SLIF name: expression \& G1 S12 expression \-\- at priority 2 \& Internal name: \& SLIF name: expression \& G1 S13 \-\- at priority 0 \& Internal name: \& SLIF name: numeric expression \& G1 S14 \-\- at priority 1 \& Internal name: \& SLIF name: numeric expression \& G1 S15 \-\- at priority 2 \& Internal name: \& SLIF name: numeric expression \& G1 S16 statements \& Internal name: \& G1 S17 statement \& Internal name: \& G1 S18 assignment \& Internal name: \& G1 S19 \& Internal name: \& G1 S20 variable \& /* terminal */ \& Internal name: \& G1 S21 expression \& Internal name: \& G1 S22 \& Internal name: \& G1 S23 string \& /* terminal */ \& Internal name: \& G1 S24 number \& /* terminal */ \& Internal name: .Ve .SS "\fIprogress()\fP outputs" .IX Subsection "progress() outputs" These section contains samples of the output of the \f(CW\*(C`progress()\*(C'\fR method \*(-- the progress reports in their \*(L"raw\*(R" format. The output is shown in Data::Dumper format, with \f(CW\*(C`Data::Dumper::Indent\*(C'\fR set to 0 and \f(CW\*(C`Data::Dumper::Terse\*(C'\fR set to 1. .PP The \f(CW\*(C`Data::Dumper\*(C'\fR output from \f(CW\*(C`progress()\*(C'\fR at G1 location 0: .PP .Vb 1 \& [[0,0,0],[1,0,0],[2,0,0],[3,0,0],[4,0,0],[19,0,0]] .Ve .PP The \f(CW\*(C`Data::Dumper\*(C'\fR output from \f(CW\*(C`progress()\*(C'\fR at G1 location 1: .PP .Vb 1 \& [[4,1,0]] .Ve .PP The \f(CW\*(C`Data::Dumper\*(C'\fR output from \f(CW\*(C`progress()\*(C'\fR at location 2: .PP .Vb 1 \& [[5,0,2],[6,0,2],[7,0,2],[8,0,2],[9,0,2],[10,0,2],[11,0,2],[4,2,0]] .Ve .PP The default \f(CW\*(C`progress()\*(C'\fR output is for the latest Earley set. Here is the \f(CW\*(C`progress()\*(C'\fR output for the latest Earley set. .PP .Vb 1 \& [[0,\-1,0],[2,\-1,0],[4,\-1,0],[5,\-1,2],[7,\-1,4],[8,\-1,4],[11,\-1,2],[19,\-1,0],[0,0,0],[1,0,5],[2,0,5],[3,0,5],[4,0,5],[11,1,2]] .Ve .SH "Copyright and License" .IX Header "Copyright and License" .Vb 5 \& Copyright 2014 Jeffrey Kegler \& This file is part of Marpa::R2. Marpa::R2 is free software: you can \& redistribute it and/or modify it under the terms of the GNU Lesser \& General Public License as published by the Free Software Foundation, \& either version 3 of the License, or (at your option) any later version. \& \& Marpa::R2 is distributed in the hope that it will be useful, \& but WITHOUT ANY WARRANTY; without even the implied warranty of \& MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU \& Lesser General Public License for more details. \& \& You should have received a copy of the GNU Lesser \& General Public License along with Marpa::R2. If not, see \& http://www.gnu.org/licenses/. .Ve