📄 preccx.y
字号:
@ line = declaration@ | notanat passthrough@ | :VV(0)="";printf("\n");:@ notanat = NOTANAT : VV(1)=putchar(T(1)); :/* this is a deliberate pop of the value 'behind' if we get none */@ passthrough = {anychar : VV(2)=V(1); :}*@ :getname(&V(1));printf("%s\n",V(1)); RESET;:@ anychar = ANYTHING : VV(1)=putchar(T(1)); : /* ---- parser expressions -------- */@ expression = alternates@ | empty/* a <'|'> separated series, at least one <'|'> - note the overpull I prefer the order which results from recursion */@ alternates = sequence@ [ WHITESPACE OR WHITESPACE alternates@ :char *n;@ VV(5)=(GETNEWNAME(&n,plainenv,NULL),P_ALT(n,V(1),V(5)));:@ ]/* appending is much more efficient than prepending because I don't waste C-stack space with MARK before a parse *//* this is a command separated sequence of sequents which are not commands*/@ sequence = manysequents @ { @ SOMESPACE command@ SOMESPACE manysequents@ :char *n;@ VV(3)=(GETNEWNAME(&n,plainenv,NULL),P_AND(n,V(1),V(3)));:@ }*@ [ WHITESPACE command ] /* here we attach to the manysequents which this follows */@ command = COLON c_code COLONorEOL@ : char *n,*m;@ VV(5)=(GETNEWNAME(&n,plainenv,NULL),GETNEWNAME(&m,plainenv,NULL),P_ATT(m,V(1),n,V(4))); :/* commands can't be treated as ordinary atoms at the moment, because they * are required to end a sequence of 'and's and force a stack shift */@ c_code = cstuffs : VV(1)=V(1); getname(&V(1)); :/* the stuff inside a command is a sequence of C constants or C tokens */@ cstuffs= cstuff {cstuff : VV(2) = V(1); :}*@ | : VV(0) =""; :/* all the component tokens are accumulating in the cbuff */@ cstuff = STRING@ | CHARCONST@ | DOLLARID@ | COMMENT@ | NOTACOLON : VV(1) = putchar(T(1)); :/* manysequents is a 0 or more long list of nonempty non-commands *//* start a new count *//* do the pulling in moresequents, if it happens */@ manysequents = firstsequent [ moresequents ] : popcount();:/* need "empty newvar empty" and "sequent newvar empty" to make the above complete, but it's too much bother right now */@ firstsequent = { sequent@ | empty@ } :pushcount();: /* overpull again in the option again, I prefer to use recursion for better output order *//* without a parameterized spec, I can't prevent repetitions */@ newvar = BACKSLASH IDENTIFIER@ :VV(2)=V(2);getname(&V(2));ADDVAR(V(2));:/* moresequents is a 1 or more long list of sequents, or an attr decl * followed by a 1 or more long list. It is not empty. It is not * (presently) a newvar on its own, though it might eventually be */@ moresequents = newvar SOMESPACE sequent [ moresequents ]@ : char *n; VV(4)=V(1);popenv();@ GETNEWNAME(&n,plainenv,NULL);V(1)=P_STAR(n,V(1),V(4),V(2));:@ | dummyvar SOMESPACE sequent [ moresequents ]@ : char *n; VV(4)=V(1);@ if (precc_data.oldattributes){popenv();@ GETNEWNAME(&n,plainenv,NULL);V(1)=P_STAR(n,V(1),V(4),V(2));}@ else{@ GETNEWNAME(&n,plainenv,NULL);V(1)=P_AND(n,V(1),V(4));}:/* in the above, have to be careful to avoid allowing a trailing "empty" because that wrecks the returned value from an @foo@ */@ dummyvar = :/*empty*/ VV(0)=V(1);@ if(precc_data.oldattributes){@ getname(&V(1));@ GETANAME(&V(1),"p_","",count++);@ V(1)=GNAME(V(1));putname(V(1));@ getname(&V(1));@ ADDVAR(V(1)); } /* Don't overpull now because ... */@ sequent = seqoperand [ postfix ] /* in each of these cases the postfix must behave as though the seqoperand were before it and overpull its arguments and write into the stack position to the left of itself */@ postfix = starop@ | plusop @ | hideop@ bracket = OPENBRACE WHITESPACE@ expression@ WHITESPACE CLOSEBRACE@ : VV(5) = V(3); :@ option = OPENBRACKET WHITESPACE@ expression@ WHITESPACE CLOSEBRACKET@ : char *n;VV(5)=(GETNEWNAME(&n,plainenv,NULL),P_OPT(n,V(3))); :@ empty = : VV(0)= "p_nothing0"; :@ result= AT WHITESPACE expr WHITESPACE AT@ :char *n; VV(5)=(getname(&V(3)),@ GETNEWNAME(&n,plainenv,NULL),P_ATA(n,V(3))); : /* here is one overpull */int starflag=0;char *starqual;@ starop = STAR [ expr :starflag=1;VV(2)=(getname(&V(2)),V(2));:]@ : char *n;if(starflag){@ VV(2)=(GETNEWNAME(&n,plainenv,NULL),P_ITR(n,V(1),V(3))); @ } else {@ VV(2)=(GETNEWNAME(&n,plainenv,NULL),P_INF(n,V(1)));@ } starflag=0; :@ anymatch = QUESTION : VV(1)="p_anything0"; :/* recall that exprnames get saved in the cbuff */@ seqoperand = bracket@ | option@ | literal@ | antiliteral@ | range @ | test@ | phantom@ | result@ | untilmatch@ | anymatch | beginmatch | eofmatch@ | dollarplingmatch | finishmatch@ | plingexpr@ | plingmatch | exprname@ plingexpr = PLING bracket @ : char *n; VV(2)=(GETNEWNAME(&n,plainenv,NULL),P_ERR(n,V(2))); :@ phantom = CLOSEBRACKET WHITESPACE@ expression@ WHITESPACE OPENBRACKET@ :char *n;VV(5)=(GETNEWNAME(&n,plainenv,NULL),P_PHA(n,V(3))); :/* a literal is anything inside angle brackets. * an antiliteral is anything inside anti angle brackets. * anglebrackets inside may be escaped to protect them */@ lstuff = STRING @ | CHARCONST@ | COMMENT@ | NOTARIGHTANGLEBRACKET : VV(1) = putchar(T(1)); :@ alstuff = STRING @ | CHARCONST@ | COMMENT@ | NOTALEFTANGLEBRACKET : VV(1) = putchar(T(1)); :@ lstuffs = lstuff {lstuff : VV(2) = V(1); :}*@ | : VV(0)=""; :/* close the accumulator for lstuffs */@ lits = lstuffs :VV(1)=V(1);getname(&V(1));:@ alstuffs = alstuff {alstuff : VV(2) = V(1); :}*@ | : VV(0)=""; :/* close the accumulator for alstuffs */@ alits = alstuffs :VV(1)=V(1);getname(&V(1));:@ LITERAL = LEFTANGLEBRACKET@ lits@ RIGHTANGLEBRACKET@ : VV(3) = V(2); :@ ANTILITERAL = RIGHTANGLEBRACKET@ alits@ LEFTANGLEBRACKET @ : VV(3) = V(2) ; : @ literal = LITERAL @ :char *n;VV(1)=(GETNEWNAME(&n,plainenv,NULL),P_LIT(n,V(1))); :@ antiliteral = ANTILITERAL@ :char *n;VV(1)=(GETNEWNAME(&n,plainenv,NULL),P_ALI(n,V(1))); :@ range = OPENPAREN expr CLOSEPAREN@ :char *n;VV(3)=(getname(&V(2)),GETNEWNAME(&n,plainenv,NULL),P_RAN(n,V(2)));:@ test = CLOSEPAREN expr OPENPAREN@ :char *n;VV(3)=(getname(&V(2)),GETNEWNAME(&n,plainenv,NULL),P_TST(n,V(2)));:@ beginmatch = CARET : VV(1)="p_first0"; :@ finishmatch = DOLLAR : VV(1)="p_last0"; :@ plingmatch = PLING : VV(1)="p_uniq0"; :@ dollarplingmatch = DOLLAR PLING : VV(2)="p_lastuniq0"; :@ eofmatch = DOLLAR DOLLAR : VV(2)="p_eof0"; : /* another overpull */@ plusop = PLUS@ : char *n;VV(2)=(GETNEWNAME(&n,plainenv,NULL),P_SOM(n,V(1))); :@ hideop = SLASH OPENPAREN expr CLOSEPAREN@ :char *n;@ VV(5)=(getname(&V(4)),GETNEWNAME(&n,plainenv,NULL),P_HID(n,V(1),V(4)));:@ untilmatch = ELLIPSIS WHITESPACE seqoperand@ : char *n;VV(3)=(GETNEWNAME(&n,plainenv,NULL),P_UNT(n,V(3))); : /* ------- finis -------- */MAIN(line)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -