📄 preccx.1
字号:
The following macros can be set if required:.IP # define READBUFFERSIZE length.PP(default 2048) This defines the lookahead token buffer length. No morethan <length> tokens can appear between cut marks (`!') in the script,as without cut indicators, preccx cannot know if the parser might laterbacktrack or not, and will not embed buffer reset instructions (in v2.41and later versions, \fIpreccx\fP will attempt to increase the buffer inREADBUFFERSIZE increments when necessary, so it is not a hard limit)..IP # define MAXPROGRAMSIZE length.PP(default 4096) This defines the maximum length of the internal programbuilt by parsers in order to execute attached actions..IP # define STACKSIZE length.PP(default 0) This defines the size of a runtime stack formerly used tomanipulate attached attributes in versions prior to 2.41 and it is nowobsolete. The usage was approximately proportional to nesting depthin productions. The stack can be re-enabled by setting the STACKSIZEto some positive amount. The V(n) macro can then be used to access it..PPIt can be safely left as 0 in code generated by preccx 2.41 and above..IP # define CONTEXTSTACKSIZE length.PP(default 1024) This defines the number of breakpoints that can be heldfor backtracking. Usage is proportional to the number of sequents inproductions between cuts..IP# define C_STACKSIZE length.PP(default 0x7FFF or 32K) This is the C call stack..PPNow for the horrors of synthetic attributes. To get a parser generatedby \fIpreccx\fP to do anything significant, you need either to get it tosynthesise a data structure, or get it to generate outputs. Whichever,you usually need to scatter \fIactions\fP and \fIattributes\fP throughthe script. There are two styles of script to get to know:(a) old \fIyacc\fP(1)-style scripts, in which attributes are referred to bynumber, and (b) new style scripts, in which synthesized attributes are referred to by name..PPActions are pieces of C code (terminated by a semi-colon) and placedbetween a pair of bracket-colons (`{:\0...\0:}') in the grammar definitionscript. For example, this action uses old-style \fIyacc\fP(1) numericalreferences to build a numerical value which it stashes in a C globalvariable:.IP @ addexpr = expr <'+'> expr {: total=$1+$3; :}.PPIn the new style of named reference, this would be rendered as follows:.IP @ addexpr = expr\\x <'+'> expr\\y {: total=$x+$y; :}.IPIf the computed value is to be attached as an attribute for the parse,this can be rendered as follows:.IP.@ addexpr = expr\\x <'+'> expr\\y {@ $x+$y @}.PPA newly attached attribute can then be used as an inheritedparameter in the rest of the parse: .IP @ sum(subtotal) = addexpr\\x <'+'> sum(subtotal+$x) @ \0\0\0\0\0\0\0\0\0\0\0\0\0\0 | \0....PPIn contrast, the value of total generated in the action is notavailable to the parse because actions execute later than the parsetime. The value is available to later actions, however. And it is available in the parse once the next cut mark '!' in the script hasbeen passed. .PPIn the action, `$1' is the value attached to the leftmost term, and `$3'is that attached to the rightmost term. The `$1' may be replaced by theexplicit `*(VALUE*)p_1' within C macros (their contents are not directlyaccessible to preccx and this is what `$1' expands to) in version 2.41and above. In earlier versions than 2.41, `V(1)' is the appropriatereplacement to use..PP`Values' attached to each term of a \fIpreccx\fP expression are an appropriateway to think of what is going on. Note that the full \fIyacc\fP(1) style ofscript, with attribute assignments mixed into the action code viathe `$$' pseudo-variable, is only supported until v2.40 and no later.Moreover, the \fIyacc\fP-style numerical referencing via `$1', `$2' and soon, from v2.41 on requires the `-old' command line switch to preccx. In previous versions of \fIpreccx\fP, it was supported withoutrestriction..PPEarlier versions of preccx than version 2.41 used a runtime interpreter(like yacc(1)) and a dynamic stack to implement the synthesizedattributes. Version 2.41 and above compiles the attributes instead.The difference makes for some slight incompatibilities with yacc(1):the $0 reference now makes no sense, for example. It used to refer tothe attribute attached to the term just seen to the left and wasavailable below on the dynamic stack. But in a compiled model, itis simply out of scope. .SH A BIT OF HISTORYIn version 1.5 to 2.40, \fIpreccx\fP generated code to shift the frame ofreference in a runtime attribute stack automatically. This was setby `call_mode=0' (the default) in the BEGIN macro. In earlierversions, or if `call_mode=1' was set, frame shifts had to be codedexplicitly in the script: this would be accomplished by including aVV(n) call early in the action attached to each clause. For example, athree term clause would need a VV(3) call. After the call (incall_mode=1 mode) the $n values would be correctly aligned with thegrammar expressions, and without it, they would not be. The value to beassociated with the whole expression was written into $1. Writing VV(3)=$2 was shorthand for VV(3);$1=$2. After version 1.5 andwith `call_mode=0' set, the explicit VV(3) was not required and theattribute build could be coded as $1=$2 alone. Or, for compatabilitywith \fIyacc\fP(1), as $$=$2..PPThis was all exactly equivalent to the treatment in the Unix \fIyacc\fP(1)utility, and it allowed you to incorporate the same incomprehensibletricks of pulling values off the stack when they were notionally`further to the left' than the scope of the current expression, using $0or even lower references..PPTo recap, in versions 1.50 to 2.40 the user had to choose a `call mode'which controlled the way the stack of attributes is handled at run time.Using the default call_mode=0 mode, stack frame shifts were automaticand it was not necessary to set VV(n) (shift value stack by n) commandsin actions. If call_mode=1, then stack shifts were left to the user,and VV(n) instructions had to be added explicitly to actions. Fromversion 2.41 up `call mode' is entirely obsolete so you can forgetit!.PPIn earlier versions than 1.50, the only call mode was call_mode=1.The call mode in later versions was set by: .IPcall_mode = 0 (automatic); or 1 (user-directed);.PPin the BEGIN macro, to be #defined before the #include <cc.h> or<ccx.h> in the script. In version 2.41 none of this is necessary asthe attributes are handled in the C runtime call stack, which islooked after by C. You can #define STACKSIZE 0 (to remove the stackentirely, to save space), all this also before the #include <cc.h> or<ccx.h> directive..PPHistory off..SH ATTRIBUTESIn version 2.41 and above, the job of building synthetic attributes hasbeen hived off into the parser proper. Synthetic attributes are anynon-side-effecting expression, possibly involving the dollarvariables which denote the values of attributes of other terms in aclause. They are written within {@ ... @} symbols. The last attribute in aclause becomes the attribute of a clause. For example:.IP@ tree = <'('> tree\\x <')'> tree\\y {@ mknode($x,$y) @}.IP@ \0\0\0\0 | ....PPis sufficient to build a simple parse tree for bracketed input. Notehowever that the attribute should be non-side-effecting. It may becalled several times in a parse. Since compound structures have to bebuilt via side-effects in C, each call to mknode will have to check itsarguments to see whether it has been called before, and to return thepreviously built structure if it has. It will have to do its ownmemoizing. On the other hand, rebuilding the structure several timesbecomes an allowable strategy when garbage collection takes place oftenenough to reclaim wasted structures. Either technique removes visibleside-effects. .SH ACTIONSReal side-effects that the parse is intended to invoke are coded in allversions of \fIpreccx\fP as actions between {:...:} pairs, analogouslyto \fIyacc\fP(1). Side-effecting actions need a little explanation.Because \fIpreccx\fP is an infinite look-ahead parser, it cannotexecute actions at the same time as it reads input. It might have tolater backtrack across its parse, and, whilst it might deconstruct datastructures built up in the parse, it is certainly impossible, forexample, to undo any writes to \fIstdout\fP which might have occurred..PPSo \fIpreccx\fP builds a program as it parses. When the parse finishescorrectly, the program is executed by an internal engine, but if the parseis unsuccessful or has to be backtracked, the program is `unbuilt' beforeits actions are executed. This program is a linear sequence of C code actionswhich have been specified in the \fIpreccx\fP definition file. Thus thespecification:.IP @abc=a\0b\0c\0{:printf("D");:}.IP @a=<'a'>\0{:printf("A");:}.IP @b=<'b'>\0{:printf("B");:}.IP @c=<'c'>\0{:printf("C");:}.PPwill, upon receiving input "abc", generate the program.IP printf("A");printf("B");printf("C");printf("D");.PPto be executed later.Thus actions attached to a sequence expression may be thought of as occurringimmediately after the actions attached to sub-expressions, and so ondown. That explanation should enable you to generate side-effects inthe correct sequence..PPAs remarked above, in version 1.50 to 2.40 of \fIpreccx\fP, attributes werebuilt in the side-effecting actions, in yacc(1) style. In version 2.41 andabove, attributes are attached using the new {@foo@} notation. Thisis certainly mechanically more robust, and it ought to be conceptuallycleaner too. Attributes need the {@ @} signs and should not haveside-effects. Actions need {: :} signs and should contain onlyside-effects, and cannot make attributes..PP.SH USAGE.I Preccxgrammar description files conventionally have the .\fIy\fP suffix, andshould follow the following format:.IP# define TOKEN ... (default = char).IP# define VALUE ... (default = char*).IP# define BEGIN ... (default nothing).IP# define END\0\0 ... (default nothing).IP# define ON_ERROR(x) ... (defaults to standard).IP# include "cc.h" (or ccx.h).IP @ first\0definition : attached action; :.IP @ ....IP @ ....IPMAIN(name of entry parser).PPThe cc.h header file may be used instead of ccx.h in scripts whichconsist only of unparameterized definitions and terms..SH EXAMPLEThe following script defines a simple +/- calculator in the version2.41 language, using parameters. For scripts that work with earlierversions of the language, see earlier versions of the manual. Somenotes on differences appear afterward..IP# define TOKEN char.IP# define VALUE int.IP# define BEGIN printf("\\nready> ");.IP#\0include\0"ccx.h".IP#\0include\0<ctype.h>.IP @\0digit\0=\0(isdigit)\\x\0\0\0\0{@ $x-'0' @}.IP @\0posint(t)=\0digit\\x\0posint(10*t+$x).IP @\0\0\0\0\0\0\0|\0digit\\x\0\0\0\0\0\0\0\0\0\0\0\0{@ 10*t+$x @}.IP @\0posint0=\0posint(0).IP @\0anyint=\0<'-'>\0posint0\\x\0\0\0\0{@ -$x @}.IP @\0\0\0\0\0\0\0|\0posint(0).IP @\0atom\0\0=\0<'('>\0expr\\x\0<')'>\0{@ $x @}.IP @\0\0\0\0\0\0\0|\0int.IP @\0expr\0\0=\0atom\\x\0sign_sum\\y\0\0{@ $x+$y @}.IP @\0\0\0\0\0\0\0|\0atom.IP @\0sign_sum=\0<'-'>\0atom\\x\0sign_sum\\y.IP @\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0{@ -$x+$y @}.IP @\0\0\0\0\0\0\0\0\0|\0<'-'>\0atom\\x\0\0\0\0\0{@ -$x @}.IP @\0\0\0\0\0\0\0\0\0|\0<'+'>\0atom\\x\0sign_sum\\y.IP @\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0{@ $x+$y @}.IP @\0\0\0\0\0\0\0\0\0|\0<'+'>\0atom\\x\0\0\0\0\0{@ $x @}.IP @\0top\0\0\0\0\0=\0expr\\x\0\0\0\0\0\0\0\0\0\0\0{: printf("=%d\\n",$x); :}.IPMAIN(expr).PPThis script must be passed through \fIpreccx\fP:.IPpreccx\0<\0calculator.y\0>\0calculator.c.PPand then compiled, using the \fIpreccx\fP kernel library in libcc.a:.IPgcc\0\-Wall\0\-ansi\0\-o\0calculator\0calculator.c\0\-L\0...\0\-lcc.PPThe three dots stand for the directory in which the preccx library file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -