1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041 |
- \input texinfo @c -*-texinfo-*-
- @c %**start of header
- @setfilename ../../info/wisent.info
- @set TITLE Wisent Parser Development
- @set AUTHOR Eric M. Ludlam, David Ponce, and Richard Y. Kim
- @settitle @value{TITLE}
- @include docstyle.texi
- @c *************************************************************************
- @c @ Header
- @c *************************************************************************
- @c Merge all indexes into a single index for now.
- @c We can always separate them later into two or more as needed.
- @syncodeindex vr cp
- @syncodeindex fn cp
- @syncodeindex ky cp
- @syncodeindex pg cp
- @syncodeindex tp cp
- @c @footnotestyle separate
- @c @paragraphindent 2
- @c @@smallbook
- @c %**end of header
- @copying
- Copyright @copyright{} 1988--1993, 1995, 1998--2004, 2007, 2012--2016
- Free Software Foundation, Inc.
- @c Since we are both GNU manuals, we do not need to ack each other here.
- @ignore
- Some texts are borrowed or adapted from the manual of Bison version
- 1.35. The text in section entitled ``Understanding the automaton'' is
- adapted from the section ``Understanding Your Parser'' in the manual
- of Bison version 1.49.
- @end ignore
- @quotation
- Permission is granted to copy, distribute and/or modify this document
- under the terms of the GNU Free Documentation License, Version 1.3 or
- any later version published by the Free Software Foundation; with no
- Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
- and with the Back-Cover Texts as in (a) below. A copy of the license
- is included in the section entitled ``GNU Free Documentation License''.
- (a) The FSF's Back-Cover Text is: ``You have the freedom to copy and
- modify this GNU manual.''
- @end quotation
- @end copying
- @dircategory Emacs misc features
- @direntry
- * Wisent: (wisent). Semantic Wisent parser development.
- @end direntry
- @iftex
- @finalout
- @end iftex
- @c @setchapternewpage odd
- @c @setchapternewpage off
- @titlepage
- @sp 10
- @title @value{TITLE}
- @author by @value{AUTHOR}
- @page
- @vskip 0pt plus 1 fill
- @insertcopying
- @end titlepage
- @page
- @macro semantic{}
- @i{Semantic}
- @end macro
- @c *************************************************************************
- @c @ Document
- @c *************************************************************************
- @contents
- @node top
- @top @value{TITLE}
- Wisent (the European Bison ;-) is an Emacs Lisp implementation of the
- GNU Compiler Compiler Bison.
- This manual describes how to use Wisent to develop grammars for
- programming languages, and how to use grammars to parse language
- source in Emacs buffers.
- It also describes how Wisent is used with the @semantic{} tool set
- described in the @ref{Top, Semantic Manual, Semantic Manual, semantic}.
- @ifnottex
- @insertcopying
- @end ifnottex
- @menu
- * Wisent Overview::
- * Wisent Grammar::
- * Wisent Parsing::
- * Wisent Semantic::
- * GNU Free Documentation License::
- * Index::
- @end menu
- @node Wisent Overview
- @chapter Wisent Overview
- @dfn{Wisent} (the European Bison) is an implementation in Emacs Lisp
- of the GNU Compiler Compiler Bison. Its code is a port of the C code
- of GNU Bison 1.28 & 1.31.
- For more details on the basic concepts for understanding Wisent, it is
- worthwhile to read the @ref{Top, Bison Manual, , bison}.
- Wisent can generate compilers compatible with the @semantic{} tool set.
- See the @ref{Top, Semantic Manual, , semantic}.
- It benefits from these Bison features:
- @itemize @bullet
- @item
- It uses a fast but not so space-efficient encoding for the parse
- tables, described in Corbett's PhD thesis from Berkeley:
- @quotation
- @cite{Static Semantics in Compiler Error Recovery}@*
- June 1985, Report No. UCB/CSD 85/251.
- @end quotation
- @item
- For generating the lookahead sets, Wisent uses the well-known
- technique of F. DeRemer and T. Pennello described in:
- @quotation
- @cite{Efficient Computation of LALR(1) Look-Ahead Sets}@*
- October 1982, ACM TOPLAS Vol 4 No 4, 615--49,
- @uref{http://dx.doi.org/10.1145/69622.357187}.
- @end quotation
- @item
- Wisent resolves shift/reduce conflicts using operator precedence and
- associativity.
- @item
- Parser error recovery is accomplished using rules which match the
- special token @code{error}.
- @end itemize
- Nevertheless there are some fundamental differences between Bison and
- Wisent.
- @itemize
- @item
- Wisent is intended to be used in Emacs. It reads and produces Emacs
- Lisp data structures. All the additional code used in grammars is
- Emacs Lisp code.
- @item
- Contrary to Bison, Wisent does not generate a parser which combines
- Emacs Lisp code and grammar constructs. They exist separately.
- Wisent reads the grammar from a Lisp data structure and then generates
- grammar constructs as tables. Afterward, the derived tables can be
- included and byte-compiled in separate Emacs Lisp files, and be used
- at a later time by the Wisent's parser engine.
- @item
- Wisent allows multiple start nonterminals and allows a call to the
- parsing function to be made for a particular start nonterminal. For
- example, this is particularly useful to parse a region of an Emacs
- buffer. @semantic{} heavily depends on the availability of this feature.
- @end itemize
- @node Wisent Grammar
- @chapter Wisent Grammar
- @cindex context-free grammar
- @cindex rule
- In order for Wisent to parse a language, it must be described by a
- @dfn{context-free grammar}. That is a grammar specified as rules that
- can be applied regardless of context. For more information, see
- @ref{Language and Grammar, , , bison}, in the Bison manual.
- @cindex terminal
- @cindex nonterminal
- The formal grammar is formulated using @dfn{terminal} and
- @dfn{nonterminal} items. Terminals can be Emacs Lisp symbols or
- characters, and nonterminals are symbols only.
- @cindex token
- Terminals (also known as @dfn{tokens}) represent the lexical
- elements of the language like numbers, strings, etc..
- For example @samp{PLUS} can represent the operator @samp{+}.
- Nonterminal symbols are described by rules:
- @example
- @group
- RESULT @equiv{} COMPONENTS@dots{}
- @end group
- @end example
- @samp{RESULT} is a nonterminal that this rule describes and
- @samp{COMPONENTS} are various terminals and nonterminals that are put
- together by this rule.
- For example, this rule:
- @example
- @group
- exp @equiv{} exp PLUS exp
- @end group
- @end example
- Says that two groupings of type @samp{exp}, with a @samp{PLUS} token
- in between, can be combined into a larger grouping of type @samp{exp}.
- @menu
- * Grammar format::
- * Example::
- * Compiling a grammar::
- * Conflicts::
- @end menu
- @node Grammar format
- @section Grammar format
- @cindex grammar format
- To be acceptable by Wisent a context-free grammar must respect a
- particular format. That is, must be represented as an Emacs Lisp list
- of the form:
- @code{(@var{terminals} @var{assocs} . @var{non-terminals})}
- @table @var
- @item terminals
- Is the list of terminal symbols used in the grammar.
- @cindex associativity
- @item assocs
- Specify the associativity of @var{terminals}. It is @code{nil} when
- there is no associativity defined, or an alist of
- @w{@code{(@var{assoc-type} . @var{assoc-value})}} elements.
- @var{assoc-type} must be one of the @code{default-prec},
- @code{nonassoc}, @code{left} or @code{right} symbols. When
- @var{assoc-type} is @code{default-prec}, @var{assoc-value} must be
- @code{nil} or @code{t} (the default). Otherwise it is a list of
- tokens which must have been previously declared in @var{terminals}.
- For details, see @ref{Contextual Precedence, , , bison}, in the
- Bison manual.
- @item non-terminals
- Is the list of nonterminal definitions. Each definition has the form:
- @code{(@var{nonterm} . @var{rules})}
- Where @var{nonterm} is the nonterminal symbol defined and
- @var{rules} the list of rules that describe this nonterminal. Each
- rule is a list:
- @code{(@var{components} [@var{precedence}] [@var{action}])}
- Where:
- @table @var
- @item components
- Is a list of various terminals and nonterminals that are put together
- by this rule.
- For example,
- @example
- @group
- (exp ((exp ?+ exp)) ;; exp: exp '+' exp
- ) ;; ;
- @end group
- @end example
- Says that two groupings of type @samp{exp}, with a @samp{+} token in
- between, can be combined into a larger grouping of type @samp{exp}.
- @cindex grammar coding conventions
- By convention, a nonterminal symbol should be in lower case, such as
- @samp{exp}, @samp{stmt} or @samp{declaration}. Terminal symbols
- should be upper case to distinguish them from nonterminals: for
- example, @samp{INTEGER}, @samp{IDENTIFIER}, @samp{IF} or
- @samp{RETURN}. A terminal symbol that represents a particular keyword
- in the language is conventionally the same as that keyword converted
- to upper case. The terminal symbol @code{error} is reserved for error
- recovery.
- @cindex middle-rule actions
- Scattered among the components can be @dfn{middle-rule} actions.
- Usually only @var{action} is provided (@pxref{action}).
- If @var{components} in a rule is @code{nil}, it means that the rule
- can match the empty string. For example, here is how to define a
- comma-separated sequence of zero or more @samp{exp} groupings:
- @smallexample
- @group
- (expseq (nil) ;; expseq: ;; empty
- ((expseq1)) ;; | expseq1
- ) ;; ;
- (expseq1 ((exp)) ;; expseq1: exp
- ((expseq1 ?, exp)) ;; | expseq1 ',' exp
- ) ;; ;
- @end group
- @end smallexample
- @cindex precedence level
- @item precedence
- Assign the rule the precedence of the given terminal item, overriding
- the precedence that would be deduced for it, that is the one of the
- last terminal in it. Notice that only terminals declared in
- @var{assocs} have a precedence level. The altered rule precedence
- then affects how conflicts involving that rule are resolved.
- @var{precedence} is an optional vector of one terminal item.
- Here is how @var{precedence} solves the problem of unary minus.
- First, declare a precedence for a fictitious terminal symbol named
- @code{UMINUS}. There are no tokens of this type, but the symbol
- serves to stand for its precedence:
- @example
- @dots{}
- ((default-prec t) ;; This is the default
- (left '+' '-')
- (left '*')
- (left UMINUS))
- @end example
- Now the precedence of @code{UMINUS} can be used in specific rules:
- @smallexample
- @group
- (exp @dots{} ;; exp: @dots{}
- ((exp ?- exp)) ;; | exp '-' exp
- @dots{} ;; @dots{}
- ((?- exp) [UMINUS]) ;; | '-' exp %prec UMINUS
- @dots{} ;; @dots{}
- ) ;; ;
- @end group
- @end smallexample
- If you forget to append @code{[UMINUS]} to the rule for unary minus,
- Wisent silently assumes that minus has its usual precedence. This
- kind of problem can be tricky to debug, since one typically discovers
- the mistake only by testing the code.
- Using @code{(default-prec nil)} declaration makes it easier to
- discover this kind of problem systematically. It causes rules that
- lack a @var{precedence} modifier to have no precedence, even if the
- last terminal symbol mentioned in their components has a declared
- precedence.
- If @code{(default-prec nil)} is in effect, you must specify
- @var{precedence} for all rules that participate in precedence conflict
- resolution. Then you will see any shift/reduce conflict until you
- tell Wisent how to resolve it, either by changing your grammar or by
- adding an explicit precedence. This will probably add declarations to
- the grammar, but it helps to protect against incorrect rule
- precedences.
- The effect of @code{(default-prec nil)} can be reversed by giving
- @code{(default-prec t)}, which is the default.
- For more details, see @ref{Contextual Precedence, , , bison}, in the
- Bison manual.
- It is important to understand that @var{assocs} declarations defines
- associativity but also assign a precedence level to terminals. All
- terminals declared in the same @code{left}, @code{right} or
- @code{nonassoc} association get the same precedence level. The
- precedence level is increased at each new association.
- On the other hand, @var{precedence} explicitly assign the precedence
- level of the given terminal to a rule.
- @cindex semantic actions
- @item @anchor{action}action
- An action is an optional Emacs Lisp function call, like this:
- @code{(identity $1)}
- The result of an action determines the semantic value of a rule.
- From an implementation standpoint, the function call will be embedded
- in a lambda expression, and several useful local variables will be
- defined:
- @table @code
- @vindex $N
- @item $@var{n}
- Where @var{n} is a positive integer. Like in Bison, the value of
- @code{$@var{n}} is the semantic value of the @var{n}th element of
- @var{components}, starting from 1. It can be of any Lisp data
- type.
- @vindex $region@var{n}
- @item $regionN
- Where @var{n} is a positive integer. For each @code{$@var{n}}
- variable defined there is a corresponding @code{$region@var{n}}
- variable. Its value is a pair @code{(@var{start-pos} .
- @var{end-pos})} that represent the start and end positions (in the
- lexical input stream) of the @code{$@var{n}} value. It can be
- @code{nil} when the component positions are not available, like for an
- empty string component for example.
- @vindex $region
- @item $region
- Its value is the leftmost and rightmost positions of input data
- matched by all @var{components} in the rule. This is a pair
- @code{(@var{leftmost-pos} . @var{rightmost-pos})}. It can be
- @code{nil} when components positions are not available.
- @vindex $nterm
- @item $nterm
- This variable is initialized with the nonterminal symbol
- (@var{nonterm}) the rule belongs to. It could be useful to improve
- error reporting or debugging. It is also used to automatically
- provide incremental re-parse entry points for @semantic{} tags
- (@pxref{Wisent Semantic}).
- @vindex $action
- @item $action
- The value of @code{$action} is the symbolic name of the current
- semantic action (@pxref{Debugging actions}).
- @end table
- When an action is not specified a default value is supplied, it is
- @code{(identity $1)}. This means that the default semantic value of a
- rule is the value of its first component. Excepted for a rule
- matching the empty string, for which the default action is to return
- @code{nil}.
- @end table
- @end table
- @node Example
- @section Example
- @cindex grammar example
- Here is an example to parse simple infix arithmetic expressions. See
- @ref{Infix Calc, , , bison}, in the Bison manual for details.
- @lisp
- @group
- '(
- ;; Terminals
- (NUM)
- ;; Terminal associativity & precedence
- ((nonassoc ?=)
- (left ?- ?+)
- (left ?* ?/)
- (left NEG)
- (right ?^))
- ;; Rules
- (input
- ((line))
- ((input line)
- (format "%s %s" $1 $2))
- )
- (line
- ((?;)
- (progn ";"))
- ((exp ?;)
- (format "%s;" $1))
- ((error ?;)
- (progn "Error;")))
- )
- (exp
- ((NUM)
- (string-to-number $1))
- ((exp ?= exp)
- (= $1 $3))
- ((exp ?+ exp)
- (+ $1 $3))
- ((exp ?- exp)
- (- $1 $3))
- ((exp ?* exp)
- (* $1 $3))
- ((exp ?/ exp)
- (/ $1 $3))
- ((?- exp) [NEG]
- (- $2))
- ((exp ?^ exp)
- (expt $1 $3))
- ((?\( exp ?\))
- (progn $2))
- )
- )
- @end group
- @end lisp
- In the bison-like @dfn{WY} format (@pxref{Wisent Semantic}) the
- grammar looks like this:
- @example
- @group
- %token <number> NUM
- %nonassoc '=' ;; comparison
- %left '-' '+'
- %left '*' '/'
- %left NEG ;; negation--unary minus
- %right '^' ;; exponentiation
- %%
- input:
- line
- | input line
- (format "%s %s" $1 $2)
- ;
- line:
- ';'
- @{";"@}
- | exp ';'
- (format "%s;" $1)
- | error ';'
- @{"Error;"@}
- ;
- exp:
- NUM
- (string-to-number $1)
- | exp '=' exp
- (= $1 $3)
- | exp '+' exp
- (+ $1 $3)
- | exp '-' exp
- (- $1 $3)
- | exp '*' exp
- (* $1 $3)
- | exp '/' exp
- (/ $1 $3)
- | '-' exp %prec NEG
- (- $2)
- | exp '^' exp
- (expt $1 $3)
- | '(' exp ')'
- @{$2@}
- ;
- %%
- @end group
- @end example
- @node Compiling a grammar
- @section Compiling a grammar
- @cindex automaton
- After providing a context-free grammar in a suitable format, it must
- be translated into a set of tables (an @dfn{automaton}) that will be
- used to derive the parser. Like Bison, Wisent translates grammars that
- must be @dfn{LALR(1)}.
- @cindex LALR(1) grammar
- @cindex look-ahead token
- A grammar is @acronym{LALR(1)} if it is possible to tell how to parse
- any portion of an input string with just a single token of look-ahead:
- the @dfn{look-ahead token}. See @ref{Language and Grammar, , ,
- bison}, in the Bison manual for more information.
- @cindex grammar compilation
- Grammar translation (compilation) is achieved by the function:
- @cindex compiling a grammar
- @vindex wisent-single-start-flag
- @findex wisent-compile-grammar
- @defun wisent-compile-grammar grammar &optional start-list
- Compile @var{grammar} and return an @acronym{LALR(1)} automaton.
- Optional argument @var{start-list} is a list of start symbols
- (nonterminals). If @code{nil} the first nonterminal defined in the
- grammar is the default start symbol. If @var{start-list} contains
- only one element, it defines the start symbol. If @var{start-list}
- contains more than one element, all are defined as potential start
- symbols, unless @code{wisent-single-start-flag} is non-@code{nil}. In
- that case the first element of @var{start-list} defines the start
- symbol and others are ignored.
- The @acronym{LALR(1)} automaton is a vector of the form:
- @code{[@var{actions gotos starts functions}]}
- @table @var
- @item actions
- A state/token matrix telling the parser what to do at every state
- based on the current look-ahead token. That is shift, reduce, accept
- or error. See also @ref{Wisent Parsing}.
- @item gotos
- A state/nonterminal matrix telling the parser the next state to go to
- after reducing with each rule.
- @item starts
- An alist which maps the allowed start symbols (nonterminals) to
- lexical tokens that will be first shifted into the parser stack.
- @item functions
- An obarray of semantic action symbols. A semantic action is actually
- an Emacs Lisp function (lambda expression).
- @end table
- @end defun
- @node Conflicts
- @section Conflicts
- Normally, a grammar should produce an automaton where at each state
- the parser has only one action to do (@pxref{Wisent Parsing}).
- @cindex ambiguous grammar
- In certain cases, a grammar can produce an automaton where, at some
- states, there are more than one action possible. Such a grammar is
- @dfn{ambiguous}, and generates @dfn{conflicts}.
- @cindex deterministic automaton
- The parser can't be driven by an automaton which isn't completely
- @dfn{deterministic}, that is which contains conflicts. It is
- necessary to resolve the conflicts to eliminate them. Wisent resolves
- conflicts like Bison does.
- @cindex grammar conflicts
- @cindex conflicts resolution
- There are two sorts of conflicts:
- @table @dfn
- @cindex shift/reduce conflicts
- @item shift/reduce conflicts
- When either a shift or a reduction would be valid at the same state.
- Such conflicts are resolved by choosing to shift, unless otherwise
- directed by operator precedence declarations.
- See @ref{Shift/Reduce , , , bison}, in the Bison manual for more
- information.
- @cindex reduce/reduce conflicts
- @item reduce/reduce conflicts
- That occurs if there are two or more rules that apply to the same
- sequence of input. This usually indicates a serious error in the
- grammar.
- Such conflicts are resolved by choosing to use the rule that appears
- first in the grammar, but it is very risky to rely on this. Every
- reduce/reduce conflict must be studied and usually eliminated. See
- @ref{Reduce/Reduce , , , bison}, in the Bison manual for more
- information.
- @end table
- @menu
- * Grammar Debugging::
- * Understanding the automaton::
- @end menu
- @node Grammar Debugging
- @subsection Grammar debugging
- @cindex grammar debugging
- @cindex grammar verbose description
- To help writing a new grammar, @code{wisent-compile-grammar} can
- produce a verbose report containing a detailed description of the
- grammar and parser (equivalent to what Bison reports with the
- @option{--verbose} option).
- To enable the verbose report you can set to non-@code{nil} the
- variable:
- @vindex wisent-verbose-flag
- @deffn Option wisent-verbose-flag
- non-@code{nil} means to report verbose information on generated parser.
- @end deffn
- Or interactively use the command:
- @findex wisent-toggle-verbose-flag
- @deffn Command wisent-toggle-verbose-flag
- Toggle whether to report verbose information on generated parser.
- @end deffn
- The verbose report is printed in the temporary buffer
- @file{*wisent-log*} when running interactively, or in file
- @file{wisent.output} when running in batch mode. Different
- reports are separated from each other by a line like this:
- @example
- @group
- *** Wisent @var{source-file} - 2002-06-27 17:33
- @end group
- @end example
- where @var{source-file} is the name of the Emacs Lisp file from which
- the grammar was read. See @ref{Understanding the automaton}, for
- details on the verbose report.
- @table @strong
- @item Please Note
- To help debugging the grammar compiler itself, you can set this
- variable to print the content of some internal data structures:
- @vindex wisent-debug-flag
- @defvar wisent-debug-flag
- non-@code{nil} means enable some debug stuff.
- @end defvar
- @end table
- @node Understanding the automaton
- @subsection Understanding the automaton
- @cindex understanding the automaton
- This section (took from the manual of Bison 1.49) describes how to use
- the verbose report printed by @code{wisent-compile-grammar} to
- understand the generated automaton, to tune or fix a grammar.
- We will use the following example:
- @example
- @group
- (let ((wisent-verbose-flag t)) ;; Print a verbose report!
- (wisent-compile-grammar
- '((NUM STR) ; %token NUM STR
- ((left ?+ ?-) ; %left '+' '-';
- (left ?*)) ; %left '*'
- (exp ; exp:
- ((exp ?+ exp)) ; exp '+' exp
- ((exp ?- exp)) ; | exp '-' exp
- ((exp ?* exp)) ; | exp '*' exp
- ((exp ?/ exp)) ; | exp '/' exp
- ((NUM)) ; | NUM
- ) ; ;
- (useless ; useless:
- ((STR)) ; STR
- ) ; ;
- )
- 'nil) ; no %start declarations
- )
- @end group
- @end example
- When evaluating the above expression, grammar compilation first issues
- the following two clear messages:
- @example
- @group
- Grammar contains 1 useless nonterminals and 1 useless rules
- Grammar contains 7 shift/reduce conflicts
- @end group
- @end example
- The @file{*wisent-log*} buffer details things!
- The first section reports conflicts that were solved using precedence
- and/or associativity:
- @example
- @group
- Conflict in state 7 between rule 1 and token '+' resolved as reduce.
- Conflict in state 7 between rule 1 and token '-' resolved as reduce.
- Conflict in state 7 between rule 1 and token '*' resolved as shift.
- Conflict in state 8 between rule 2 and token '+' resolved as reduce.
- Conflict in state 8 between rule 2 and token '-' resolved as reduce.
- Conflict in state 8 between rule 2 and token '*' resolved as shift.
- Conflict in state 9 between rule 3 and token '+' resolved as reduce.
- Conflict in state 9 between rule 3 and token '-' resolved as reduce.
- Conflict in state 9 between rule 3 and token '*' resolved as reduce.
- @end group
- @end example
- The next section reports useless tokens, nonterminal and rules (note
- that useless tokens might be used by the scanner):
- @example
- @group
- Useless nonterminals:
- useless
- Terminals which are not used:
- STR
- Useless rules:
- #6 useless: STR;
- @end group
- @end example
- The next section lists states that still have conflicts:
- @example
- @group
- State 7 contains 1 shift/reduce conflict.
- State 8 contains 1 shift/reduce conflict.
- State 9 contains 1 shift/reduce conflict.
- State 10 contains 4 shift/reduce conflicts.
- @end group
- @end example
- The next section reproduces the grammar used:
- @example
- @group
- Grammar
- Number, Rule
- 1 exp -> exp '+' exp
- 2 exp -> exp '-' exp
- 3 exp -> exp '*' exp
- 4 exp -> exp '/' exp
- 5 exp -> NUM
- @end group
- @end example
- And reports the uses of the symbols:
- @example
- @group
- Terminals, with rules where they appear
- $EOI (-1)
- error (1)
- NUM (2) 5
- STR (3) 6
- '+' (4) 1
- '-' (5) 2
- '*' (6) 3
- '/' (7) 4
- Nonterminals, with rules where they appear
- exp (8)
- on left: 1 2 3 4 5, on right: 1 2 3 4
- @end group
- @end example
- The report then details the automaton itself, describing each state
- with it set of @dfn{items}, also known as @dfn{pointed rules}. Each
- item is a production rule together with a point (marked by @samp{.})
- that the input cursor.
- @example
- @group
- state 0
- NUM shift, and go to state 1
- exp go to state 2
- @end group
- @end example
- State 0 corresponds to being at the very beginning of the parsing, in
- the initial rule, right before the start symbol (@samp{exp}). When
- the parser returns to this state right after having reduced a rule
- that produced an @samp{exp}, it jumps to state 2. If there is no such
- transition on a nonterminal symbol, and the lookahead is a @samp{NUM},
- then this token is shifted on the parse stack, and the control flow
- jumps to state 1. Any other lookahead triggers a parse error.
- In the state 1...
- @example
- @group
- state 1
- exp -> NUM . (rule 5)
- $default reduce using rule 5 (exp)
- @end group
- @end example
- the rule 5, @samp{exp: NUM;}, is completed. Whatever the lookahead
- (@samp{$default}), the parser will reduce it. If it was coming from
- state 0, then, after this reduction it will return to state 0, and
- will jump to state 2 (@samp{exp: go to state 2}).
- @example
- @group
- state 2
- exp -> exp . '+' exp (rule 1)
- exp -> exp . '-' exp (rule 2)
- exp -> exp . '*' exp (rule 3)
- exp -> exp . '/' exp (rule 4)
- $EOI shift, and go to state 11
- '+' shift, and go to state 3
- '-' shift, and go to state 4
- '*' shift, and go to state 5
- '/' shift, and go to state 6
- @end group
- @end example
- In state 2, the automaton can only shift a symbol. For instance,
- because of the item @samp{exp -> exp . '+' exp}, if the lookahead if
- @samp{+}, it will be shifted on the parse stack, and the automaton
- control will jump to state 3, corresponding to the item
- @samp{exp -> exp . '+' exp}:
- @example
- @group
- state 3
- exp -> exp '+' . exp (rule 1)
- NUM shift, and go to state 1
- exp go to state 7
- @end group
- @end example
- Since there is no default action, any other token than those listed
- above will trigger a parse error.
- The interpretation of states 4 to 6 is straightforward:
- @example
- @group
- state 4
- exp -> exp '-' . exp (rule 2)
- NUM shift, and go to state 1
- exp go to state 8
- state 5
- exp -> exp '*' . exp (rule 3)
- NUM shift, and go to state 1
- exp go to state 9
- state 6
- exp -> exp '/' . exp (rule 4)
- NUM shift, and go to state 1
- exp go to state 10
- @end group
- @end example
- As was announced in beginning of the report, @samp{State 7 contains 1
- shift/reduce conflict.}:
- @example
- @group
- state 7
- exp -> exp . '+' exp (rule 1)
- exp -> exp '+' exp . (rule 1)
- exp -> exp . '-' exp (rule 2)
- exp -> exp . '*' exp (rule 3)
- exp -> exp . '/' exp (rule 4)
- '*' shift, and go to state 5
- '/' shift, and go to state 6
- '/' [reduce using rule 1 (exp)]
- $default reduce using rule 1 (exp)
- @end group
- @end example
- Indeed, there are two actions associated to the lookahead @samp{/}:
- either shifting (and going to state 6), or reducing rule 1. The
- conflict means that either the grammar is ambiguous, or the parser
- lacks information to make the right decision. Indeed the grammar is
- ambiguous, as, since we did not specify the precedence of @samp{/},
- the sentence @samp{NUM + NUM / NUM} can be parsed as @samp{NUM + (NUM
- / NUM)}, which corresponds to shifting @samp{/}, or as @samp{(NUM +
- NUM) / NUM}, which corresponds to reducing rule 1.
- Because in @acronym{LALR(1)} parsing a single decision can be made,
- Wisent arbitrarily chose to disable the reduction, see
- @ref{Conflicts}. Discarded actions are reported in between square
- brackets.
- Note that all the previous states had a single possible action: either
- shifting the next token and going to the corresponding state, or
- reducing a single rule. In the other cases, i.e., when shifting
- @emph{and} reducing is possible or when @emph{several} reductions are
- possible, the lookahead is required to select the action. State 7 is
- one such state: if the lookahead is @samp{*} or @samp{/} then the
- action is shifting, otherwise the action is reducing rule 1. In other
- words, the first two items, corresponding to rule 1, are not eligible
- when the lookahead is @samp{*}, since we specified that @samp{*} has
- higher precedence that @samp{+}. More generally, some items are
- eligible only with some set of possible lookaheads.
- States 8 to 10 are similar:
- @example
- @group
- state 8
- exp -> exp . '+' exp (rule 1)
- exp -> exp . '-' exp (rule 2)
- exp -> exp '-' exp . (rule 2)
- exp -> exp . '*' exp (rule 3)
- exp -> exp . '/' exp (rule 4)
- '*' shift, and go to state 5
- '/' shift, and go to state 6
- '/' [reduce using rule 2 (exp)]
- $default reduce using rule 2 (exp)
- state 9
- exp -> exp . '+' exp (rule 1)
- exp -> exp . '-' exp (rule 2)
- exp -> exp . '*' exp (rule 3)
- exp -> exp '*' exp . (rule 3)
- exp -> exp . '/' exp (rule 4)
- '/' shift, and go to state 6
- '/' [reduce using rule 3 (exp)]
- $default reduce using rule 3 (exp)
- state 10
- exp -> exp . '+' exp (rule 1)
- exp -> exp . '-' exp (rule 2)
- exp -> exp . '*' exp (rule 3)
- exp -> exp . '/' exp (rule 4)
- exp -> exp '/' exp . (rule 4)
- '+' shift, and go to state 3
- '-' shift, and go to state 4
- '*' shift, and go to state 5
- '/' shift, and go to state 6
- '+' [reduce using rule 4 (exp)]
- '-' [reduce using rule 4 (exp)]
- '*' [reduce using rule 4 (exp)]
- '/' [reduce using rule 4 (exp)]
- $default reduce using rule 4 (exp)
- @end group
- @end example
- Observe that state 10 contains conflicts due to the lack of precedence
- of @samp{/} wrt @samp{+}, @samp{-}, and @samp{*}, but also because the
- associativity of @samp{/} is not specified.
- Finally, the state 11 (plus 12) is named the @dfn{final state}, or the
- @dfn{accepting state}:
- @example
- @group
- state 11
- $EOI shift, and go to state 12
- state 12
- $default accept
- @end group
- @end example
- The end of input is shifted @samp{$EOI shift,} and the parser exits
- successfully (@samp{go to state 12}, that terminates).
- @node Wisent Parsing
- @chapter Wisent Parsing
- @cindex bottom-up parser
- @cindex shift-reduce parser
- The Wisent's parser is what is called a @dfn{bottom-up} or
- @dfn{shift-reduce} parser which repeatedly:
- @table @dfn
- @cindex shift
- @item shift
- That is pushes the value of the last lexical token read (the
- look-ahead token) into a value stack, and reads a new one.
- @cindex reduce
- @item reduce
- That is replaces a nonterminal by its semantic value. The values of
- the components which form the right hand side of a rule are popped
- from the value stack and reduced by the semantic action of this rule.
- The result is pushed back on top of value stack.
- @end table
- The parser will stop on:
- @table @dfn
- @cindex accept
- @item accept
- When all input has been successfully parsed. The semantic value of
- the start nonterminal is on top of the value stack.
- @cindex syntax error
- @item error
- When a syntax error (an unexpected token in input) has been detected.
- At this point the parser issues an error message and either stops or
- calls a recovery routine to try to resume parsing.
- @end table
- @cindex table-driven parser
- The above elementary actions are driven by the @acronym{LALR(1)}
- automaton built by @code{wisent-compile-grammar} from a context-free
- grammar.
- The Wisent's parser is entered by calling the function:
- @findex wisent-parse
- @defun wisent-parse automaton lexer &optional error start
- Parse input using the automaton specified in @var{automaton}.
- @table @var
- @item automaton
- Is an @acronym{LALR(1)} automaton generated by
- @code{wisent-compile-grammar} (@pxref{Wisent Grammar}).
- @item lexer
- Is a function with no argument called by the parser to obtain the next
- terminal (token) in input (@pxref{Writing a lexer}).
- @item error
- Is an optional reporting function called when a parse error occurs.
- It receives a message string to report. It defaults to the function
- @code{wisent-message} (@pxref{Report errors}).
- @item start
- Specify the start symbol (nonterminal) used by the parser as its goal.
- It defaults to the start symbol defined in the grammar
- (@pxref{Wisent Grammar}).
- @end table
- @end defun
- The following two normal hooks permit doing some useful processing
- respectively before starting parsing, and after the parser terminated.
- @vindex wisent-pre-parse-hook
- @defvar wisent-pre-parse-hook
- Normal hook run just before entering the @var{LR} parser engine.
- @end defvar
- @vindex wisent-post-parse-hook
- @defvar wisent-post-parse-hook
- Normal hook run just after the @var{LR} parser engine terminated.
- @end defvar
- @menu
- * Writing a lexer::
- * Actions goodies::
- * Report errors::
- * Error recovery::
- * Debugging actions::
- @end menu
- @node Writing a lexer
- @section What the parser must receive
- It is important to understand that the parser does not parse
- characters, but lexical tokens, and does not know anything about
- characters in text streams!
- @cindex lexical analysis
- @cindex lexer
- @cindex scanner
- Reading input data to produce lexical tokens is performed by a lexer
- (also called a scanner) in a lexical analysis step, before the syntax
- analysis step performed by the parser. The parser automatically calls
- the lexer when it needs the next token to parse.
- @cindex lexical tokens
- A Wisent's lexer is an Emacs Lisp function with no argument. It must
- return a valid lexical token of the form:
- @code{(@var{token-class value} [@var{start} . @var{end}])}
- @table @var
- @item token-class
- Is a category of lexical token identifying a terminal as specified in
- the grammar (@pxref{Wisent Grammar}). It can be a symbol or a character
- literal.
- @item value
- Is the value of the lexical token. It can be of any valid Emacs Lisp
- data type.
- @item start
- @itemx end
- Are the optional beginning and ending positions of @var{value} in the
- input stream.
- @end table
- When there are no more tokens to read the lexer must return the token
- @code{(list wisent-eoi-term)} to each request.
- @vindex wisent-eoi-term
- @defvar wisent-eoi-term
- Predefined constant, End-Of-Input terminal symbol.
- @end defvar
- @code{wisent-lex} is an example of a lexer that reads lexical tokens
- produced by a @semantic{} lexer, and translates them into lexical tokens
- suitable to the Wisent parser. See also @ref{Wisent Lex}.
- To call the lexer in a semantic action use the function
- @code{wisent-lexer}. See also @ref{Actions goodies}.
- @node Actions goodies
- @section Variables and macros useful in grammar actions.
- @vindex wisent-input
- @defvar wisent-input
- The last token read.
- This variable only has meaning in the scope of @code{wisent-parse}.
- @end defvar
- @findex wisent-lexer
- @defun wisent-lexer
- Obtain the next terminal in input.
- @end defun
- @findex wisent-region
- @defun wisent-region &rest positions
- Return the start/end positions of the region including
- @var{positions}. Each element of @var{positions} is a pair
- @w{@code{(@var{start-pos} . @var{end-pos})}} or @code{nil}. The
- returned value is the pair @w{@code{(@var{min-start-pos} .
- @var{max-end-pos})}} or @code{nil} if no @var{positions} are
- available.
- @end defun
- @node Report errors
- @section The error reporting function
- @cindex error reporting
- When the parser encounters a syntax error it calls a user-defined
- function. It must be an Emacs Lisp function with one argument: a
- string containing the message to report.
- By default the parser uses this function to report error messages:
- @findex wisent-message
- @defun wisent-message string &rest args
- Print a one-line message if @code{wisent-parse-verbose-flag} is set.
- Pass @var{string} and @var{args} arguments to @dfn{message}.
- @end defun
- @table @strong
- @item Please Note:
- @code{wisent-message} uses the following function to print lexical
- tokens:
- @defun wisent-token-to-string token
- Return a printed representation of lexical token @var{token}.
- @end defun
- The general printed form of a lexical token is:
- @w{@code{@var{token}(@var{value})@@@var{location}}}
- @end table
- To control the verbosity of the parser you can set to non-@code{nil}
- this variable:
- @vindex wisent-parse-verbose-flag
- @deffn Option wisent-parse-verbose-flag
- non-@code{nil} means to issue more messages while parsing.
- @end deffn
- Or interactively use the command:
- @findex wisent-parse-toggle-verbose-flag
- @deffn Command wisent-parse-toggle-verbose-flag
- Toggle whether to issue more messages while parsing.
- @end deffn
- When the error reporting function is entered the variable
- @code{wisent-input} contains the unexpected token as returned by the
- lexer.
- The error reporting function can be called from a semantic action too
- using the special macro @code{wisent-error}. When called from a
- semantic action entered by error recovery (@pxref{Error recovery}) the
- value of the variable @code{wisent-recovering} is non-@code{nil}.
- @node Error recovery
- @section Error recovery
- @cindex error recovery
- The error recovery mechanism of the Wisent's parser conforms to the
- one Bison uses. See @ref{Error Recovery, , , bison}, in the Bison
- manual for details.
- @cindex error token
- To recover from a syntax error you must write rules to recognize the
- special token @code{error}. This is a terminal symbol that is
- automatically defined and reserved for error handling.
- When the parser encounters a syntax error, it pops the state stack
- until it finds a state that allows shifting the @code{error} token.
- After it has been shifted, if the old look-ahead token is not
- acceptable to be shifted next, the parser reads tokens and discards
- them until it finds a token which is acceptable.
- @cindex error recovery strategy
- Strategies for error recovery depend on the choice of error rules in
- the grammar. A simple and useful strategy is simply to skip the rest
- of the current statement if an error is detected:
- @example
- @group
- (statement (( error ?; )) ;; on error, skip until ';' is read
- )
- @end group
- @end example
- It is also useful to recover to the matching close-delimiter of an
- opening-delimiter that has already been parsed:
- @example
- @group
- (primary (( ?@{ expr ?@} ))
- (( ?@{ error ?@} ))
- @dots{}
- )
- @end group
- @end example
- @cindex error recovery actions
- Note that error recovery rules may have actions, just as any other
- rules can. Here are some predefined hooks, variables, functions or
- macros, useful in such actions:
- @vindex wisent-nerrs
- @defvar wisent-nerrs
- The number of parse errors encountered so far.
- @end defvar
- @vindex wisent-recovering
- @defvar wisent-recovering
- non-@code{nil} means that the parser is recovering.
- This variable only has meaning in the scope of @code{wisent-parse}.
- @end defvar
- @findex wisent-error
- @defun wisent-error msg
- Call the user supplied error reporting function with message
- @var{msg} (@pxref{Report errors}).
- For an example of use, @xref{wisent-skip-token}.
- @end defun
- @findex wisent-errok
- @defun wisent-errok
- Resume generating error messages immediately for subsequent syntax
- errors.
- The parser suppress error message for syntax errors that happens
- shortly after the first, until three consecutive input tokens have
- been successfully shifted.
- Calling @code{wisent-errok} in an action, make error messages resume
- immediately. No error messages will be suppressed if you call it in
- an error rule's action.
- For an example of use, @xref{wisent-skip-token}.
- @end defun
- @findex wisent-clearin
- @defun wisent-clearin
- Discard the current lookahead token.
- This will cause a new lexical token to be read.
- In an error rule's action the previous lookahead token is reanalyzed
- immediately. @code{wisent-clearin} may be called to clear this token.
- For example, suppose that on a parse error, an error handling routine
- is called that advances the input stream to some point where parsing
- should once again commence. The next symbol returned by the lexical
- scanner is probably correct. The previous lookahead token ought to
- be discarded with @code{wisent-clearin}.
- For an example of use, @xref{wisent-skip-token}.
- @end defun
- @findex wisent-abort
- @defun wisent-abort
- Abort parsing and save the lookahead token.
- @end defun
- @findex wisent-set-region
- @defun wisent-set-region start end
- Change the region of text matched by the current nonterminal.
- @var{start} and @var{end} are respectively the beginning and end
- positions of the region occupied by the group of components associated
- to this nonterminal. If @var{start} or @var{end} values are not a
- valid positions the region is set to @code{nil}.
- For an example of use, @xref{wisent-skip-token}.
- @end defun
- @vindex wisent-discarding-token-functions
- @defvar wisent-discarding-token-functions
- List of functions to be called when discarding a lexical token.
- These functions receive the lexical token discarded.
- When the parser encounters unexpected tokens, it can discards them,
- based on what directed by error recovery rules. Either when the
- parser reads tokens until one is found that can be shifted, or when an
- semantic action calls the function @code{wisent-skip-token} or
- @code{wisent-skip-block}.
- For language specific hooks, make sure you define this as a local
- hook.
- For example, in @semantic{}, this hook is set to the function
- @code{wisent-collect-unmatched-syntax} to collect unmatched lexical
- tokens (@pxref{Useful functions}).
- @end defvar
- @findex wisent-skip-token
- @defun wisent-skip-token
- @anchor{wisent-skip-token}
- Skip the lookahead token in order to resume parsing.
- Return @code{nil}.
- Must be used in error recovery semantic actions.
- It typically looks like this:
- @lisp
- @group
- (wisent-message "%s: skip %s" $action
- (wisent-token-to-string wisent-input))
- (run-hook-with-args
- 'wisent-discarding-token-functions wisent-input)
- (wisent-clearin)
- (wisent-errok)))
- @end group
- @end lisp
- @end defun
- @findex wisent-skip-block
- @defun wisent-skip-block
- Safely skip a block in order to resume parsing.
- Return @code{nil}.
- Must be used in error recovery semantic actions.
- A block is data between an open-delimiter (syntax class @code{(}) and
- a matching close-delimiter (syntax class @code{)}):
- @example
- @group
- (a parenthesized block)
- [a block between brackets]
- @{a block between braces@}
- @end group
- @end example
- The following example uses @code{wisent-skip-block} to safely skip a
- block delimited by @samp{LBRACE} (@code{@{}) and @samp{RBRACE}
- (@code{@}}) tokens, when a syntax error occurs in
- @samp{other-components}:
- @example
- @group
- (block ((LBRACE other-components RBRACE))
- ((LBRACE RBRACE))
- ((LBRACE error)
- (wisent-skip-block))
- )
- @end group
- @end example
- @end defun
- @node Debugging actions
- @section Debugging semantic actions
- @cindex semantic action symbols
- Each semantic action is represented by a symbol interned in an
- @dfn{obarray} that is part of the @acronym{LALR(1)} automaton
- (@pxref{Compiling a grammar}). @code{symbol-function} on a semantic
- action symbol return the semantic action lambda expression.
- A semantic action symbol name has the form
- @code{@var{nonterminal}:@var{index}}, where @var{nonterminal} is the
- name of the nonterminal symbol the action belongs to, and @var{index}
- is an action sequence number within the scope of @var{nonterminal}.
- For example, this nonterminal definition:
- @example
- @group
- input:
- line [@code{input:0}]
- | input line
- (format "%s %s" $1 $2) [@code{input:1}]
- ;
- @end group
- @end example
- Will produce two semantic actions, and associated symbols:
- @table @code
- @item input:0
- A default action that returns @code{$1}.
- @item input:1
- That returns @code{(format "%s %s" $1 $2)}.
- @end table
- @cindex debugging semantic actions
- Debugging uses the Lisp debugger to investigate what is happening
- during execution of semantic actions.
- Three commands are available to debug semantic actions. They receive
- two arguments:
- @itemize @bullet
- @item The automaton that contains the semantic action.
- @item The semantic action symbol.
- @end itemize
- @findex wisent-debug-on-entry
- @deffn Command wisent-debug-on-entry automaton function
- Request @var{automaton}'s @var{function} to invoke debugger each time it is called.
- @var{function} must be a semantic action symbol that exists in @var{automaton}.
- @end deffn
- @findex wisent-cancel-debug-on-entry
- @deffn Command wisent-cancel-debug-on-entry automaton function
- Undo effect of @code{wisent-debug-on-entry} on @var{automaton}'s @var{function}.
- @var{function} must be a semantic action symbol that exists in @var{automaton}.
- @end deffn
- @findex wisent-debug-show-entry
- @deffn Command wisent-debug-show-entry automaton function
- Show the source of @var{automaton}'s semantic action @var{function}.
- @var{function} must be a semantic action symbol that exists in @var{automaton}.
- @end deffn
- @node Wisent Semantic
- @chapter How to use Wisent with Semantic
- @cindex tags
- This section presents how the Wisent's parser can be used to produce
- @dfn{tags} for the @semantic{} tool set.
- @semantic{} tags form a hierarchy of Emacs Lisp data structures that
- describes a program in a way independent of programming languages.
- Tags map program declarations, like functions, methods, variables,
- data types, classes, includes, grammar rules, etc..
- @cindex WY grammar format
- To use the Wisent parser with @semantic{} you have to define
- your grammar in @dfn{WY} form, a grammar format very close
- to the one used by Bison.
- Please @inforef{top, Semantic Grammar Framework Manual, grammar-fw}
- for more information on @semantic{} grammars.
- @menu
- * Grammar styles::
- * Wisent Lex::
- @end menu
- @node Grammar styles
- @section Grammar styles
- @cindex grammar styles
- @semantic{} parsing heavily depends on how you wrote the grammar.
- There are mainly two styles to write a Wisent's grammar intended to be
- used with the @semantic{} tool set: the @dfn{Iterative style} and the
- @dfn{Bison style}. Each one has pros and cons, and in certain cases
- it can be worth a mix of the two styles!
- @menu
- * Iterative style::
- * Bison style::
- * Mixed style::
- * Start nonterminals::
- * Useful functions::
- @end menu
- @node Iterative style
- @subsection Iterative style
- @cindex grammar iterative style
- The @dfn{iterative style} is the preferred style to use with @semantic{}.
- It relies on an iterative parser back-end mechanism which parses start
- nonterminals one at a time and automagically skips unexpected lexical
- tokens in input.
- Compared to rule-based iterative functions (@pxref{Bison style}),
- iterative parsers are better in that they can handle obscure errors
- more cleanly.
- @cindex raw tag
- Each start nonterminal must produces a @dfn{raw tag} by calling a
- @code{TAG}-like grammar macro with appropriate parameters. See also
- @ref{Start nonterminals}.
- @cindex expanded tag
- Then, each parsing iteration automatically translates a raw tag into
- @dfn{expanded tags}, updating the raw tag structure with internal
- properties and buffer related data.
- After parsing completes, it results in a tree of expanded tags.
- The following example is a snippet of the iterative style Java grammar
- provided in the @semantic{} distribution in the file
- @file{semantic/wisent/java-tags.wy}.
- @example
- @group
- @dots{}
- ;; Alternate entry points
- ;; - Needed by partial re-parse
- %start formal_parameter
- @dots{}
- ;; - Needed by EXPANDFULL clauses
- %start formal_parameters
- @dots{}
- formal_parameter_list
- : PAREN_BLOCK
- (EXPANDFULL $1 formal_parameters)
- ;
- formal_parameters
- : LPAREN
- ()
- | RPAREN
- ()
- | formal_parameter COMMA
- | formal_parameter RPAREN
- ;
- formal_parameter
- : formal_parameter_modifier_opt type variable_declarator_id
- (VARIABLE-TAG $3 $2 nil :typemodifiers $1)
- ;
- @end group
- @end example
- @findex EXPANDFULL
- It shows the use of the @code{EXPANDFULL} grammar macro to parse a
- @samp{PAREN_BLOCK} which contains a @samp{formal_parameter_list}.
- @code{EXPANDFULL} tells to recursively parse @samp{formal_parameters}
- inside @samp{PAREN_BLOCK}. The parser iterates until it digested all
- available input data inside the @samp{PAREN_BLOCK}, trying to match
- any of the @samp{formal_parameters} rules:
- @itemize
- @item @samp{LPAREN}
- @item @samp{RPAREN}
- @item @samp{formal_parameter COMMA}
- @item @samp{formal_parameter RPAREN}
- @end itemize
- At each iteration it will return a @samp{formal_parameter} raw tag,
- or @code{nil} to skip unwanted (single @samp{LPAREN} or @samp{RPAREN}
- for example) or unexpected input data. Those raw tags will be
- automatically expanded by the iterative back-end parser.
- @node Bison style
- @subsection Bison style
- @cindex grammar bison style
- What we call the @dfn{Bison style} is the traditional style of Bison's
- grammars. Compared to iterative style, it is not straightforward to
- use grammars written in Bison style in @semantic{}. Mainly because such
- grammars are designed to parse the whole input data in one pass, and
- don't use the iterative parser back-end mechanism (@pxref{Iterative
- style}). With Bison style the parser is called once to parse the
- grammar start nonterminal.
- The following example is a snippet of the Bison style Java grammar
- provided in the @semantic{} distribution in the file
- @file{semantic/wisent/java.wy}.
- @example
- @group
- %start formal_parameter
- @dots{}
- formal_parameter_list
- : formal_parameter_list COMMA formal_parameter
- (cons $3 $1)
- | formal_parameter
- (list $1)
- ;
- formal_parameter
- : formal_parameter_modifier_opt type variable_declarator_id
- (EXPANDTAG
- (VARIABLE-TAG $3 $2 :typemodifiers $1)
- )
- ;
- @end group
- @end example
- The first consequence is that syntax errors are not automatically
- handled by @semantic{}. Thus, it is necessary to explicitly handle
- them at the grammar level, providing error recovery rules to skip
- unexpected input data.
- The second consequence is that the iterative parser can't do automatic
- tag expansion, except for the start nonterminal value. It is
- necessary to explicitly expand tags from concerned semantic actions by
- calling the grammar macro @code{EXPANDTAG} with a raw tag as
- parameter. See also @ref{Start nonterminals}, for incremental
- re-parse considerations.
- @node Mixed style
- @subsection Mixed style
- @cindex grammar mixed style
- @example
- @group
- %start grammar
- ;; Reparse
- %start prologue epilogue declaration nonterminal rule
- @dots{}
- %%
- grammar:
- prologue
- | epilogue
- | declaration
- | nonterminal
- | PERCENT_PERCENT
- ;
- @dots{}
- nonterminal:
- SYMBOL COLON rules SEMI
- (TAG $1 'nonterminal :children $3)
- ;
- rules:
- lifo_rules
- (apply 'nconc (nreverse $1))
- ;
- lifo_rules:
- lifo_rules OR rule
- (cons $3 $1)
- | rule
- (list $1)
- ;
- rule:
- rhs
- (let* ((rhs $1)
- name type comps prec action elt)
- @dots{}
- (EXPANDTAG
- (TAG name 'rule :type type :value comps :prec prec :expr action)
- ))
- ;
- @end group
- @end example
- This example shows how iterative and Bison styles can be combined in
- the same grammar to obtain a good compromise between grammar
- complexity and an efficient parsing strategy in an interactive
- environment.
- @samp{nonterminal} is parsed using iterative style via the main
- @samp{grammar} rule. The semantic action uses the @code{TAG} macro to
- produce a raw tag, automagically expanded by @semantic{}.
- But @samp{rules} part is parsed in Bison style! Why?
- Rule delimiters are the colon (@code{:}), that follows the nonterminal
- name, and a final semicolon (@code{;}). Unfortunately these
- delimiters are not @code{open-paren}/@code{close-paren} type, and the
- Emacs' syntactic analyzer can't easily isolate data between them to
- produce a @samp{RULES_PART} parenthesis-block-like lexical token.
- Consequently it is not possible to use @code{EXPANDFULL} to iterate in
- @samp{RULES_PART}, like this:
- @example
- @group
- nonterminal:
- SYMBOL COLON rules SEMI
- (TAG $1 'nonterminal :children $3)
- ;
- rules:
- RULES_PART ;; @strong{Map a parenthesis-block-like lexical token}
- (EXPANDFULL $1 'rules)
- ;
- rules:
- COLON
- ()
- OR
- ()
- SEMI
- ()
- rhs
- rhs
- (let* ((rhs $1)
- name type comps prec action elt)
- @dots{}
- (TAG name 'rule :type type :value comps :prec prec :expr action)
- )
- ;
- @end group
- @end example
- In such cases, when it is difficult for Emacs to obtain
- parenthesis-block-like lexical tokens, the best solution is to use the
- traditional Bison style with error recovery!
- In some extreme cases, it can also be convenient to extend the lexer,
- to deliver new lexical tokens, to simplify the grammar.
- @node Start nonterminals
- @subsection Start nonterminals
- @cindex start nonterminals
- @cindex @code{reparse-symbol} property
- When you write a grammar for @semantic{}, it is important to carefully
- indicate the start nonterminals. Each one defines an entry point in
- the grammar, and after parsing its semantic value is returned to the
- back-end iterative engine. Consequently:
- @strong{The semantic value of a start nonterminal must be a produced
- by a TAG like grammar macro}.
- Start nonterminals are declared by @code{%start} statements. When
- nothing is specified the first nonterminal that appears in the grammar
- is the start nonterminal.
- Generally, the following nonterminals must be declared as start
- symbols:
- @itemize @bullet
- @item The main grammar entry point
- @quotation
- Of course!
- @end quotation
- @item nonterminals passed to @code{EXPAND}/@code{EXPANDFULL}
- @quotation
- These grammar macros recursively parse a part of input data, based on
- rules of the given nonterminal.
- For example, the following will parse @samp{PAREN_BLOCK} data using
- the @samp{formal_parameters} rules:
- @example
- @group
- formal_parameter_list
- : PAREN_BLOCK
- (EXPANDFULL $1 formal_parameters)
- ;
- @end group
- @end example
- The semantic value of @samp{formal_parameters} becomes the value of
- the @code{EXPANDFULL} expression. It is a list of @semantic{} tags
- spliced in the tags tree.
- Because the automaton must know that @samp{formal_parameters} is a
- start symbol, you must declare it like this:
- @example
- @group
- %start formal_parameters
- @end group
- @end example
- @end quotation
- @end itemize
- @cindex incremental re-parse
- @cindex reparse-symbol
- The @code{EXPANDFULL} macro has a side effect it is important to know,
- related to the incremental re-parse mechanism of @semantic{}: the
- nonterminal symbol parameter passed to @code{EXPANDFULL} also becomes
- the @code{reparse-symbol} property of the tag returned by the
- @code{EXPANDFULL} expression.
- When buffer's data mapped by a tag is modified, @semantic{}
- schedules an incremental re-parse of that data, using the tag's
- @code{reparse-symbol} property as start nonterminal.
- @strong{The rules associated to such start symbols must be carefully
- reviewed to ensure that the incremental parser will work!}
- Things are a little bit different when the grammar is written in Bison
- style.
- @strong{The @code{reparse-symbol} property is set to the nonterminal
- symbol the rule that explicitly uses @code{EXPANDTAG} belongs to.}
- For example:
- @example
- @group
- rule:
- rhs
- (let* ((rhs $1)
- name type comps prec action elt)
- @dots{}
- (EXPANDTAG
- (TAG name 'rule :type type :value comps :prec prec :expr action)
- ))
- ;
- @end group
- @end example
- Set the @code{reparse-symbol} property of the expanded tag to
- @samp{rule}. A important consequence is that:
- @strong{Every nonterminal having any rule that calls @code{EXPANDTAG}
- in a semantic action, should be declared as a start symbol!}
- @node Useful functions
- @subsection Useful functions
- Here is a description of some predefined functions it might be useful
- to know when writing new code to use Wisent in @semantic{}:
- @findex wisent-collect-unmatched-syntax
- @defun wisent-collect-unmatched-syntax input
- Add @var{input} lexical token to the cache of unmatched tokens, in
- variable @code{semantic-unmatched-syntax-cache}.
- See implementation of the function @code{wisent-skip-token} in
- @ref{Error recovery}, for an example of use.
- @end defun
- @node Wisent Lex
- @section The Wisent Lex lexer
- @findex semantic-lex
- The lexical analysis step of @semantic{} is performed by the general
- function @code{semantic-lex}. For more information, @inforef{Writing
- Lexers, ,semantic-langdev}.
- @code{semantic-lex} produces lexical tokens of the form:
- @example
- @group
- @code{(@var{token-class start} . @var{end})}
- @end group
- @end example
- @table @var
- @item token-class
- Is a symbol that identifies a lexical token class, like @code{symbol},
- @code{string}, @code{number}, or @code{PAREN_BLOCK}.
- @item start
- @itemx end
- Are the start and end positions of mapped data in the input buffer.
- @end table
- The Wisent's parser doesn't depend on the nature of analyzed input
- stream (buffer, string, etc.), and requires that lexical tokens have a
- different form (@pxref{Writing a lexer}):
- @example
- @group
- @code{(@var{token-class value} [@var{start} . @var{end}])}
- @end group
- @end example
- @cindex lexical token mapping
- @code{wisent-lex} is the default Wisent's lexer used in @semantic{}.
- @vindex wisent-lex-istream
- @findex wisent-lex
- @defun wisent-lex
- Return the next available lexical token in Wisent's form.
- The variable @code{wisent-lex-istream} contains the list of lexical
- tokens produced by @code{semantic-lex}. Pop the next token available
- and convert it to a form suitable for the Wisent's parser.
- @end defun
- Mapping of lexical tokens as produced by @code{semantic-lex} into
- equivalent Wisent lexical tokens is straightforward:
- @example
- @group
- (@var{token-class start} . @var{end})
- @result{} (@var{token-class value start} . @var{end})
- @end group
- @end example
- @var{value} is the input @code{buffer-substring} from @var{start} to
- @var{end}.
- @node GNU Free Documentation License
- @appendix GNU Free Documentation License
- @include doclicense.texi
- @node Index
- @unnumbered Index
- @printindex cp
- @iftex
- @contents
- @summarycontents
- @end iftex
- @bye
- @c Following comments are for the benefit of ispell.
- @c LocalWords: Wisent automagically wisent Wisent's LALR obarray
|