ADDED embedded/man/files/modules/pt/pt_cparam_config_tea.n Index: embedded/man/files/modules/pt/pt_cparam_config_tea.n ================================================================== --- /dev/null +++ embedded/man/files/modules/pt/pt_cparam_config_tea.n @@ -0,0 +1,333 @@ +'\" +'\" Generated from file 'pt_cparam_config_tea\&.man' by tcllib/doctools with format 'nroff' +'\" Copyright (c) 2009 Andreas Kupries +'\" +.TH "pt::cparam::configuration::tea" n 0\&.1 tcllib "Parser Tools" +.\" The -*- nroff -*- definitions below are for supplemental macros used +.\" in Tcl/Tk manual entries. +.\" +.\" .AP type name in/out ?indent? +.\" Start paragraph describing an argument to a library procedure. +.\" type is type of argument (int, etc.), in/out is either "in", "out", +.\" or "in/out" to describe whether procedure reads or modifies arg, +.\" and indent is equivalent to second arg of .IP (shouldn't ever be +.\" needed; use .AS below instead) +.\" +.\" .AS ?type? ?name? +.\" Give maximum sizes of arguments for setting tab stops. Type and +.\" name are examples of largest possible arguments that will be passed +.\" to .AP later. If args are omitted, default tab stops are used. +.\" +.\" .BS +.\" Start box enclosure. From here until next .BE, everything will be +.\" enclosed in one large box. +.\" +.\" .BE +.\" End of box enclosure. +.\" +.\" .CS +.\" Begin code excerpt. +.\" +.\" .CE +.\" End code excerpt. +.\" +.\" .VS ?version? ?br? +.\" Begin vertical sidebar, for use in marking newly-changed parts +.\" of man pages. The first argument is ignored and used for recording +.\" the version when the .VS was added, so that the sidebars can be +.\" found and removed when they reach a certain age. If another argument +.\" is present, then a line break is forced before starting the sidebar. +.\" +.\" .VE +.\" End of vertical sidebar. +.\" +.\" .DS +.\" Begin an indented unfilled display. +.\" +.\" .DE +.\" End of indented unfilled display. +.\" +.\" .SO ?manpage? +.\" Start of list of standard options for a Tk widget. The manpage +.\" argument defines where to look up the standard options; if +.\" omitted, defaults to "options". The options follow on successive +.\" lines, in three columns separated by tabs. +.\" +.\" .SE +.\" End of list of standard options for a Tk widget. +.\" +.\" .OP cmdName dbName dbClass +.\" Start of description of a specific option. cmdName gives the +.\" option's name as specified in the class command, dbName gives +.\" the option's name in the option database, and dbClass gives +.\" the option's class in the option database. +.\" +.\" .UL arg1 arg2 +.\" Print arg1 underlined, then print arg2 normally. +.\" +.\" .QW arg1 ?arg2? +.\" Print arg1 in quotes, then arg2 normally (for trailing punctuation). +.\" +.\" .PQ arg1 ?arg2? +.\" Print an open parenthesis, arg1 in quotes, then arg2 normally +.\" (for trailing punctuation) and then a closing parenthesis. +.\" +.\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. +.if t .wh -1.3i ^B +.nr ^l \n(.l +.ad b +.\" # Start an argument description +.de AP +.ie !"\\$4"" .TP \\$4 +.el \{\ +. ie !"\\$2"" .TP \\n()Cu +. el .TP 15 +.\} +.ta \\n()Au \\n()Bu +.ie !"\\$3"" \{\ +\&\\$1 \\fI\\$2\\fP (\\$3) +.\".b +.\} +.el \{\ +.br +.ie !"\\$2"" \{\ +\&\\$1 \\fI\\$2\\fP +.\} +.el \{\ +\&\\fI\\$1\\fP +.\} +.\} +.. +.\" # define tabbing values for .AP +.de AS +.nr )A 10n +.if !"\\$1"" .nr )A \\w'\\$1'u+3n +.nr )B \\n()Au+15n +.\" +.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n +.nr )C \\n()Bu+\\w'(in/out)'u+2n +.. +.AS Tcl_Interp Tcl_CreateInterp in/out +.\" # BS - start boxed text +.\" # ^y = starting y location +.\" # ^b = 1 +.de BS +.br +.mk ^y +.nr ^b 1u +.if n .nf +.if n .ti 0 +.if n \l'\\n(.lu\(ul' +.if n .fi +.. +.\" # BE - end boxed text (draw box now) +.de BE +.nf +.ti 0 +.mk ^t +.ie n \l'\\n(^lu\(ul' +.el \{\ +.\" Draw four-sided box normally, but don't draw top of +.\" box if the box started on an earlier page. +.ie !\\n(^b-1 \{\ +\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' +.\} +.el \}\ +\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' +.\} +.\} +.fi +.br +.nr ^b 0 +.. +.\" # VS - start vertical sidebar +.\" # ^Y = starting y location +.\" # ^v = 1 (for troff; for nroff this doesn't matter) +.de VS +.if !"\\$2"" .br +.mk ^Y +.ie n 'mc \s12\(br\s0 +.el .nr ^v 1u +.. +.\" # VE - end of vertical sidebar +.de VE +.ie n 'mc +.el \{\ +.ev 2 +.nf +.ti 0 +.mk ^t +\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' +.sp -1 +.fi +.ev +.\} +.nr ^v 0 +.. +.\" # Special macro to handle page bottom: finish off current +.\" # box/sidebar if in box/sidebar mode, then invoked standard +.\" # page bottom macro. +.de ^B +.ev 2 +'ti 0 +'nf +.mk ^t +.if \\n(^b \{\ +.\" Draw three-sided box if this is the box's first page, +.\" draw two sides but no top otherwise. +.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c +.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c +.\} +.if \\n(^v \{\ +.nr ^x \\n(^tu+1v-\\n(^Yu +\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c +.\} +.bp +'fi +.ev +.if \\n(^b \{\ +.mk ^y +.nr ^b 2 +.\} +.if \\n(^v \{\ +.mk ^Y +.\} +.. +.\" # DS - begin display +.de DS +.RS +.nf +.sp +.. +.\" # DE - end display +.de DE +.fi +.RE +.sp +.. +.\" # SO - start of list of standard options +.de SO +'ie '\\$1'' .ds So \\fBoptions\\fR +'el .ds So \\fB\\$1\\fR +.SH "STANDARD OPTIONS" +.LP +.nf +.ta 5.5c 11c +.ft B +.. +.\" # SE - end of list of standard options +.de SE +.fi +.ft R +.LP +See the \\*(So manual entry for details on the standard options. +.. +.\" # OP - start of full description for a single option +.de OP +.LP +.nf +.ta 4c +Command-Line Name: \\fB\\$1\\fR +Database Name: \\fB\\$2\\fR +Database Class: \\fB\\$3\\fR +.fi +.IP +.. +.\" # CS - begin code excerpt +.de CS +.RS +.nf +.ta .25i .5i .75i 1i +.. +.\" # CE - end code excerpt +.de CE +.fi +.RE +.. +.\" # UL - underline word +.de UL +\\$1\l'|0\(ul'\\$2 +.. +.\" # QW - apply quotation marks to word +.de QW +.ie '\\*(lq'"' ``\\$1''\\$2 +.\"" fix emacs highlighting +.el \\*(lq\\$1\\*(rq\\$2 +.. +.\" # PQ - apply parens and quotation marks to word +.de PQ +.ie '\\*(lq'"' (``\\$1''\\$2)\\$3 +.\"" fix emacs highlighting +.el (\\*(lq\\$1\\*(rq\\$2)\\$3 +.. +.\" # QR - quoted range +.de QR +.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3 +.\"" fix emacs highlighting +.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3 +.. +.\" # MT - "empty" string +.de MT +.QW "" +.. +.BS +.SH NAME +pt::cparam::configuration::tea \- C/PARAM, Canned configuration, TEA +.SH SYNOPSIS +package require \fBTcl 8\&.5\fR +.sp +package require \fBpt::cparam::configuration::tea ?0\&.1?\fR +.sp +\fB::pt::cparam::configuration::tea\fR \fBdef\fR \fIname\fR \fIpkg\fR \fIversion\fR \fIcmdprefix\fR +.sp +.BE +.SH DESCRIPTION +.PP +Are you lost ? +Do you have trouble understanding this document ? +In that case please read the overview provided by the +\fIIntroduction to Parser Tools\fR\&. This document is the +entrypoint to the whole system the current package is a part of\&. +.PP +This package is an adjunct to \fBpt::peg::to::cparam\fR, to make +the use of this highly configurable package easier by providing a +canned configuration\&. When applied this configuration causes the +package \fBpt::peg::to::cparam\fR to generate plain parser code +ready for inclusion into a \fITEA\fR-based C extension\&. +.PP +It is a supporting package in the Core Layer of Parser Tools\&. +.PP +IMAGE: arch_core_support +.PP +.SH API +.TP +\fB::pt::cparam::configuration::tea\fR \fBdef\fR \fIname\fR \fIpkg\fR \fIversion\fR \fIcmdprefix\fR +The command applies the configuration provided by this package to the +\fIcmdprefix\fR, causing the creation of \fBtea\fR-based parsers +whose class is \fIname\fR, in package \fIpkg\fR with \fIversion\fR\&. +.sp +The use of a command prefix as API allows application of the +configuration to not only \fBpt::peg::to::cparam\fR +(\fBpt::peg::to::cparam configure\fR), but also export manager +instances and PEG containers (\fB$export configuration set\fR and +\fB[$container exporter] configuration set\fR respectively)\&. +.sp +Or anything other command prefix accepting two arguments, option and +value\&. +.PP +.SH "BUGS, IDEAS, FEEDBACK" +This document, and the package it describes, will undoubtedly contain +bugs and other problems\&. +Please report such in the category \fIpt\fR of the +\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&. +Please also report any ideas for enhancements you may have for either +package and/or documentation\&. +.SH KEYWORDS +EBNF, LL(k), PEG, TDPL, context-free languages, expression, grammar, matching, parser, parsing expression, parsing expression grammar, push down automaton, recursive descent, state, top-down parsing languages, transducer +.SH CATEGORY +Parsing and Grammars +.SH COPYRIGHT +.nf +Copyright (c) 2009 Andreas Kupries + +.fi Index: embedded/man/index.n ================================================================== --- embedded/man/index.n +++ embedded/man/index.n @@ -1559,10 +1559,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -2852,10 +2855,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -3284,10 +3290,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -3953,10 +3962,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -5135,10 +5147,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -5603,10 +5618,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -6569,10 +6587,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -6809,10 +6830,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -6947,10 +6971,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -7124,10 +7151,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -7574,10 +7604,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -7838,10 +7871,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -9137,10 +9173,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -9626,10 +9665,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -10277,10 +10319,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR @@ -10460,10 +10505,13 @@ \fBfiles/modules/pt/pt_astree\&.n\fR pt::ast .TP \fBfiles/modules/pt/pt_cparam_config_critcl\&.n\fR pt::cparam::configuration::critcl +.TP +\fBfiles/modules/pt/pt_cparam_config_tea\&.n\fR +pt::cparam::configuration::tea .TP \fBfiles/modules/pt/pt_json_language\&.n\fR pt::json_language .TP \fBfiles/modules/pt/pt_param\&.n\fR Index: embedded/man/toc.n ================================================================== --- embedded/man/toc.n +++ embedded/man/toc.n @@ -946,10 +946,13 @@ \fIfiles/modules/pt/pt_astree\&.n\fR: Abstract Syntax Tree Serialization .TP \fBpt::cparam::configuration::critcl\fR \fIfiles/modules/pt/pt_cparam_config_critcl\&.n\fR: C/PARAM, Canned configuration, Critcl .TP +\fBpt::cparam::configuration::tea\fR +\fIfiles/modules/pt/pt_cparam_config_tea\&.n\fR: C/PARAM, Canned configuration, TEA +.TP \fBpt::json_language\fR \fIfiles/modules/pt/pt_json_language\&.n\fR: The JSON Grammar Exchange Format .TP \fBpt::param\fR \fIfiles/modules/pt/pt_param\&.n\fR: PackRat Machine Specification Index: embedded/www/index.html ================================================================== --- embedded/www/index.html +++ embedded/www/index.html @@ -748,11 +748,11 @@ grammar::me_intro context-free languages - grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op control control · term · term::ansi::code · term::ansi::code::attr · term::ansi::code::ctrl · term::ansi::code::macros · term::ansi::ctrl::unix · term::ansi::send · term::interact::menu · term::interact::pager · term::receive · term::receive::bind · term::send @@ -1214,11 +1214,11 @@ grammar::aycock EBNF - pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op eccentricity struct::graph::op @@ -1354,11 +1354,11 @@ doctools::html::cssdefaults · doctools::idx::export · doctools::idx::export::docidx · doctools::idx::export::html · doctools::idx::export::json · doctools::idx::export::nroff · doctools::idx::export::text · doctools::idx::export::wiki · doctools::nroff::man_macros · doctools::toc::export · doctools::toc::export::doctoc · doctools::toc::export::html · doctools::toc::export::json · doctools::toc::export::nroff · doctools::toc::export::text · doctools::toc::export::wiki · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg expression - grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op extended namespace namespacex @@ -1625,11 +1625,11 @@ gpx grammar - grammar::aycock · grammar::fa · grammar::fa::dacceptor · grammar::fa::dexec · grammar::fa::op · grammar::me::cpu · grammar::me::cpu::core · grammar::me::cpu::gasm · grammar::me::tcl · grammar::me_intro · grammar::me_vm · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + grammar::aycock · grammar::fa · grammar::fa::dacceptor · grammar::fa::dexec · grammar::fa::op · grammar::me::cpu · grammar::me::cpu::core · grammar::me::cpu::gasm · grammar::me::tcl · grammar::me_intro · grammar::me_vm · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op graph grammar::me::cpu::gasm · struct::graph · struct::graph::op · struct::graph_v1 · struct::queue · struct::stack @@ -2125,11 +2125,11 @@ docstrip · docstrip_util · tcldocstrip LL(k) - grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op local searching struct::graph::op @@ -2228,11 +2228,11 @@ valtype::creditcard::mastercard matching - grammar::me_intro · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op · struct::graph::op + grammar::me_intro · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op · struct::graph::op math math · math::bigfloat · math::bignum · math::calculus · math::complexnumbers · math::constants · math::decimal · math::fuzzy · math::geometry · math::interpolate · math::linearalgebra · math::optimize · math::polynomials · math::rationalfunctions · math::special · simulation::annealing · simulation::montecarlo · simulation::random @@ -2632,11 +2632,11 @@ tepam · tepam::argument_dialogbox parser - doctools::idx::parse · doctools::tcl::parse · doctools::toc::parse · grammar::aycock · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op · xsxp + doctools::idx::parse · doctools::tcl::parse · doctools::toc::parse · grammar::aycock · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op · xsxp parser generator page · page_intro · page_pluginmgr · page_util_flow · page_util_norm_lemon · page_util_norm_peg · page_util_peg · page_util_quote @@ -2647,16 +2647,16 @@ bench::in · bibtex · doctools2idx_introduction · doctools2toc_introduction · doctools::idx · doctools::idx::import · doctools::toc · doctools::toc::import · grammar::aycock · grammar::fa · grammar::fa::dacceptor · grammar::fa::dexec · grammar::fa::op · grammar::me::cpu · grammar::me::cpu::core · grammar::me::cpu::gasm · grammar::me::tcl · grammar::me_intro · grammar::me_vm · grammar::peg · grammar::peg::interp · htmlparse · huddle · string::token::shell · yaml parsing expression - grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op parsing expression grammar - grammar::me_intro · grammar::peg · grammar::peg::interp · page_util_peg · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + grammar::me_intro · grammar::peg · grammar::peg::interp · page_util_peg · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op partial application lambda @@ -2692,11 +2692,11 @@ rcs PEG - grammar::me_intro · page_util_norm_peg · page_util_peg · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + grammar::me_intro · page_util_norm_peg · page_util_peg · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op performance bench · bench::in · bench::out::csv · bench::out::text · bench_intro · bench_lang_intro · bench_lang_spec · profiler @@ -2862,11 +2862,11 @@ hook push down automaton - grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op Keywords: Q @@ -2958,11 +2958,11 @@ struct::queue · struct::record recursive descent - grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op reduce generator · struct::list @@ -3501,11 +3501,11 @@ tcl::chan::std state - grammar::fa · grammar::fa::dacceptor · grammar::fa::dexec · grammar::fa::op · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + grammar::fa · grammar::fa::dacceptor · grammar::fa::dexec · grammar::fa::op · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op state (de)serialization namespacex @@ -3709,11 +3709,11 @@ pt::peg::to::tclparam TDPL - grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op temp file fileutil @@ -3889,11 +3889,11 @@ string::token · string::token::shell top-down parsing languages - grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op torrent bee @@ -3914,11 +3914,11 @@ debug · debug::caller · debug::heartbeat · debug::timestamp transducer - grammar::aycock · grammar::fa · grammar::fa::dacceptor · grammar::fa::dexec · grammar::fa::op · grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op + grammar::aycock · grammar::fa · grammar::fa::dacceptor · grammar::fa::dexec · grammar::fa::op · grammar::me_intro · grammar::peg · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op transfer transfer::connect · transfer::copy · transfer::copy::queue · transfer::data::destination · transfer::data::source · transfer::receiver · transfer::transmitter ADDED embedded/www/tcllib/files/modules/pt/pt_cparam_config_tea.html Index: embedded/www/tcllib/files/modules/pt/pt_cparam_config_tea.html ================================================================== --- /dev/null +++ embedded/www/tcllib/files/modules/pt/pt_cparam_config_tea.html @@ -0,0 +1,184 @@ + + +pt::cparam::configuration::tea - Parser Tools + + + + + +
+
[ + Tcllib Home +| Main Table Of Contents +| Table Of Contents +| Keyword Index +| Categories +| Modules +| Applications + ]
+

pt::cparam::configuration::tea(n) 0.1 tcllib "Parser Tools"

+

Name

+

pt::cparam::configuration::tea - C/PARAM, Canned configuration, TEA

+
+ +

Synopsis

+
+
    +
  • package require Tcl 8.5
  • +
  • package require pt::cparam::configuration::tea ?0.1?
  • +
+ +
+
+

Description

+

Are you lost ? +Do you have trouble understanding this document ? +In that case please read the overview provided by the +Introduction to Parser Tools. This document is the +entrypoint to the whole system the current package is a part of.

+

This package is an adjunct to pt::peg::to::cparam, to make +the use of this highly configurable package easier by providing a +canned configuration. When applied this configuration causes the +package pt::peg::to::cparam to generate plain parser code +ready for inclusion into a TEA-based C extension.

+

It is a supporting package in the Core Layer of Parser Tools.

+

arch_core_support

+
+

API

+
+
::pt::cparam::configuration::tea def name pkg version cmdprefix
+

The command applies the configuration provided by this package to the +cmdprefix, causing the creation of tea-based parsers +whose class is name, in package pkg with version.

+

The use of a command prefix as API allows application of the +configuration to not only pt::peg::to::cparam +(pt::peg::to::cparam configure), but also export manager +instances and PEG containers ($export configuration set and +[$container exporter] configuration set respectively).

+

Or anything other command prefix accepting two arguments, option and +value.

+
+
+

Bugs, Ideas, Feedback

+

This document, and the package it describes, will undoubtedly contain +bugs and other problems. +Please report such in the category pt of the +Tcllib Trackers. +Please also report any ideas for enhancements you may have for either +package and/or documentation.

+
+ +

Category

+

Parsing and Grammars

+
+ +
Index: embedded/www/tcllib/toc.html ================================================================== --- embedded/www/tcllib/toc.html +++ embedded/www/tcllib/toc.html @@ -915,738 +915,742 @@ pt::cparam::configuration::critcl C/PARAM, Canned configuration, Critcl +pt::cparam::configuration::tea +C/PARAM, Canned configuration, TEA + + pt::json_language The JSON Grammar Exchange Format - + pt::param PackRat Machine Specification - + pt::pe Parsing Expression Serialization - + pt::pe::op Parsing Expression Utilities - + pt::peg Parsing Expression Grammar Serialization - + pt::peg::container PEG Storage - + pt::peg::container::peg PEG Storage. Canned PEG grammar specification - + pt::peg::export PEG Export - + pt::peg::export::container PEG Export Plugin. Write CONTAINER format - + pt::peg::export::json PEG Export Plugin. Write JSON format - + pt::peg::export::peg PEG Export Plugin. Write PEG format - + pt::peg::from::container PEG Conversion. From CONTAINER format - + pt::peg::from::json PEG Conversion. Read JSON format - + pt::peg::from::peg PEG Conversion. Read PEG format - + pt::peg::import PEG Import - + pt::peg::import::container PEG Import Plugin. From CONTAINER format - + pt::peg::import::json PEG Import Plugin. Read JSON format - + pt::peg::import::peg PEG Import Plugin. Read PEG format - + pt::peg::interp Interpreter for parsing expression grammars - + pt::peg::to::container PEG Conversion. Write CONTAINER format - + pt::peg::to::cparam PEG Conversion. Write CPARAM format - + pt::peg::to::json PEG Conversion. Write JSON format - + pt::peg::to::param PEG Conversion. Write PARAM format - + pt::peg::to::peg PEG Conversion. Write PEG format - + pt::peg::to::tclparam PEG Conversion. Write TCLPARAM format - + pt::peg_language PEG Language Tutorial - + pt::pegrammar Introduction to Parsing Expression Grammars - + pt::pgen Parser Generator - + pt::rde Parsing Runtime Support, PARAM based - + pt::tclparam::configuration::snit Tcl/PARAM, Canned configuration, Snit - + pt::tclparam::configuration::tcloo Tcl/PARAM, Canned configuration, Tcloo - + pt::util General utilities - + pt_export_api Parser Tools Export API - + pt_import_api Parser Tools Import API - + pt_introduction Introduction to Parser Tools - + pt_parse_peg Parser Tools PEG Parser - + pt_parser_api Parser API - + pt_peg_op Parser Tools PE Grammar Utility Operations - + rc4 Implementation of the RC4 stream cipher - + rcs RCS low level utilities - + report Create and manipulate report objects - + rest define REST web APIs and call them inline or asychronously - + ripemd128 RIPEMD-128 Message-Digest Algorithm - + ripemd160 RIPEMD-160 Message-Digest Algorithm - + S3 Amazon S3 Web Service Interface - + SASL Implementation of SASL mechanisms for Tcl - + SASL::NTLM Implementation of SASL NTLM mechanism for Tcl - + SASL::SCRAM Implementation of SASL SCRAM mechanism for Tcl - + SASL::XGoogleToken Implementation of SASL NTLM mechanism for Tcl - + sha1 SHA1 Message-Digest Algorithm - + sha256 SHA256 Message-Digest Algorithm - + simulation::annealing Simulated annealing - + simulation::montecarlo Monte Carlo simulations - + simulation::random Pseudo-random number generators - + smtp Client-side tcl implementation of the smtp protocol - + smtpd Tcl SMTP server implementation - + snit Snit's Not Incr Tcl - + snitfaq Snit Frequently Asked Questions - + soundex Soundex - + stooop Object oriented extension. - + string::token Regex based iterative lexing - + string::token::shell Parsing of shell command line - + stringprep Implementation of stringprep - + stringprep::data stringprep data tables, generated, internal - + struct::disjointset Disjoint set data structure - + struct::graph Create and manipulate directed graph objects - + struct::graph::op Operation for (un)directed graph objects - + struct::graph_v1 Create and manipulate directed graph objects - + struct::list Procedures for manipulating lists - + struct::matrix Create and manipulate matrix objects - + struct::matrix_v1 Create and manipulate matrix objects - + struct::pool Create and manipulate pool objects (of discrete items) - + struct::prioqueue Create and manipulate prioqueue objects - + struct::queue Create and manipulate queue objects - + struct::record Define and create records (similar to 'C' structures) - + struct::set Procedures for manipulating sets - + struct::skiplist Create and manipulate skiplists - + struct::stack Create and manipulate stack objects - + struct::tree Create and manipulate tree objects - + struct::tree_v1 Create and manipulate tree objects - + sum Calculate a sum(1) compatible checksum - + switched switch/option management. - + tar Tar file creation, extraction & manipulation - + tcl::chan::cat Concatenation channel - + tcl::chan::core Basic reflected/virtual channel support - + tcl::chan::events Event support for reflected/virtual channels - + tcl::chan::facade Facade channel - + tcl::chan::fifo In-memory fifo channel - + tcl::chan::fifo2 In-memory interconnected fifo channels - + tcl::chan::halfpipe In-memory channel, half of a fifo2 - + tcl::chan::memchan In-memory channel - + tcl::chan::null Null channel - + tcl::chan::nullzero Null/Zero channel combination - + tcl::chan::random Random channel - + tcl::chan::std Standard I/O, unification of stdin and stdout - + tcl::chan::string Read-only in-memory channel - + tcl::chan::textwindow Textwindow channel - + tcl::chan::variable In-memory channel using variable for storage - + tcl::chan::zero Zero channel - + tcl::randomseed Utilities for random channels - + tcl::transform::adler32 Adler32 transformation - + tcl::transform::base64 Base64 encoding transformation - + tcl::transform::core Basic reflected/virtual channel transform support - + tcl::transform::counter Counter transformation - + tcl::transform::crc32 Crc32 transformation - + tcl::transform::hex Hexadecimal encoding transformation - + tcl::transform::identity Identity transformation - + tcl::transform::limitsize limiting input - + tcl::transform::observe Observer transformation, stream copy - + tcl::transform::otp Encryption via one-time pad - + tcl::transform::rot rot-encryption - + tcl::transform::spacer Space insertation and removal - + tcl::transform::zlib zlib (de)compression - + tcldes Implementation of the DES and triple-DES ciphers - + tcldes Implementation of the DES and triple-DES ciphers - + tcldocstrip Tcl-based Docstrip Processor - + tcllib_ip IPv4 and IPv6 address manipulation - + tclrep/machineparameters Compute double precision machine parameters. - + tepam An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager - + tepam::argument_dialogbox TEPAM argument_dialogbox, reference manual - + tepam::doc_gen TEPAM DOC Generation, reference manual - + tepam::procedure TEPAM procedure, reference manual - + term General terminal control - + term::ansi::code Helper for control sequences - + term::ansi::code::attr ANSI attribute sequences - + term::ansi::code::ctrl ANSI control sequences - + term::ansi::code::macros Macro sequences - + term::ansi::ctrl::unix Control operations and queries - + term::ansi::send Output of ANSI control sequences to terminals - + term::interact::menu Terminal widget, menu - + term::interact::pager Terminal widget, paging - + term::receive General input from terminals - + term::receive::bind Keyboard dispatch from terminals - + term::send General output to terminals - + textutil Procedures to manipulate texts and strings. - + textutil::adjust Procedures to adjust, indent, and undent paragraphs - + textutil::expander Procedures to process templates and expand text. - + textutil::repeat Procedures to repeat strings. - + textutil::split Procedures to split texts - + textutil::string Procedures to manipulate texts and strings. - + textutil::tabify Procedures to (un)tabify strings - + textutil::trim Procedures to trim strings - + tie Array persistence, standard data sources - + tie Array persistence - + tiff TIFF reading, writing, and querying and manipulation of meta data - + transfer::connect Connection setup - + transfer::copy Data transfer foundation - + transfer::copy::queue Queued transfers - + transfer::data::destination Data destination - + transfer::data::source Data source - + transfer::receiver Data source - + transfer::transmitter Data source - + treeql Query tree objects - + try try - Trap and process errors and exceptions - + uevent User events - + uevent::onidle Request merging and deferal to idle time - + unicode Implementation of Unicode normalization - + unicode::data unicode data tables, generated, internal - + units unit conversion - + uri URI utilities - + uri_urn URI utilities, URN scheme - + uuencode UU-encode/decode binary data - + uuid UUID generation and comparison - + valtype::common Validation, common code - + valtype::creditcard::amex Validation for AMEX creditcard number - + valtype::creditcard::discover Validation for Discover creditcard number - + valtype::creditcard::mastercard Validation for Mastercard creditcard number - + valtype::creditcard::visa Validation for VISA creditcard number - + valtype::gs1::ean13 Validation for EAN13 - + valtype::iban Validation for IBAN - + valtype::imei Validation for IMEI - + valtype::isbn Validation for ISBN - + valtype::luhn Validation for plain number with a LUHN checkdigit - + valtype::luhn5 Validation for plain number with a LUHN5 checkdigit - + valtype::usnpi Validation for USNPI - + valtype::verhoeff Validation for plain number with a VERHOEFF checkdigit - + websocket Tcl implementation of the websocket protocol - + wip Word Interpreter - + xsxp eXtremely Simple Xml Parser - + yaml YAML Format Encoder/Decoder - + yencode Y-encode/decode binary data - + zipfile::decode Access to zip archives - + zipfile::encode Generation of zip archives
Index: embedded/www/toc.html ================================================================== --- embedded/www/toc.html +++ embedded/www/toc.html @@ -1026,158 +1026,162 @@ pt::cparam::configuration::critcl C/PARAM, Canned configuration, Critcl +pt::cparam::configuration::tea +C/PARAM, Canned configuration, TEA + + pt::json_language The JSON Grammar Exchange Format - + pt::param PackRat Machine Specification - + pt::pe Parsing Expression Serialization - + pt::pe::op Parsing Expression Utilities - + pt::peg Parsing Expression Grammar Serialization - + pt::peg::container PEG Storage - + pt::peg::container::peg PEG Storage. Canned PEG grammar specification - + pt::peg::export PEG Export - + pt::peg::export::container PEG Export Plugin. Write CONTAINER format - + pt::peg::export::json PEG Export Plugin. Write JSON format - + pt::peg::export::peg PEG Export Plugin. Write PEG format - + pt::peg::from::container PEG Conversion. From CONTAINER format - + pt::peg::from::json PEG Conversion. Read JSON format - + pt::peg::from::peg PEG Conversion. Read PEG format - + pt::peg::import PEG Import - + pt::peg::import::container PEG Import Plugin. From CONTAINER format - + pt::peg::import::json PEG Import Plugin. Read JSON format - + pt::peg::import::peg PEG Import Plugin. Read PEG format - + pt::peg::interp Interpreter for parsing expression grammars - + pt::peg::to::container PEG Conversion. Write CONTAINER format - + pt::peg::to::cparam PEG Conversion. Write CPARAM format - + pt::peg::to::json PEG Conversion. Write JSON format - + pt::peg::to::param PEG Conversion. Write PARAM format - + pt::peg::to::peg PEG Conversion. Write PEG format - + pt::peg::to::tclparam PEG Conversion. Write TCLPARAM format - + pt::peg_language PEG Language Tutorial - + pt::pegrammar Introduction to Parsing Expression Grammars - + pt::pgen Parser Generator - + pt::rde Parsing Runtime Support, PARAM based - + pt::tclparam::configuration::snit Tcl/PARAM, Canned configuration, Snit - + pt::tclparam::configuration::tcloo Tcl/PARAM, Canned configuration, Tcloo - + pt::util General utilities - + pt_export_api Parser Tools Export API - + pt_import_api Parser Tools Import API - + pt_introduction Introduction to Parser Tools - + pt_parse_peg Parser Tools PEG Parser - + pt_parser_api Parser API - + pt_peg_op Parser Tools PE Grammar Utility Operations
Procedures, arguments, parameters, options
@@ -2905,158 +2909,162 @@ pt::cparam::configuration::critcl C/PARAM, Canned configuration, Critcl +pt::cparam::configuration::tea +C/PARAM, Canned configuration, TEA + + pt::json_language The JSON Grammar Exchange Format - + pt::param PackRat Machine Specification - + pt::pe Parsing Expression Serialization - + pt::pe::op Parsing Expression Utilities - + pt::peg Parsing Expression Grammar Serialization - + pt::peg::container PEG Storage - + pt::peg::container::peg PEG Storage. Canned PEG grammar specification - + pt::peg::export PEG Export - + pt::peg::export::container PEG Export Plugin. Write CONTAINER format - + pt::peg::export::json PEG Export Plugin. Write JSON format - + pt::peg::export::peg PEG Export Plugin. Write PEG format - + pt::peg::from::container PEG Conversion. From CONTAINER format - + pt::peg::from::json PEG Conversion. Read JSON format - + pt::peg::from::peg PEG Conversion. Read PEG format - + pt::peg::import PEG Import - + pt::peg::import::container PEG Import Plugin. From CONTAINER format - + pt::peg::import::json PEG Import Plugin. Read JSON format - + pt::peg::import::peg PEG Import Plugin. Read PEG format - + pt::peg::interp Interpreter for parsing expression grammars - + pt::peg::to::container PEG Conversion. Write CONTAINER format - + pt::peg::to::cparam PEG Conversion. Write CPARAM format - + pt::peg::to::json PEG Conversion. Write JSON format - + pt::peg::to::param PEG Conversion. Write PARAM format - + pt::peg::to::peg PEG Conversion. Write PEG format - + pt::peg::to::tclparam PEG Conversion. Write TCLPARAM format - + pt::peg_language PEG Language Tutorial - + pt::pegrammar Introduction to Parsing Expression Grammars - + pt::pgen Parser Generator - + pt::rde Parsing Runtime Support, PARAM based - + pt::tclparam::configuration::snit Tcl/PARAM, Canned configuration, Snit - + pt::tclparam::configuration::tcloo Tcl/PARAM, Canned configuration, Tcloo - + pt::util General utilities - + pt_export_api Parser Tools Export API - + pt_import_api Parser Tools Import API - + pt_introduction Introduction to Parser Tools - + pt_parse_peg Parser Tools PEG Parser - + pt_parser_api Parser API - + pt_peg_op Parser Tools PE Grammar Utility Operations
rc4
Index: embedded/www/toc0.html ================================================================== --- embedded/www/toc0.html +++ embedded/www/toc0.html @@ -1026,158 +1026,162 @@ pt::cparam::configuration::critcl C/PARAM, Canned configuration, Critcl +pt::cparam::configuration::tea +C/PARAM, Canned configuration, TEA + + pt::json_language The JSON Grammar Exchange Format - + pt::param PackRat Machine Specification - + pt::pe Parsing Expression Serialization - + pt::pe::op Parsing Expression Utilities - + pt::peg Parsing Expression Grammar Serialization - + pt::peg::container PEG Storage - + pt::peg::container::peg PEG Storage. Canned PEG grammar specification - + pt::peg::export PEG Export - + pt::peg::export::container PEG Export Plugin. Write CONTAINER format - + pt::peg::export::json PEG Export Plugin. Write JSON format - + pt::peg::export::peg PEG Export Plugin. Write PEG format - + pt::peg::from::container PEG Conversion. From CONTAINER format - + pt::peg::from::json PEG Conversion. Read JSON format - + pt::peg::from::peg PEG Conversion. Read PEG format - + pt::peg::import PEG Import - + pt::peg::import::container PEG Import Plugin. From CONTAINER format - + pt::peg::import::json PEG Import Plugin. Read JSON format - + pt::peg::import::peg PEG Import Plugin. Read PEG format - + pt::peg::interp Interpreter for parsing expression grammars - + pt::peg::to::container PEG Conversion. Write CONTAINER format - + pt::peg::to::cparam PEG Conversion. Write CPARAM format - + pt::peg::to::json PEG Conversion. Write JSON format - + pt::peg::to::param PEG Conversion. Write PARAM format - + pt::peg::to::peg PEG Conversion. Write PEG format - + pt::peg::to::tclparam PEG Conversion. Write TCLPARAM format - + pt::peg_language PEG Language Tutorial - + pt::pegrammar Introduction to Parsing Expression Grammars - + pt::pgen Parser Generator - + pt::rde Parsing Runtime Support, PARAM based - + pt::tclparam::configuration::snit Tcl/PARAM, Canned configuration, Snit - + pt::tclparam::configuration::tcloo Tcl/PARAM, Canned configuration, Tcloo - + pt::util General utilities - + pt_export_api Parser Tools Export API - + pt_import_api Parser Tools Import API - + pt_introduction Introduction to Parser Tools - + pt_parse_peg Parser Tools PEG Parser - + pt_parser_api Parser API - + pt_peg_op Parser Tools PE Grammar Utility Operations
Procedures, arguments, parameters, options
Index: embedded/www/toc1.html ================================================================== --- embedded/www/toc1.html +++ embedded/www/toc1.html @@ -1161,158 +1161,162 @@ pt::cparam::configuration::critcl C/PARAM, Canned configuration, Critcl +pt::cparam::configuration::tea +C/PARAM, Canned configuration, TEA + + pt::json_language The JSON Grammar Exchange Format - + pt::param PackRat Machine Specification - + pt::pe Parsing Expression Serialization - + pt::pe::op Parsing Expression Utilities - + pt::peg Parsing Expression Grammar Serialization - + pt::peg::container PEG Storage - + pt::peg::container::peg PEG Storage. Canned PEG grammar specification - + pt::peg::export PEG Export - + pt::peg::export::container PEG Export Plugin. Write CONTAINER format - + pt::peg::export::json PEG Export Plugin. Write JSON format - + pt::peg::export::peg PEG Export Plugin. Write PEG format - + pt::peg::from::container PEG Conversion. From CONTAINER format - + pt::peg::from::json PEG Conversion. Read JSON format - + pt::peg::from::peg PEG Conversion. Read PEG format - + pt::peg::import PEG Import - + pt::peg::import::container PEG Import Plugin. From CONTAINER format - + pt::peg::import::json PEG Import Plugin. Read JSON format - + pt::peg::import::peg PEG Import Plugin. Read PEG format - + pt::peg::interp Interpreter for parsing expression grammars - + pt::peg::to::container PEG Conversion. Write CONTAINER format - + pt::peg::to::cparam PEG Conversion. Write CPARAM format - + pt::peg::to::json PEG Conversion. Write JSON format - + pt::peg::to::param PEG Conversion. Write PARAM format - + pt::peg::to::peg PEG Conversion. Write PEG format - + pt::peg::to::tclparam PEG Conversion. Write TCLPARAM format - + pt::peg_language PEG Language Tutorial - + pt::pegrammar Introduction to Parsing Expression Grammars - + pt::pgen Parser Generator - + pt::rde Parsing Runtime Support, PARAM based - + pt::tclparam::configuration::snit Tcl/PARAM, Canned configuration, Snit - + pt::tclparam::configuration::tcloo Tcl/PARAM, Canned configuration, Tcloo - + pt::util General utilities - + pt_export_api Parser Tools Export API - + pt_import_api Parser Tools Import API - + pt_introduction Introduction to Parser Tools - + pt_parse_peg Parser Tools PEG Parser - + pt_parser_api Parser API - + pt_peg_op Parser Tools PE Grammar Utility Operations
rc4
Index: modules/pt/pkgIndex.tcl ================================================================== --- modules/pt/pkgIndex.tcl +++ modules/pt/pkgIndex.tcl @@ -57,10 +57,11 @@ # PEG grammar specification, as CONTAINER package ifneeded pt::peg::container::peg 1 [list source [file join $dir pt_peg_container_peg.tcl]] # */PARAM support (canned configurations). package ifneeded pt::cparam::configuration::critcl 1.0.2 [list source [file join $dir pt_cparam_config_critcl.tcl]] +package ifneeded pt::cparam::configuration::tea 0.1 [list source [file join $dir pt_cparam_config_tea.tcl]] package ifneeded pt::tclparam::configuration::snit 1.0.2 [list source [file join $dir pt_tclparam_config_snit.tcl]] package ifneeded pt::tclparam::configuration::tcloo 1.0.4 [list source [file join $dir pt_tclparam_config_tcloo.tcl]] # Parser generator core. package ifneeded pt::pgen 1.0.3 [list source [file join $dir pt_pgen.tcl]] Index: modules/pt/pt_cparam_config_critcl.tcl ================================================================== --- modules/pt/pt_cparam_config_critcl.tcl +++ modules/pt/pt_cparam_config_critcl.tcl @@ -1,7 +1,11 @@ # -*- tcl -*- # Copyright (c) 2009-2014 Andreas Kupries + +# TODO: Refactor this and pt::cparam::configuration::critcl to avoid +# TODO: duplication of the supporting code (creation of the RDE +# TODO: amalgamation, basic C template). # Canned configuration for the converter to C/PARAM representation, # causing generation of a proper critcl-based parser. # The requirements of the embedded template are not our requirements. ADDED modules/pt/pt_cparam_config_tea.man Index: modules/pt/pt_cparam_config_tea.man ================================================================== --- /dev/null +++ modules/pt/pt_cparam_config_tea.man @@ -0,0 +1,48 @@ +[vset VERSION 0.1] +[comment {-*- text -*- doctools manpage}] +[manpage_begin pt::cparam::configuration::tea n [vset VERSION]] +[include include/module.inc] +[titledesc {C/PARAM, Canned configuration, TEA}] +[require pt::cparam::configuration::tea [opt [vset VERSION]]] +[description] +[include include/ref_intro.inc] + +This package is an adjunct to [package pt::peg::to::cparam], to make +the use of this highly configurable package easier by providing a +canned configuration. When applied this configuration causes the +package [package pt::peg::to::cparam] to generate plain parser code +ready for inclusion into a [term TEA]-based C extension. + +[para] + +It is a supporting package in the Core Layer of Parser Tools. +[para][image arch_core_support][para] + +[section API] + +[list_begin definitions] + +[call [cmd ::pt::cparam::configuration::tea] [method def] \ + [arg name] [arg pkg] [arg version] [arg cmdprefix]] + +The command applies the configuration provided by this package to the +[arg cmdprefix], causing the creation of [package tea]-based parsers +whose class is [arg name], in package [arg pkg] with [arg version]. + +[para] + +The use of a command prefix as API allows application of the +configuration to not only [package pt::peg::to::cparam] +([cmd {pt::peg::to::cparam configure}]), but also export manager +instances and PEG containers ([cmd {$export configuration set}] and +[cmd {[$container exporter] configuration set}] respectively). + +[para] + +Or anything other command prefix accepting two arguments, option and +value. + +[list_end] + +[include include/feedback.inc] +[manpage_end] ADDED modules/pt/pt_cparam_config_tea.tcl Index: modules/pt/pt_cparam_config_tea.tcl ================================================================== --- /dev/null +++ modules/pt/pt_cparam_config_tea.tcl @@ -0,0 +1,465 @@ +# -*- tcl -*- +# Copyright (c) 2014 Christian Gollwitzer + +# TODO: Refactor this and pt::cparam::configuration::critcl to avoid +# TODO: duplication of the supporting code (creation of the RDE +# TODO: amalgamation, basic C template). + +# Canned configuration for the converter to C/PARAM representation, +# causing generation of a C-based parser which can be plugged into a +# TEA-based C extension. The supporting files, i.e. configure.in, +# Makefile.in, etc. still have to be written separately, and manually. + +# The generated file can easily be compiled with a single +# +# gcc -dynamiclib -o .dylib .c -DUSE_TCL_STUBS -ltclstub8.5 +# +# or similar, or included in a larger package, if added to the source +# files and by invoking the _Init() function within the init +# function of the main package. +# +# TODO: Put the above note/semi-example into the manpage for this generator. + +# # ## ### ##### ######## ############# ##################### +## Requirements + +package require Tcl 8.5 ; # Required runtime. + +# # ## ### ##### ######## ############# ##################### +## + +namespace eval ::pt::cparam::configuration::tea { + namespace export def + namespace ensemble create + + # @mdgen OWNER: rde_critcl/util.* + # @mdgen OWNER: rde_critcl/stack.* + # @mdgen OWNER: rde_critcl/tc.* + # @mdgen OWNER: rde_critcl/param.* + # Access to the rde_critcl files forming the low-level runtime + variable selfdir [file dirname [file normalize [info script]]] +} + +# # ## ### ##### ######## ############# +## Public API + +# Check that the proposed serialization of an abstract syntax tree is +# indeed such. + +proc ::pt::cparam::configuration::tea::def {class pkg version cmd} { + # TODO :: See if we can consolidate the API for converters, + # TODO :: plugins, export manager, and container in some way. + # TODO :: Container may make exporter manager available through + # TODO :: public method. + + # class = The namespace/prefix for the generated commands. + # pkg = The name of the generated package / parser. + # version = The version of the generated package / parser. + + if {[string first :: $class] < 0} { + set cheader $class + set ctrailer $class + } else { + set cheader [namespace qualifier $class] + set ctrailer [namespace tail $class] + } + + set pkghead [string range $pkg 0 0] + set pkgtail [string range $pkg 1 end] + set pkglowcase "[string toupper $pkghead][string tolower $pkgtail]" + + lappend map @@RUNTIME@@ [GetRuntime] + lappend map @@PKG@@ $pkg + lappend map @@PKGLOWCASE@@ $pkglowcase + lappend map @@VERSION@@ $version + lappend map @@CLASS@@ $class + lappend map @@CHEAD@@ $cheader + lappend map @@CTAIL@@ $ctrailer + lappend map \n\t \n ;# undent the template + + {*}$cmd -main MAIN + {*}$cmd -indent 8 + {*}$cmd -template [string trim \ + [string map $map { + /************************************************************ + ** + ** TEA-based C/PARAM implementation of the parsing + ** expression grammar + ** + ** @name@ + ** + ** Generated from file @file@ + ** for user @user@ + ** + * * ** *** ***** ******** ************* *********************/ + #include + #include + #include + #include + #define SCOPE static + +@@RUNTIME@@ +@code@ + /* -*- c -*- */ + + typedef struct PARSERg { + long int counter; + char buf [50]; + } PARSERg; + + static void + PARSERgRelease (ClientData cd, Tcl_Interp* interp) + { + ckfree((char*) cd); + } + + static const char* + PARSERnewName (Tcl_Interp* interp) + { +#define KEY "tcllib/parser/@@PKG@@/TEA" + + Tcl_InterpDeleteProc* proc = PARSERgRelease; + PARSERg* parserg; + + parserg = Tcl_GetAssocData (interp, KEY, &proc); + if (parserg == NULL) { + parserg = (PARSERg*) ckalloc (sizeof (PARSERg)); + parserg->counter = 0; + + Tcl_SetAssocData (interp, KEY, proc, + (ClientData) parserg); + } + + parserg->counter ++; + sprintf (parserg->buf, "@@CTAIL@@%d", parserg->counter); + return parserg->buf; +#undef KEY + } + + static void + PARSERdeleteCmd (ClientData clientData) + { + /* + * Release the whole PARSER + * (Low-level engine only actually). + */ + rde_param_del ((RDE_PARAM) clientData); + } + + + /* * ** *** ***** ******** ************* + ** Functions implementing the object methods, and helper. + */ + + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp); + + static int parser_PARSE (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + int mode; + Tcl_Channel chan; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "chan"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, + Tcl_GetString (objv[2]), + &mode); + + if (!chan) { + return TCL_ERROR; + } + + rde_param_reset (p, chan); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + static int parser_PARSET (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + char* buf; + int len; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "text"); + return TCL_ERROR; + } + + buf = Tcl_GetStringFromObj (objv[2], &len); + + rde_param_reset (p, NULL); + rde_param_data (p, buf, len); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + /* See also rde_critcl/m.c, param_COMPLETE() */ + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp) + { + if (rde_param_query_st (p)) { + long int ac; + Tcl_Obj** av; + + rde_param_query_ast (p, &ac, &av); + + if (ac > 1) { + Tcl_Obj** lv = NALLOC (3+ac, Tcl_Obj*); + + memcpy(lv + 3, av, ac * sizeof (Tcl_Obj*)); + lv [0] = Tcl_NewObj (); + lv [1] = Tcl_NewIntObj (1 + rde_param_query_lstop (p)); + lv [2] = Tcl_NewIntObj (rde_param_query_cl (p)); + + Tcl_SetObjResult (interp, Tcl_NewListObj (3, lv)); + ckfree ((char*) lv); + + } else if (ac == 0) { + /* + * Match, but no AST. This is possible if the grammar + * consists of only the start expression. + */ + Tcl_SetObjResult (interp, Tcl_NewStringObj ("",-1)); + } else { + Tcl_SetObjResult (interp, av [0]); + } + + return TCL_OK; + } else { + Tcl_Obj* xv [1]; + const ERROR_STATE* er = rde_param_query_er (p); + Tcl_Obj* res = rde_param_query_er_tcl (p, er); + /* res = list (location, list(msg)) */ + + /* Stick the exception type-tag before the existing elements */ + xv [0] = Tcl_NewStringObj ("pt::rde",-1); + Tcl_ListObjReplace(interp, res, 0, 0, 1, xv); + + Tcl_SetErrorCode (interp, "PT", "RDE", "SYNTAX", NULL); + Tcl_SetObjResult (interp, res); + return TCL_ERROR; + } + } + + + /* * ** *** ***** ******** ************* + ** Object command, method dispatch. + */ + static int parser_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + RDE_PARAM p = (RDE_PARAM) cd; + int m, res; + + static CONST char* methods [] = { + "destroy", "parse", "parset", NULL + }; + enum methods { + M_DESTROY, M_PARSE, M_PARSET + }; + + if (objc < 2) { + Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option", + 0, &m) != TCL_OK) { + return TCL_ERROR; + } + + /* Dispatch to methods. They check the #args in + * detail before performing the requested + * functionality + */ + + switch (m) { + case M_DESTROY: + if (objc != 2) { + Tcl_WrongNumArgs (interp, 2, objv, NULL); + return TCL_ERROR; + } + + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) rde_param_query_clientdata (p)); + return TCL_OK; + + case M_PARSE: res = parser_PARSE (p, interp, objc, objv); break; + case M_PARSET: res = parser_PARSET (p, interp, objc, objv); break; + default: + /* Not coming to this place */ + ASSERT (0,"Reached unreachable location"); + } + + return res; + } + + /** * ** *** ***** ******** ************* + * Class command, i.e. object construction. + */ + static int ParserClassCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const*objv) { + /* + * Syntax: No arguments beyond the name + */ + + RDE_PARAM parser; + CONST char* name; + Tcl_Obj* fqn; + Tcl_CmdInfo ci; + Tcl_Command c; + +#define USAGE "?name?" + + if ((objc != 2) && (objc != 1)) { + Tcl_WrongNumArgs (interp, 1, objv, USAGE); + return TCL_ERROR; + } + + if (objc < 2) { + name = PARSERnewName (interp); + } else { + name = Tcl_GetString (objv [1]); + } + + if (!Tcl_StringMatch (name, "::*")) { + /* Relative name. Prefix with current namespace */ + + Tcl_Eval (interp, "namespace current"); + fqn = Tcl_GetObjResult (interp); + fqn = Tcl_DuplicateObj (fqn); + Tcl_IncrRefCount (fqn); + + if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { + Tcl_AppendToObj (fqn, "::", -1); + } + Tcl_AppendToObj (fqn, name, -1); + } else { + fqn = Tcl_NewStringObj (name, -1); + Tcl_IncrRefCount (fqn); + } + Tcl_ResetResult (interp); + + if (Tcl_GetCommandInfo (interp, + Tcl_GetString (fqn), + &ci)) { + Tcl_Obj* err; + + err = Tcl_NewObj (); + Tcl_AppendToObj (err, "command \"", -1); + Tcl_AppendObjToObj (err, fqn); + Tcl_AppendToObj (err, "\" already exists", -1); + + Tcl_DecrRefCount (fqn); + Tcl_SetObjResult (interp, err); + return TCL_ERROR; + } + + parser = rde_param_new (sizeof(p_string)/sizeof(char*), (char**) p_string); + c = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), + parser_objcmd, (ClientData) parser, + PARSERdeleteCmd); + rde_param_clientdata (parser, (ClientData) c); + Tcl_SetObjResult (interp, fqn); + Tcl_DecrRefCount (fqn); + return TCL_OK; + } + + int @@PKGLOWCASE@@_Init(Tcl_Interp* interp) { + if (interp == 0) return TCL_ERROR; + + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + + if (Tcl_CreateObjCommand(interp, "@@CLASS@@", ParserClassCmd , NULL, NULL) == NULL) { + Tcl_SetResult(interp, "Can't create constructor", NULL); + return TCL_ERROR; + } + + + Tcl_PkgProvide(interp, "@@PKG@@", "0.1"); + + return TCL_OK; + } + + }]] + + return +} + +proc ::pt::cparam::configuration::tea::GetRuntime {} { + # This is the C code for the RDE, i.e. the implementation of + # pt::rde. Only the low-level engine is imported, the Tcl + # interface layer is ignored. This generated parser provides its + # own layer for that. + + # We are inlining the code (making the functions static) to + # prevent any conflict with the support for pt::rde, should both + # be put into the same shared library. + + variable selfdir + + set code {} + + foreach f { + rde_critcl/util.h + rde_critcl/stack.h + rde_critcl/tc.h + rde_critcl/param.h + rde_critcl/util.c + rde_critcl/stack.c + rde_critcl/tc.c + rde_critcl/param.c + } { + # Load C code. + set c [open $selfdir/$f] + set d [read $c] + close $c + + # Strip include directives and anything explicitly excluded. + set skip 0 + set n {} + foreach l [split $d \n] { + if {[string match {*#include*} $l]} { + continue + } + if {[string match {*SKIP START*} $l]} { + set skip 1 + continue + } + if {[string match {*SKIP END*} $l]} { + set skip 0 + continue + } + if {$skip} continue + lappend n $l + } + set d [join $n \n] + + # Strip comments, trailing whitespace, empty lines. + set d [regsub -all {/\*.*?\*/} $d {}] + set d [regsub -all {//.*?\n} $d {}] + set d [regsub -all {[ ]+$} $d {}] + while {1} { + set n [string map [list \n\n \n] $d] + if {$n eq $d} break + set d $n + } + + # Indent code. + lappend code "#line 1 \"$f\"" + foreach l [split $d \n] { + if {$l ne ""} { set l \t$l } + lappend code $l + } + } + + #lappend code "#line x \"X\"" + return [join $code \n] +} + +# # ## ### ##### ######## ############# + +namespace eval ::pt::cparam::configuration::tea {} + +# # ## ### ##### ######## ############# ##################### +## Ready + +package provide pt::cparam::configuration::tea 0.1 +return ADDED modules/pt/pt_cparam_config_tea.test Index: modules/pt/pt_cparam_config_tea.test ================================================================== --- /dev/null +++ modules/pt/pt_cparam_config_tea.test @@ -0,0 +1,50 @@ +# -*- tcl -*- +# pt_cparam_config_critcl.test: tests for the pt::peg::to::cparam +# converter package configured for critcl. +# +# Copyright (c) 2009 by Andreas Kupries +# All rights reserved. +# +# RCS: @(#) $Id: pt_cparam_config_critcl.test,v 1.1 2010/03/26 05:07:24 andreas_kupries Exp $ + +# ------------------------------------------------------------------------- + +source [file join \ + [file dirname [file dirname [file join [pwd] [info script]]]] \ + devtools testutilities.tcl] + +testsNeedTcl 8.5 +testsNeedTcltest 2 + +support { + useAccel [useTcllibC] struct/sets.tcl struct::set ; # used by pt::pe::op, + TestAccelInit struct::set ; # however not by the + # # commands used here. + + use fileutil/fileutil.tcl fileutil ;# tests/common + use textutil/adjust.tcl textutil::adjust + + useLocal pt_pexpression.tcl pt::pe + useLocal pt_pexpr_op.tcl pt::pe::op + useLocal pt_pegrammar.tcl pt::peg + useLocal text_write.tcl text::write + useLocal char.tcl char + + useLocal pt_peg_to_cparam.tcl pt::peg::to::cparam + + source [localPath tests/common] +} +testing { + useLocal pt_cparam_config_tea.tcl pt::cparam::configuration::tea +} + +set mytestdir tests/data + +# ------------------------------------------------------------------------- + +source [localPath tests/pt_cparam_config_tea.tests] + +# ------------------------------------------------------------------------- +TestAccelExit struct::set +testsuiteCleanup +return Index: modules/pt/pt_pgen.tcl ================================================================== --- modules/pt/pt_pgen.tcl +++ modules/pt/pt_pgen.tcl @@ -22,10 +22,11 @@ package require pt::peg::to::tclparam ; # PARAM assembly, embedded into Tcl package require pt::peg::to::cparam ; # PARAM assembly, embedded into C package require pt::tclparam::configuration::snit 1.0.2 ; # PARAM/Tcl, snit::type package require pt::tclparam::configuration::tcloo 1.0.4 ; # PARAM/Tcl, TclOO class package require pt::cparam::configuration::critcl 1.0.2 ; # PARAM/C, in critcl +package require pt::cparam::configuration::tea ; # PARAM/C, in TEA # ### ### ### ######### ######### ######### ## Implementation namespace eval ::pt::pgen { @@ -53,11 +54,11 @@ # # ## ### ##### ######## ############# ## Internals - Generating the parser. namespace eval ::pt::pgen::Write { - namespace export json peg container param snit oo critcl c + namespace export json peg container param snit oo critcl c tea namespace ensemble create } proc ::pt::pgen::Write::json {args} { # args = (option value)... grammar @@ -104,10 +105,25 @@ $class $package $version \ {pt::peg::to::tclparam configure} return [pt::peg::to::tclparam convert [lindex $args end]] } + +proc ::pt::pgen::Write::tea {args} { + # args = (option value)... grammar + # Class -> touches/defines variable 'class' + # Package -> touches/defines variable 'package' + # Version -> touches/defines variable 'version' + pt::peg::to::cparam configure {*}[Package [Version [Class [lrange $args 0 end-1]]]] + ClassPackageDefaults + + pt::cparam::configuration::tea def \ + $class $package $version \ + {pt::peg::to::cparam configure} + + return [pt::peg::to::cparam convert [lindex $args end]] +} proc ::pt::pgen::Write::critcl {args} { # args = (option value)... grammar # Class -> touches/defines variable 'class' # Package -> touches/defines variable 'package' ADDED modules/pt/tests/data/ok/peg_cparam-tea/0_basic_arithmetic Index: modules/pt/tests/data/ok/peg_cparam-tea/0_basic_arithmetic ================================================================== --- /dev/null +++ modules/pt/tests/data/ok/peg_cparam-tea/0_basic_arithmetic @@ -0,0 +1,2345 @@ +/************************************************************ +** +** TEA-based C/PARAM implementation of the parsing +** expression grammar +** +** TEMPLATE +** +** Generated from file TEST +** for user unknown +** +* * ** *** ***** ******** ************* *********************/ + #include + #include + #include + #include + #define SCOPE static + +#line 1 "rde_critcl/util.h" + + #ifndef _RDE_UTIL_H + #define _RDE_UTIL_H 1 + #ifndef SCOPE + #define SCOPE + #endif + #define ALLOC(type) (type *) ckalloc (sizeof (type)) + #define NALLOC(n,type) (type *) ckalloc ((n) * sizeof (type)) + #undef RDE_DEBUG + #define RDE_DEBUG 1 + #undef RDE_TRACE + #ifdef RDE_DEBUG + #define STOPAFTER(x) { static int count = (x); count --; if (!count) { Tcl_Panic ("stop"); } } + #define XSTR(x) #x + #define STR(x) XSTR(x) + #define RANGEOK(i,n) ((0 <= (i)) && (i < (n))) + #define ASSERT(x,msg) if (!(x)) { Tcl_Panic (msg " (" #x "), in file " __FILE__ " @line " STR(__LINE__));} + #define ASSERT_BOUNDS(i,n) ASSERT (RANGEOK(i,n),"array index out of bounds: " STR(i) " >= " STR(n)) + #else + #define STOPAFTER(x) + #define ASSERT(x,msg) + #define ASSERT_BOUNDS(i,n) + #endif + #ifdef RDE_TRACE + SCOPE void trace_enter (const char* fun); + SCOPE void trace_return (const char *pat, ...); + SCOPE void trace_printf (const char *pat, ...); + #define ENTER(fun) trace_enter (fun) + #define RETURN(format,x) trace_return (format,x) ; return x + #define RETURNVOID trace_return ("%s","(void)") ; return + #define TRACE0(x) trace_printf0 x + #define TRACE(x) trace_printf x + #else + #define ENTER(fun) + #define RETURN(f,x) return x + #define RETURNVOID return + #define TRACE0(x) + #define TRACE(x) + #endif + #endif + + +#line 1 "rde_critcl/stack.h" + + #ifndef _RDE_DS_STACK_H + #define _RDE_DS_STACK_H 1 + typedef void (*RDE_STACK_CELL_FREE) (void* cell); + typedef struct RDE_STACK_* RDE_STACK; + static const int RDE_STACK_INITIAL_SIZE = 256; + #endif + + +#line 1 "rde_critcl/tc.h" + + #ifndef _RDE_DS_TC_H + #define _RDE_DS_TC_H 1 + typedef struct RDE_TC_* RDE_TC; + #endif + + +#line 1 "rde_critcl/param.h" + + #ifndef _RDE_DS_PARAM_H + #define _RDE_DS_PARAM_H 1 + typedef struct RDE_PARAM_* RDE_PARAM; + typedef struct ERROR_STATE { + int refCount; + long int loc; + RDE_STACK msg; + } ERROR_STATE; + typedef struct NC_STATE { + long int CL; + long int ST; + Tcl_Obj* SV; + ERROR_STATE* ER; + } NC_STATE; + #endif + + +#line 1 "rde_critcl/util.c" + + #ifdef RDE_TRACE + typedef struct F_STACK { + const char* str; + struct F_STACK* down; + } F_STACK; + static F_STACK* top = 0; + static int level = 0; + static void + push (const char* str) + { + F_STACK* new = ALLOC (F_STACK); + new->str = str; + new->down = top; + top = new; + level += 4; + } + static void + pop (void) + { + F_STACK* next = top->down; + level -= 4; + ckfree ((char*)top); + top = next; + } + static void + indent (void) + { + int i; + for (i = 0; i < level; i++) { + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + if (top) { + fwrite(top->str, 1, strlen(top->str), stdout); + fflush (stdout); + } + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + SCOPE void + trace_enter (const char* fun) + { + push (fun); + indent(); + fwrite("ENTER\n", 1, 6, stdout); + fflush (stdout); + } + static char msg [1024*1024]; + SCOPE void + trace_return (const char *pat, ...) + { + int len; + va_list args; + indent(); + fwrite("RETURN = ", 1, 9, stdout); + fflush (stdout); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + pop(); + } + SCOPE void + trace_printf (const char *pat, ...) + { + int len; + va_list args; + indent(); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + SCOPE void + trace_printf0 (const char *pat, ...) + { + int len; + va_list args; + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + #endif + + +#line 1 "rde_critcl/stack.c" + + typedef struct RDE_STACK_ { + long int max; + long int top; + RDE_STACK_CELL_FREE freeCellProc; + void** cell; + } RDE_STACK_; + + SCOPE RDE_STACK + rde_stack_new (RDE_STACK_CELL_FREE freeCellProc) + { + RDE_STACK s = ALLOC (RDE_STACK_); + s->cell = NALLOC (RDE_STACK_INITIAL_SIZE, void*); + s->max = RDE_STACK_INITIAL_SIZE; + s->top = 0; + s->freeCellProc = freeCellProc; + return s; + } + SCOPE void + rde_stack_del (RDE_STACK s) + { + if (s->freeCellProc && s->top) { + long int i; + for (i=0; i < s->top; i++) { + ASSERT_BOUNDS(i,s->max); + s->freeCellProc ( s->cell [i] ); + } + } + ckfree ((char*) s->cell); + ckfree ((char*) s); + } + SCOPE void + rde_stack_push (RDE_STACK s, void* item) + { + if (s->top >= s->max) { + long int new = s->max ? (2 * s->max) : RDE_STACK_INITIAL_SIZE; + void** cell = (void**) ckrealloc ((char*) s->cell, new * sizeof(void*)); + ASSERT (cell,"Memory allocation failure for RDE stack"); + s->max = new; + s->cell = cell; + } + ASSERT_BOUNDS(s->top,s->max); + s->cell [s->top] = item; + s->top ++; + } + SCOPE void* + rde_stack_top (RDE_STACK s) + { + ASSERT_BOUNDS(s->top-1,s->max); + return s->cell [s->top - 1]; + } + SCOPE void + rde_stack_pop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + if (s->freeCellProc) { + while (n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + n --; + } + } else { + s->top -= n; + } + } + SCOPE void + rde_stack_trim (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad trimsize"); + if (s->freeCellProc) { + while (s->top > n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + } + } else { + s->top = n; + } + } + SCOPE void + rde_stack_drop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + s->top -= n; + } + SCOPE void + rde_stack_move (RDE_STACK dst, RDE_STACK src) + { + ASSERT (dst->freeCellProc == src->freeCellProc, "Ownership mismatch"); + + while (src->top > 0) { + src->top --; + ASSERT_BOUNDS(src->top,src->max); + rde_stack_push (dst, src->cell [src->top] ); + } + } + SCOPE void + rde_stack_get (RDE_STACK s, long int* cn, void*** cc) + { + *cn = s->top; + *cc = s->cell; + } + SCOPE long int + rde_stack_size (RDE_STACK s) + { + return s->top; + } + + +#line 1 "rde_critcl/tc.c" + + typedef struct RDE_TC_ { + int max; + int num; + char* str; + RDE_STACK off; + } RDE_TC_; + + SCOPE RDE_TC + rde_tc_new (void) + { + RDE_TC tc = ALLOC (RDE_TC_); + tc->max = RDE_STACK_INITIAL_SIZE; + tc->num = 0; + tc->str = NALLOC (RDE_STACK_INITIAL_SIZE, char); + tc->off = rde_stack_new (NULL); + return tc; + } + SCOPE void + rde_tc_del (RDE_TC tc) + { + rde_stack_del (tc->off); + ckfree (tc->str); + ckfree ((char*) tc); + } + SCOPE long int + rde_tc_size (RDE_TC tc) + { + return rde_stack_size (tc->off); + } + SCOPE void + rde_tc_clear (RDE_TC tc) + { + tc->num = 0; + rde_stack_trim (tc->off, 0); + } + SCOPE char* + rde_tc_append (RDE_TC tc, char* string, long int len) + { + long int base = tc->num; + long int off = tc->num; + char* ch; + int clen; + Tcl_UniChar uni; + if (len < 0) { + len = strlen (string); + } + + if (!len) { + return tc->str + base; + } + + if ((tc->num + len) >= tc->max) { + int new = len + (tc->max ? (2 * tc->max) : RDE_STACK_INITIAL_SIZE); + char* str = ckrealloc (tc->str, new * sizeof(char)); + ASSERT (str,"Memory allocation failure for token character array"); + tc->max = new; + tc->str = str; + } + tc->num += len; + ASSERT_BOUNDS(tc->num,tc->max); + ASSERT_BOUNDS(off,tc->max); + ASSERT_BOUNDS(off+len-1,tc->max); + ASSERT_BOUNDS(off+len-1,tc->num); + memcpy (tc->str + off, string, len); + + ch = string; + while (ch < (string + len)) { + ASSERT_BOUNDS(off,tc->num); + rde_stack_push (tc->off, (void*) off); + clen = Tcl_UtfToUniChar (ch, &uni); + off += clen; + ch += clen; + } + return tc->str + base; + } + SCOPE void + rde_tc_get (RDE_TC tc, int at, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + off = ov [at]; + if ((at+1) == oc) { + end = tc->num; + } else { + end = ov [at+1]; + } + TRACE (("rde_tc_get (RDE_TC %p, @ %d) => %d.[%d ... %d]/%d",tc,at,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + SCOPE void + rde_tc_get_s (RDE_TC tc, int at, int last, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + ASSERT_BOUNDS(last,oc); + off = ov [at]; + if ((last+1) == oc) { + end = tc->num; + } else { + end = ov [last+1]; + } + TRACE (("rde_tc_get_s (RDE_TC %p, @ %d .. %d) => %d.[%d ... %d]/%d",tc,at,last,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + + +#line 1 "rde_critcl/param.c" + + typedef struct RDE_PARAM_ { + Tcl_Channel IN; + Tcl_Obj* readbuf; + char* CC; + long int CC_len; + RDE_TC TC; + long int CL; + RDE_STACK LS; + ERROR_STATE* ER; + RDE_STACK ES; + long int ST; + Tcl_Obj* SV; + Tcl_HashTable NC; + + RDE_STACK ast ; + RDE_STACK mark ; + + long int numstr; + char** string; + + ClientData clientData; + } RDE_PARAM_; + typedef int (*UniCharClass) (int); + typedef enum test_class_id { + tc_alnum, + tc_alpha, + tc_ascii, + tc_control, + tc_ddigit, + tc_digit, + tc_graph, + tc_lower, + tc_printable, + tc_punct, + tc_space, + tc_upper, + tc_wordchar, + tc_xdigit + } test_class_id; + static void ast_node_free (void* n); + static void error_state_free (void* es); + static void error_set (RDE_PARAM p, int s); + static void nc_clear (RDE_PARAM p); + static int UniCharIsAscii (int character); + static int UniCharIsHexDigit (int character); + static int UniCharIsDecDigit (int character); + static void test_class (RDE_PARAM p, UniCharClass class, test_class_id id); + static int er_int_compare (const void* a, const void* b); + #define SV_INIT(p) \ + p->SV = NULL; \ + TRACE (("SV_INIT (%p => %p)", (p), (p)->SV)) + #define SV_SET(p,newsv) \ + if (((p)->SV) != (newsv)) { \ + TRACE (("SV_CLEAR/set (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = (newsv); \ + TRACE (("SV_SET (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_IncrRefCount ((p)->SV); \ + } \ + } + #define SV_CLEAR(p) \ + TRACE (("SV_CLEAR (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = NULL + #define ER_INIT(p) \ + p->ER = NULL; \ + TRACE (("ER_INIT (%p => %p)", (p), (p)->ER)) + #define ER_CLEAR(p) \ + error_state_free ((p)->ER); \ + (p)->ER = NULL + SCOPE RDE_PARAM + rde_param_new (long int nstr, char** strings) + { + RDE_PARAM p; + ENTER ("rde_param_new"); + TRACE (("\tINT %d strings @ %p", nstr, strings)); + p = ALLOC (RDE_PARAM_); + p->numstr = nstr; + p->string = strings; + p->readbuf = Tcl_NewObj (); + Tcl_IncrRefCount (p->readbuf); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_InitHashTable (&p->NC, TCL_ONE_WORD_KEYS); + p->IN = NULL; + p->CL = -1; + p->ST = 0; + ER_INIT (p); + SV_INIT (p); + p->CC = NULL; + p->CC_len = 0; + p->TC = rde_tc_new (); + p->ES = rde_stack_new (error_state_free); + p->LS = rde_stack_new (NULL); + p->ast = rde_stack_new (ast_node_free); + p->mark = rde_stack_new (NULL); + RETURN ("%p", p); + } + SCOPE void + rde_param_del (RDE_PARAM p) + { + ENTER ("rde_param_del"); + TRACE (("RDE_PARAM %p",p)); + ER_CLEAR (p); TRACE (("\ter_clear")); + SV_CLEAR (p); TRACE (("\tsv_clear")); + nc_clear (p); TRACE (("\tnc_clear")); + Tcl_DeleteHashTable (&p->NC); TRACE (("\tnc hashtable delete")); + rde_tc_del (p->TC); TRACE (("\ttc clear")); + rde_stack_del (p->ES); TRACE (("\tes clear")); + rde_stack_del (p->LS); TRACE (("\tls clear")); + rde_stack_del (p->ast); TRACE (("\tast clear")); + rde_stack_del (p->mark); TRACE (("\tmark clear")); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_DecrRefCount (p->readbuf); + ckfree ((char*) p); + RETURNVOID; + } + SCOPE void + rde_param_reset (RDE_PARAM p, Tcl_Channel chan) + { + ENTER ("rde_param_reset"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("Tcl_Channel %p",chan)); + p->IN = chan; + p->CL = -1; + p->ST = 0; + p->CC = NULL; + p->CC_len = 0; + ER_CLEAR (p); + SV_CLEAR (p); + nc_clear (p); + rde_tc_clear (p->TC); + rde_stack_trim (p->ES, 0); + rde_stack_trim (p->LS, 0); + rde_stack_trim (p->ast, 0); + rde_stack_trim (p->mark, 0); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + RETURNVOID; + } + SCOPE void + rde_param_update_strings (RDE_PARAM p, long int nstr, char** strings) + { + ENTER ("rde_param_update_strings"); + TRACE (("RDE_PARAM %p", p)); + TRACE (("INT %d strings", nstr)); + p->numstr = nstr; + p->string = strings; + RETURNVOID; + } + SCOPE void + rde_param_data (RDE_PARAM p, char* buf, long int len) + { + (void) rde_tc_append (p->TC, buf, len); + } + SCOPE void + rde_param_clientdata (RDE_PARAM p, ClientData clientData) + { + p->clientData = clientData; + } + static void + nc_clear (RDE_PARAM p) + { + Tcl_HashSearch hs; + Tcl_HashEntry* he; + Tcl_HashTable* tablePtr; + for(he = Tcl_FirstHashEntry(&p->NC, &hs); + he != NULL; + he = Tcl_FirstHashEntry(&p->NC, &hs)) { + Tcl_HashSearch hsc; + Tcl_HashEntry* hec; + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (he); + for(hec = Tcl_FirstHashEntry(tablePtr, &hsc); + hec != NULL; + hec = Tcl_NextHashEntry(&hsc)) { + NC_STATE* scs = Tcl_GetHashValue (hec); + error_state_free (scs->ER); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + ckfree ((char*) scs); + } + Tcl_DeleteHashTable (tablePtr); + ckfree ((char*) tablePtr); + Tcl_DeleteHashEntry (he); + } + } + SCOPE ClientData + rde_param_query_clientdata (RDE_PARAM p) + { + return p->clientData; + } + SCOPE void + rde_param_query_amark (RDE_PARAM p, long int* mc, long int** mv) + { + rde_stack_get (p->mark, mc, (void***) mv); + } + SCOPE void + rde_param_query_ast (RDE_PARAM p, long int* ac, Tcl_Obj*** av) + { + rde_stack_get (p->ast, ac, (void***) av); + } + SCOPE const char* + rde_param_query_in (RDE_PARAM p) + { + return p->IN + ? Tcl_GetChannelName (p->IN) + : ""; + } + SCOPE const char* + rde_param_query_cc (RDE_PARAM p, long int* len) + { + *len = p->CC_len; + return p->CC; + } + SCOPE int + rde_param_query_cl (RDE_PARAM p) + { + return p->CL; + } + SCOPE const ERROR_STATE* + rde_param_query_er (RDE_PARAM p) + { + return p->ER; + } + SCOPE Tcl_Obj* + rde_param_query_er_tcl (RDE_PARAM p, const ERROR_STATE* er) + { + Tcl_Obj* res; + if (!er) { + + res = Tcl_NewStringObj ("", 0); + } else { + Tcl_Obj* ov [2]; + Tcl_Obj** mov; + long int mc, i, j; + long int* mv; + int lastid; + const char* msg; + rde_stack_get (er->msg, &mc, (void***) &mv); + + qsort (mv, mc, sizeof (long int), er_int_compare); + + mov = NALLOC (mc, Tcl_Obj*); + lastid = -1; + for (i=0, j=0; i < mc; i++) { + ASSERT_BOUNDS (i,mc); + if (mv [i] == lastid) continue; + lastid = mv [i]; + ASSERT_BOUNDS(mv[i],p->numstr); + msg = p->string [mv[i]]; + ASSERT_BOUNDS (j,mc); + mov [j] = Tcl_NewStringObj (msg, -1); + j++; + } + + ov [0] = Tcl_NewIntObj (er->loc); + ov [1] = Tcl_NewListObj (j, mov); + res = Tcl_NewListObj (2, ov); + ckfree ((char*) mov); + } + return res; + } + SCOPE void + rde_param_query_es (RDE_PARAM p, long int* ec, ERROR_STATE*** ev) + { + rde_stack_get (p->ES, ec, (void***) ev); + } + SCOPE void + rde_param_query_ls (RDE_PARAM p, long int* lc, void*** lv) + { + rde_stack_get (p->LS, lc, lv); + } + SCOPE long int + rde_param_query_lstop (RDE_PARAM p) + { + (long int) rde_stack_top (p->LS); + } + SCOPE Tcl_HashTable* + rde_param_query_nc (RDE_PARAM p) + { + return &p->NC; + } + SCOPE int + rde_param_query_st (RDE_PARAM p) + { + return p->ST; + } + SCOPE Tcl_Obj* + rde_param_query_sv (RDE_PARAM p) + { + TRACE (("SV_QUERY %p => (%p)", (p), (p)->SV)); \ + return p->SV; + } + SCOPE long int + rde_param_query_tc_size (RDE_PARAM p) + { + return rde_tc_size (p->TC); + } + SCOPE void + rde_param_query_tc_get_s (RDE_PARAM p, long int at, long int last, char** ch, long int* len) + { + rde_tc_get_s (p->TC, at, last, ch, len); + } + SCOPE const char* + rde_param_query_string (RDE_PARAM p, long int id) + { + TRACE (("rde_param_query_string (RDE_PARAM %p, %d/%d)", p, id, p->numstr)); + ASSERT_BOUNDS(id,p->numstr); + return p->string [id]; + } + SCOPE void + rde_param_i_ast_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->mark, 1); + } + SCOPE void + rde_param_i_ast_pop_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_pop_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_push (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_ast_value_push (RDE_PARAM p) + { + ENTER ("rde_param_i_ast_value_push"); + TRACE (("RDE_PARAM %p",p)); + ASSERT(p->SV,"Unable to push undefined semantic value"); + TRACE (("rde_param_i_ast_value_push %p => (%p)", p, p->SV)); + TRACE (("SV = (%p rc%d '%s')", p->SV, p->SV->refCount, Tcl_GetString (p->SV))); + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + RETURNVOID; + } + static void + ast_node_free (void* n) + { + Tcl_DecrRefCount ((Tcl_Obj*) n); + } + SCOPE void + rde_param_i_error_clear (RDE_PARAM p) + { + ER_CLEAR (p); + } + SCOPE void + rde_param_i_error_nonterminal (RDE_PARAM p, int s) + { + + return; + long int pos; + if (!p->ER) return; + pos = 1 + (long int) rde_stack_top (p->LS); + if (p->ER->loc != pos) return; + error_set (p, s); + p->ER->loc = pos; + } + SCOPE void + rde_param_i_error_pop_merge (RDE_PARAM p) + { + ERROR_STATE* top = (ERROR_STATE*) rde_stack_top (p->ES); + + if (top == p->ER) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!top) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!p->ER) { + rde_stack_drop (p->ES, 1); + p->ER = top; + + return; + } + + if (top->loc < p->ER->loc) { + rde_stack_pop (p->ES, 1); + return; + } + + if (top->loc > p->ER->loc) { + rde_stack_drop (p->ES, 1); + error_state_free (p->ER); + p->ER = top; + + return; + } + + rde_stack_move (p->ER->msg, top->msg); + rde_stack_pop (p->ES, 1); + } + SCOPE void + rde_param_i_error_push (RDE_PARAM p) + { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + static void + error_set (RDE_PARAM p, int s) + { + error_state_free (p->ER); + p->ER = ALLOC (ERROR_STATE); + p->ER->refCount = 1; + p->ER->loc = p->CL; + p->ER->msg = rde_stack_new (NULL); + ASSERT_BOUNDS(s,p->numstr); + rde_stack_push (p->ER->msg, (void*) s); + } + static void + error_state_free (void* esx) + { + ERROR_STATE* es = esx; + if (!es) return; + es->refCount --; + if (es->refCount > 0) return; + rde_stack_del (es->msg); + ckfree ((char*) es); + } + SCOPE void + rde_param_i_loc_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_pop_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_push (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + } + SCOPE void + rde_param_i_loc_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + } + SCOPE void + rde_param_i_input_next (RDE_PARAM p, int m) + { + int leni; + char* ch; + ASSERT_BOUNDS(m,p->numstr); + p->CL ++; + if (p->CL < rde_tc_size (p->TC)) { + + rde_tc_get (p->TC, p->CL, &p->CC, &p->CC_len); + ASSERT_BOUNDS (p->CC_len, TCL_UTF_MAX); + p->ST = 1; + ER_CLEAR (p); + return; + } + if (!p->IN || + Tcl_Eof (p->IN) || + (Tcl_ReadChars (p->IN, p->readbuf, 1, 0) <= 0)) { + + p->ST = 0; + error_set (p, m); + return; + } + + ch = Tcl_GetStringFromObj (p->readbuf, &leni); + ASSERT_BOUNDS (leni, TCL_UTF_MAX); + p->CC = rde_tc_append (p->TC, ch, leni); + p->CC_len = leni; + p->ST = 1; + ER_CLEAR (p); + } + SCOPE void + rde_param_i_status_fail (RDE_PARAM p) + { + p->ST = 0; + } + SCOPE void + rde_param_i_status_ok (RDE_PARAM p) + { + p->ST = 1; + } + SCOPE void + rde_param_i_status_negate (RDE_PARAM p) + { + p->ST = !p->ST; + } + SCOPE int + rde_param_i_symbol_restore (RDE_PARAM p, int s) + { + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + + hPtr = Tcl_FindHashEntry (&p->NC, (char*) p->CL); + if (!hPtr) { return 0; } + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + hPtr = Tcl_FindHashEntry (tablePtr, (char*) s); + if (!hPtr) { return 0; } + + scs = Tcl_GetHashValue (hPtr); + p->CL = scs->CL; + p->ST = scs->ST; + error_state_free (p->ER); + p->ER = scs->ER; + if (p->ER) { p->ER->refCount ++; } + TRACE (("SV_RESTORE (%p) '%s'",scs->SV, scs->SV ? Tcl_GetString (scs->SV):"")); + SV_SET (p, scs->SV); + return 1; + } + SCOPE void + rde_param_i_symbol_save (RDE_PARAM p, int s) + { + long int at = (long int) rde_stack_top (p->LS); + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + int isnew; + ENTER ("rde_param_i_symbol_save"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("INT %d",s)); + + hPtr = Tcl_CreateHashEntry (&p->NC, (char*) at, &isnew); + if (isnew) { + tablePtr = ALLOC (Tcl_HashTable); + Tcl_InitHashTable (tablePtr, TCL_ONE_WORD_KEYS); + Tcl_SetHashValue (hPtr, tablePtr); + } else { + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + } + hPtr = Tcl_CreateHashEntry (tablePtr, (char*) s, &isnew); + if (isnew) { + + scs = ALLOC (NC_STATE); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "")); + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + Tcl_SetHashValue (hPtr, scs); + } else { + + scs = (NC_STATE*) Tcl_GetHashValue (hPtr); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE/over (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "" )); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + error_state_free (scs->ER); + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + } + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_test_alnum (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlnum, tc_alnum); + } + SCOPE void + rde_param_i_test_alpha (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlpha, tc_alpha); + } + SCOPE void + rde_param_i_test_ascii (RDE_PARAM p) + { + test_class (p, UniCharIsAscii, tc_ascii); + } + SCOPE void + rde_param_i_test_control (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsControl, tc_control); + } + SCOPE void + rde_param_i_test_char (RDE_PARAM p, const char* c, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = Tcl_UtfNcmp (p->CC, c, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_ddigit (RDE_PARAM p) + { + test_class (p, UniCharIsDecDigit, tc_ddigit); + } + SCOPE void + rde_param_i_test_digit (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsDigit, tc_digit); + } + SCOPE void + rde_param_i_test_graph (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsGraph, tc_graph); + } + SCOPE void + rde_param_i_test_lower (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsLower, tc_lower); + } + SCOPE void + rde_param_i_test_print (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPrint, tc_printable); + } + SCOPE void + rde_param_i_test_punct (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPunct, tc_punct); + } + SCOPE void + rde_param_i_test_range (RDE_PARAM p, char* s, char* e, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = + (Tcl_UtfNcmp (s, p->CC, 1) <= 0) && + (Tcl_UtfNcmp (p->CC, e, 1) <= 0); + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_space (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsSpace, tc_space); + } + SCOPE void + rde_param_i_test_upper (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsUpper, tc_upper); + } + SCOPE void + rde_param_i_test_wordchar (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsWordChar, tc_wordchar); + } + SCOPE void + rde_param_i_test_xdigit (RDE_PARAM p) + { + test_class (p, UniCharIsHexDigit, tc_xdigit); + } + static void + test_class (RDE_PARAM p, UniCharClass class, test_class_id id) + { + Tcl_UniChar ch; + Tcl_UtfToUniChar(p->CC, &ch); + ASSERT_BOUNDS(id,p->numstr); + p->ST = !!class (ch); + + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, id); + p->CL --; + } + } + static int + UniCharIsAscii (int character) + { + return (character >= 0) && (character < 0x80); + } + static int + UniCharIsHexDigit (int character) + { + return (character >= 0) && (character < 0x80) && isxdigit(character); + } + static int + UniCharIsDecDigit (int character) + { + return (character >= 0) && (character < 0x80) && isdigit(character); + } + SCOPE void + rde_param_i_value_clear (RDE_PARAM p) + { + SV_CLEAR (p); + } + SCOPE void + rde_param_i_value_leaf (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + Tcl_Obj* ov [3]; + long int pos = 1 + (long int) rde_stack_top (p->LS); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + newsv = Tcl_NewListObj (3, ov); + TRACE (("rde_param_i_value_leaf => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + } + SCOPE void + rde_param_i_value_reduce (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + int oc, i, j; + Tcl_Obj** ov; + long int ac; + Tcl_Obj** av; + long int pos = 1 + (long int) rde_stack_top (p->LS); + long int mark = (long int) rde_stack_top (p->mark); + long int asize = rde_stack_size (p->ast); + long int new = asize - mark; + ASSERT (new >= 0, "Bad number of elements to reduce"); + ov = NALLOC (3+new, Tcl_Obj*); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + rde_stack_get (p->ast, &ac, (void***) &av); + for (i = 3, j = mark; j < asize; i++, j++) { + ASSERT_BOUNDS (i, 3+new); + ASSERT_BOUNDS (j, ac); + ov [i] = av [j]; + } + ASSERT (i == 3+new, "Reduction result incomplete"); + newsv = Tcl_NewListObj (3+new, ov); + TRACE (("rde_param_i_value_reduce => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + ckfree ((char*) ov); + } + static int + er_int_compare (const void* a, const void* b) + { + long int ai = *((long int*) a); + long int bi = *((long int*) b); + if (ai < bi) { return -1; } + if (ai > bi) { return 1; } + return 0; + } + SCOPE int + rde_param_i_symbol_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE void + rde_param_i_symbol_done_d_reduce (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_reduce (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_d_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_symbol_done_d_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_next_char (RDE_PARAM p, char* c, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_char (p, c, m); + } + SCOPE void + rde_param_i_next_range (RDE_PARAM p, char* s, char* e, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_range (p, s, e, m); + } + SCOPE void + rde_param_i_next_alnum (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alnum (p); + } + SCOPE void + rde_param_i_next_alpha (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alpha (p); + } + SCOPE void + rde_param_i_next_ascii (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ascii (p); + } + SCOPE void + rde_param_i_next_control (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_control (p); + } + SCOPE void + rde_param_i_next_ddigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ddigit (p); + } + SCOPE void + rde_param_i_next_digit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_digit (p); + } + SCOPE void + rde_param_i_next_graph (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_graph (p); + } + SCOPE void + rde_param_i_next_lower (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_lower (p); + } + SCOPE void + rde_param_i_next_print (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_print (p); + } + SCOPE void + rde_param_i_next_punct (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_punct (p); + } + SCOPE void + rde_param_i_next_space (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_space (p); + } + SCOPE void + rde_param_i_next_upper (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_upper (p); + } + SCOPE void + rde_param_i_next_wordchar (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_wordchar (p); + } + SCOPE void + rde_param_i_next_xdigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_xdigit (p); + } + SCOPE void + rde_param_i_notahead_start_d (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_notahead_exit_d (RDE_PARAM p) + { + if (p->ST) { + rde_param_i_ast_pop_rewind (p); + } else { + rde_stack_pop (p->mark, 1); + } + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_notahead_exit (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_state_push_2 (RDE_PARAM p) + { + + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + SCOPE void + rde_param_i_state_push_void (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_push_value (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_merge_ok (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } + SCOPE int + rde_param_i_kleene_close (RDE_PARAM p) + { + int stop = !p->ST; + rde_param_i_error_pop_merge (p); + if (stop) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_kleene_abort (RDE_PARAM p) + { + int stop = !p->ST; + if (stop) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_seq_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_bra_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE void + rde_param_i_next_str (RDE_PARAM p, const char* str, int m) + { + int at = p->CL; + + while (*str) { + rde_param_i_input_next (p, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + rde_param_i_test_char (p, str, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + str = Tcl_UtfNext (str); + } + } + SCOPE void + rde_param_i_next_class (RDE_PARAM p, const char* class, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + while (*class) { + p->ST = Tcl_UtfNcmp (p->CC, class, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + return; + } + class = Tcl_UtfNext (class); + } + error_set (p, m); + p->CL --; + } + + + /* + * Declaring the parse functions + */ + + static void sym_AddOp (RDE_PARAM p); + static void sym_Digit (RDE_PARAM p); + static void sequence_9 (RDE_PARAM p); + static void sequence_14 (RDE_PARAM p); + static void kleene_16 (RDE_PARAM p); + static void sequence_18 (RDE_PARAM p); + static void choice_20 (RDE_PARAM p); + static void sym_Expression (RDE_PARAM p); + static void sequence_26 (RDE_PARAM p); + static void kleene_28 (RDE_PARAM p); + static void sequence_30 (RDE_PARAM p); + static void sym_Factor (RDE_PARAM p); + static void sym_MulOp (RDE_PARAM p); + static void optional_36 (RDE_PARAM p); + static void poskleene_39 (RDE_PARAM p); + static void sequence_41 (RDE_PARAM p); + static void sym_Number (RDE_PARAM p); + static void sym_Sign (RDE_PARAM p); + static void sym_Term (RDE_PARAM p); + + /* + * Precomputed table of strings (symbols, error messages, etc.). + */ + + static char const* p_string [35] = { + /* 0 = */ "alnum", + /* 1 = */ "alpha", + /* 2 = */ "ascii", + /* 3 = */ "control", + /* 4 = */ "ddigit", + /* 5 = */ "digit", + /* 6 = */ "graph", + /* 7 = */ "lower", + /* 8 = */ "print", + /* 9 = */ "punct", + /* 10 = */ "space", + /* 11 = */ "upper", + /* 12 = */ "wordchar", + /* 13 = */ "xdigit", + /* 14 = */ "cl -+", + /* 15 = */ "n AddOp", + /* 16 = */ "AddOp", + /* 17 = */ "cl 0123456789", + /* 18 = */ "n Digit", + /* 19 = */ "Digit", + /* 20 = */ "t \50", + /* 21 = */ "t \51", + /* 22 = */ "n Expression", + /* 23 = */ "Expression", + /* 24 = */ "n Factor", + /* 25 = */ "Factor", + /* 26 = */ "cl */", + /* 27 = */ "n MulOp", + /* 28 = */ "MulOp", + /* 29 = */ "n Number", + /* 30 = */ "Number", + /* 31 = */ "n Sign", + /* 32 = */ "Sign", + /* 33 = */ "n Term", + /* 34 = */ "Term" + }; + + /* + * Grammar Start Expression + */ + + static void MAIN (RDE_PARAM p) { + sym_Expression (p); + return; + } + + /* + * value Symbol 'AddOp' + */ + + static void sym_AddOp (RDE_PARAM p) { + /* + * [-+] + */ + + if (rde_param_i_symbol_start (p, 16)) return ; + rde_param_i_next_class (p, "-+", 14); + rde_param_i_symbol_done_leaf (p, 16, 15); + return; + } + + /* + * value Symbol 'Digit' + */ + + static void sym_Digit (RDE_PARAM p) { + /* + * [0123456789] + */ + + if (rde_param_i_symbol_start (p, 19)) return ; + rde_param_i_next_class (p, "0123456789", 17); + rde_param_i_symbol_done_leaf (p, 19, 18); + return; + } + + /* + * value Symbol 'Expression' + */ + + static void sym_Expression (RDE_PARAM p) { + /* + * / + * x + * '\(' + * (Expression) + * '\)' + * x + * (Factor) + * * + * x + * (MulOp) + * (Factor) + */ + + if (rde_param_i_symbol_start_d (p, 23)) return ; + choice_20 (p); + rde_param_i_symbol_done_d_reduce (p, 23, 22); + return; + } + + static void choice_20 (RDE_PARAM p) { + /* + * / + * x + * '\(' + * (Expression) + * '\)' + * x + * (Factor) + * * + * x + * (MulOp) + * (Factor) + */ + + rde_param_i_state_push_value (p); + sequence_9 (p); + if (rde_param_i_bra_value2value(p)) return; + sequence_18 (p); + rde_param_i_state_merge_value (p); + return; + } + + static void sequence_9 (RDE_PARAM p) { + /* + * x + * '\(' + * (Expression) + * '\)' + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "\50", 20); + if (rde_param_i_seq_void2value(p)) return; + sym_Expression (p); + if (rde_param_i_seq_value2value(p)) return; + rde_param_i_next_char (p, "\51", 21); + rde_param_i_state_merge_value (p); + return; + } + + static void sequence_18 (RDE_PARAM p) { + /* + * x + * (Factor) + * * + * x + * (MulOp) + * (Factor) + */ + + rde_param_i_state_push_value (p); + sym_Factor (p); + if (rde_param_i_seq_value2value(p)) return; + kleene_16 (p); + rde_param_i_state_merge_value (p); + return; + } + + static void kleene_16 (RDE_PARAM p) { + /* + * * + * x + * (MulOp) + * (Factor) + */ + + while (1) { + rde_param_i_state_push_2 (p); + sequence_14 (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + static void sequence_14 (RDE_PARAM p) { + /* + * x + * (MulOp) + * (Factor) + */ + + rde_param_i_state_push_value (p); + sym_MulOp (p); + if (rde_param_i_seq_value2value(p)) return; + sym_Factor (p); + rde_param_i_state_merge_value (p); + return; + } + + /* + * value Symbol 'Factor' + */ + + static void sym_Factor (RDE_PARAM p) { + /* + * x + * (Term) + * * + * x + * (AddOp) + * (Term) + */ + + if (rde_param_i_symbol_start_d (p, 25)) return ; + sequence_30 (p); + rde_param_i_symbol_done_d_reduce (p, 25, 24); + return; + } + + static void sequence_30 (RDE_PARAM p) { + /* + * x + * (Term) + * * + * x + * (AddOp) + * (Term) + */ + + rde_param_i_state_push_value (p); + sym_Term (p); + if (rde_param_i_seq_value2value(p)) return; + kleene_28 (p); + rde_param_i_state_merge_value (p); + return; + } + + static void kleene_28 (RDE_PARAM p) { + /* + * * + * x + * (AddOp) + * (Term) + */ + + while (1) { + rde_param_i_state_push_2 (p); + sequence_26 (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + static void sequence_26 (RDE_PARAM p) { + /* + * x + * (AddOp) + * (Term) + */ + + rde_param_i_state_push_value (p); + sym_AddOp (p); + if (rde_param_i_seq_value2value(p)) return; + sym_Term (p); + rde_param_i_state_merge_value (p); + return; + } + + /* + * value Symbol 'MulOp' + */ + + static void sym_MulOp (RDE_PARAM p) { + /* + * [\u002a\u002f] + */ + + if (rde_param_i_symbol_start (p, 28)) return ; + rde_param_i_next_class (p, "*/", 26); + rde_param_i_symbol_done_leaf (p, 28, 27); + return; + } + + /* + * value Symbol 'Number' + */ + + static void sym_Number (RDE_PARAM p) { + /* + * x + * ? + * (Sign) + * + + * (Digit) + */ + + if (rde_param_i_symbol_start_d (p, 30)) return ; + sequence_41 (p); + rde_param_i_symbol_done_d_reduce (p, 30, 29); + return; + } + + static void sequence_41 (RDE_PARAM p) { + /* + * x + * ? + * (Sign) + * + + * (Digit) + */ + + rde_param_i_state_push_value (p); + optional_36 (p); + if (rde_param_i_seq_value2value(p)) return; + poskleene_39 (p); + rde_param_i_state_merge_value (p); + return; + } + + static void optional_36 (RDE_PARAM p) { + /* + * ? + * (Sign) + */ + + rde_param_i_state_push_2 (p); + sym_Sign (p); + rde_param_i_state_merge_ok (p); + return; + } + + static void poskleene_39 (RDE_PARAM p) { + /* + * + + * (Digit) + */ + + rde_param_i_loc_push (p); + sym_Digit (p); + if (rde_param_i_kleene_abort(p)) return; + while (1) { + rde_param_i_state_push_2 (p); + sym_Digit (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + /* + * value Symbol 'Sign' + */ + + static void sym_Sign (RDE_PARAM p) { + /* + * [-+] + */ + + if (rde_param_i_symbol_start (p, 32)) return ; + rde_param_i_next_class (p, "-+", 14); + rde_param_i_symbol_done_leaf (p, 32, 31); + return; + } + + /* + * value Symbol 'Term' + */ + + static void sym_Term (RDE_PARAM p) { + /* + * (Number) + */ + + if (rde_param_i_symbol_start_d (p, 34)) return ; + sym_Number (p); + rde_param_i_symbol_done_d_reduce (p, 34, 33); + return; + } + + /* -*- c -*- */ + + typedef struct PARSERg { + long int counter; + char buf [50]; + } PARSERg; + + static void + PARSERgRelease (ClientData cd, Tcl_Interp* interp) + { + ckfree((char*) cd); + } + + static const char* + PARSERnewName (Tcl_Interp* interp) + { +#define KEY "tcllib/parser/PACKAGE/TEA" + + Tcl_InterpDeleteProc* proc = PARSERgRelease; + PARSERg* parserg; + + parserg = Tcl_GetAssocData (interp, KEY, &proc); + if (parserg == NULL) { + parserg = (PARSERg*) ckalloc (sizeof (PARSERg)); + parserg->counter = 0; + + Tcl_SetAssocData (interp, KEY, proc, + (ClientData) parserg); + } + + parserg->counter ++; + sprintf (parserg->buf, "PARSER%d", parserg->counter); + return parserg->buf; +#undef KEY + } + + static void + PARSERdeleteCmd (ClientData clientData) + { + /* + * Release the whole PARSER + * (Low-level engine only actually). + */ + rde_param_del ((RDE_PARAM) clientData); + } + + + /* * ** *** ***** ******** ************* + ** Functions implementing the object methods, and helper. + */ + + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp); + + static int parser_PARSE (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + int mode; + Tcl_Channel chan; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "chan"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, + Tcl_GetString (objv[2]), + &mode); + + if (!chan) { + return TCL_ERROR; + } + + rde_param_reset (p, chan); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + static int parser_PARSET (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + char* buf; + int len; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "text"); + return TCL_ERROR; + } + + buf = Tcl_GetStringFromObj (objv[2], &len); + + rde_param_reset (p, NULL); + rde_param_data (p, buf, len); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + /* See also rde_critcl/m.c, param_COMPLETE() */ + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp) + { + if (rde_param_query_st (p)) { + long int ac; + Tcl_Obj** av; + + rde_param_query_ast (p, &ac, &av); + + if (ac > 1) { + Tcl_Obj** lv = NALLOC (3+ac, Tcl_Obj*); + + memcpy(lv + 3, av, ac * sizeof (Tcl_Obj*)); + lv [0] = Tcl_NewObj (); + lv [1] = Tcl_NewIntObj (1 + rde_param_query_lstop (p)); + lv [2] = Tcl_NewIntObj (rde_param_query_cl (p)); + + Tcl_SetObjResult (interp, Tcl_NewListObj (3, lv)); + ckfree ((char*) lv); + + } else if (ac == 0) { + /* + * Match, but no AST. This is possible if the grammar + * consists of only the start expression. + */ + Tcl_SetObjResult (interp, Tcl_NewStringObj ("",-1)); + } else { + Tcl_SetObjResult (interp, av [0]); + } + + return TCL_OK; + } else { + Tcl_Obj* xv [1]; + const ERROR_STATE* er = rde_param_query_er (p); + Tcl_Obj* res = rde_param_query_er_tcl (p, er); + /* res = list (location, list(msg)) */ + + /* Stick the exception type-tag before the existing elements */ + xv [0] = Tcl_NewStringObj ("pt::rde",-1); + Tcl_ListObjReplace(interp, res, 0, 0, 1, xv); + + Tcl_SetErrorCode (interp, "PT", "RDE", "SYNTAX", NULL); + Tcl_SetObjResult (interp, res); + return TCL_ERROR; + } + } + + + /* * ** *** ***** ******** ************* + ** Object command, method dispatch. + */ + static int parser_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + RDE_PARAM p = (RDE_PARAM) cd; + int m, res; + + static CONST char* methods [] = { + "destroy", "parse", "parset", NULL + }; + enum methods { + M_DESTROY, M_PARSE, M_PARSET + }; + + if (objc < 2) { + Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option", + 0, &m) != TCL_OK) { + return TCL_ERROR; + } + + /* Dispatch to methods. They check the #args in + * detail before performing the requested + * functionality + */ + + switch (m) { + case M_DESTROY: + if (objc != 2) { + Tcl_WrongNumArgs (interp, 2, objv, NULL); + return TCL_ERROR; + } + + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) rde_param_query_clientdata (p)); + return TCL_OK; + + case M_PARSE: res = parser_PARSE (p, interp, objc, objv); break; + case M_PARSET: res = parser_PARSET (p, interp, objc, objv); break; + default: + /* Not coming to this place */ + ASSERT (0,"Reached unreachable location"); + } + + return res; + } + + /** * ** *** ***** ******** ************* + * Class command, i.e. object construction. + */ + static int ParserClassCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const*objv) { + /* + * Syntax: No arguments beyond the name + */ + + RDE_PARAM parser; + CONST char* name; + Tcl_Obj* fqn; + Tcl_CmdInfo ci; + Tcl_Command c; + +#define USAGE "?name?" + + if ((objc != 2) && (objc != 1)) { + Tcl_WrongNumArgs (interp, 1, objv, USAGE); + return TCL_ERROR; + } + + if (objc < 2) { + name = PARSERnewName (interp); + } else { + name = Tcl_GetString (objv [1]); + } + + if (!Tcl_StringMatch (name, "::*")) { + /* Relative name. Prefix with current namespace */ + + Tcl_Eval (interp, "namespace current"); + fqn = Tcl_GetObjResult (interp); + fqn = Tcl_DuplicateObj (fqn); + Tcl_IncrRefCount (fqn); + + if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { + Tcl_AppendToObj (fqn, "::", -1); + } + Tcl_AppendToObj (fqn, name, -1); + } else { + fqn = Tcl_NewStringObj (name, -1); + Tcl_IncrRefCount (fqn); + } + Tcl_ResetResult (interp); + + if (Tcl_GetCommandInfo (interp, + Tcl_GetString (fqn), + &ci)) { + Tcl_Obj* err; + + err = Tcl_NewObj (); + Tcl_AppendToObj (err, "command \"", -1); + Tcl_AppendObjToObj (err, fqn); + Tcl_AppendToObj (err, "\" already exists", -1); + + Tcl_DecrRefCount (fqn); + Tcl_SetObjResult (interp, err); + return TCL_ERROR; + } + + parser = rde_param_new (sizeof(p_string)/sizeof(char*), (char**) p_string); + c = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), + parser_objcmd, (ClientData) parser, + PARSERdeleteCmd); + rde_param_clientdata (parser, (ClientData) c); + Tcl_SetObjResult (interp, fqn); + Tcl_DecrRefCount (fqn); + return TCL_OK; + } + +int Package_Init(Tcl_Interp* interp) { + if (interp == 0) return TCL_ERROR; + + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + + if (Tcl_CreateObjCommand(interp, "PARSER", ParserClassCmd , NULL, NULL) == NULL) { + Tcl_SetResult(interp, "Can't create constructor", NULL); + return TCL_ERROR; + } + + + Tcl_PkgProvide(interp, "PACKAGE", "0.1"); + + return TCL_OK; +} ADDED modules/pt/tests/data/ok/peg_cparam-tea/10_notahead Index: modules/pt/tests/data/ok/peg_cparam-tea/10_notahead ================================================================== --- /dev/null +++ modules/pt/tests/data/ok/peg_cparam-tea/10_notahead @@ -0,0 +1,2034 @@ +/************************************************************ +** +** TEA-based C/PARAM implementation of the parsing +** expression grammar +** +** TEMPLATE +** +** Generated from file TEST +** for user unknown +** +* * ** *** ***** ******** ************* *********************/ + #include + #include + #include + #include + #define SCOPE static + +#line 1 "rde_critcl/util.h" + + #ifndef _RDE_UTIL_H + #define _RDE_UTIL_H 1 + #ifndef SCOPE + #define SCOPE + #endif + #define ALLOC(type) (type *) ckalloc (sizeof (type)) + #define NALLOC(n,type) (type *) ckalloc ((n) * sizeof (type)) + #undef RDE_DEBUG + #define RDE_DEBUG 1 + #undef RDE_TRACE + #ifdef RDE_DEBUG + #define STOPAFTER(x) { static int count = (x); count --; if (!count) { Tcl_Panic ("stop"); } } + #define XSTR(x) #x + #define STR(x) XSTR(x) + #define RANGEOK(i,n) ((0 <= (i)) && (i < (n))) + #define ASSERT(x,msg) if (!(x)) { Tcl_Panic (msg " (" #x "), in file " __FILE__ " @line " STR(__LINE__));} + #define ASSERT_BOUNDS(i,n) ASSERT (RANGEOK(i,n),"array index out of bounds: " STR(i) " >= " STR(n)) + #else + #define STOPAFTER(x) + #define ASSERT(x,msg) + #define ASSERT_BOUNDS(i,n) + #endif + #ifdef RDE_TRACE + SCOPE void trace_enter (const char* fun); + SCOPE void trace_return (const char *pat, ...); + SCOPE void trace_printf (const char *pat, ...); + #define ENTER(fun) trace_enter (fun) + #define RETURN(format,x) trace_return (format,x) ; return x + #define RETURNVOID trace_return ("%s","(void)") ; return + #define TRACE0(x) trace_printf0 x + #define TRACE(x) trace_printf x + #else + #define ENTER(fun) + #define RETURN(f,x) return x + #define RETURNVOID return + #define TRACE0(x) + #define TRACE(x) + #endif + #endif + + +#line 1 "rde_critcl/stack.h" + + #ifndef _RDE_DS_STACK_H + #define _RDE_DS_STACK_H 1 + typedef void (*RDE_STACK_CELL_FREE) (void* cell); + typedef struct RDE_STACK_* RDE_STACK; + static const int RDE_STACK_INITIAL_SIZE = 256; + #endif + + +#line 1 "rde_critcl/tc.h" + + #ifndef _RDE_DS_TC_H + #define _RDE_DS_TC_H 1 + typedef struct RDE_TC_* RDE_TC; + #endif + + +#line 1 "rde_critcl/param.h" + + #ifndef _RDE_DS_PARAM_H + #define _RDE_DS_PARAM_H 1 + typedef struct RDE_PARAM_* RDE_PARAM; + typedef struct ERROR_STATE { + int refCount; + long int loc; + RDE_STACK msg; + } ERROR_STATE; + typedef struct NC_STATE { + long int CL; + long int ST; + Tcl_Obj* SV; + ERROR_STATE* ER; + } NC_STATE; + #endif + + +#line 1 "rde_critcl/util.c" + + #ifdef RDE_TRACE + typedef struct F_STACK { + const char* str; + struct F_STACK* down; + } F_STACK; + static F_STACK* top = 0; + static int level = 0; + static void + push (const char* str) + { + F_STACK* new = ALLOC (F_STACK); + new->str = str; + new->down = top; + top = new; + level += 4; + } + static void + pop (void) + { + F_STACK* next = top->down; + level -= 4; + ckfree ((char*)top); + top = next; + } + static void + indent (void) + { + int i; + for (i = 0; i < level; i++) { + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + if (top) { + fwrite(top->str, 1, strlen(top->str), stdout); + fflush (stdout); + } + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + SCOPE void + trace_enter (const char* fun) + { + push (fun); + indent(); + fwrite("ENTER\n", 1, 6, stdout); + fflush (stdout); + } + static char msg [1024*1024]; + SCOPE void + trace_return (const char *pat, ...) + { + int len; + va_list args; + indent(); + fwrite("RETURN = ", 1, 9, stdout); + fflush (stdout); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + pop(); + } + SCOPE void + trace_printf (const char *pat, ...) + { + int len; + va_list args; + indent(); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + SCOPE void + trace_printf0 (const char *pat, ...) + { + int len; + va_list args; + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + #endif + + +#line 1 "rde_critcl/stack.c" + + typedef struct RDE_STACK_ { + long int max; + long int top; + RDE_STACK_CELL_FREE freeCellProc; + void** cell; + } RDE_STACK_; + + SCOPE RDE_STACK + rde_stack_new (RDE_STACK_CELL_FREE freeCellProc) + { + RDE_STACK s = ALLOC (RDE_STACK_); + s->cell = NALLOC (RDE_STACK_INITIAL_SIZE, void*); + s->max = RDE_STACK_INITIAL_SIZE; + s->top = 0; + s->freeCellProc = freeCellProc; + return s; + } + SCOPE void + rde_stack_del (RDE_STACK s) + { + if (s->freeCellProc && s->top) { + long int i; + for (i=0; i < s->top; i++) { + ASSERT_BOUNDS(i,s->max); + s->freeCellProc ( s->cell [i] ); + } + } + ckfree ((char*) s->cell); + ckfree ((char*) s); + } + SCOPE void + rde_stack_push (RDE_STACK s, void* item) + { + if (s->top >= s->max) { + long int new = s->max ? (2 * s->max) : RDE_STACK_INITIAL_SIZE; + void** cell = (void**) ckrealloc ((char*) s->cell, new * sizeof(void*)); + ASSERT (cell,"Memory allocation failure for RDE stack"); + s->max = new; + s->cell = cell; + } + ASSERT_BOUNDS(s->top,s->max); + s->cell [s->top] = item; + s->top ++; + } + SCOPE void* + rde_stack_top (RDE_STACK s) + { + ASSERT_BOUNDS(s->top-1,s->max); + return s->cell [s->top - 1]; + } + SCOPE void + rde_stack_pop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + if (s->freeCellProc) { + while (n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + n --; + } + } else { + s->top -= n; + } + } + SCOPE void + rde_stack_trim (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad trimsize"); + if (s->freeCellProc) { + while (s->top > n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + } + } else { + s->top = n; + } + } + SCOPE void + rde_stack_drop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + s->top -= n; + } + SCOPE void + rde_stack_move (RDE_STACK dst, RDE_STACK src) + { + ASSERT (dst->freeCellProc == src->freeCellProc, "Ownership mismatch"); + + while (src->top > 0) { + src->top --; + ASSERT_BOUNDS(src->top,src->max); + rde_stack_push (dst, src->cell [src->top] ); + } + } + SCOPE void + rde_stack_get (RDE_STACK s, long int* cn, void*** cc) + { + *cn = s->top; + *cc = s->cell; + } + SCOPE long int + rde_stack_size (RDE_STACK s) + { + return s->top; + } + + +#line 1 "rde_critcl/tc.c" + + typedef struct RDE_TC_ { + int max; + int num; + char* str; + RDE_STACK off; + } RDE_TC_; + + SCOPE RDE_TC + rde_tc_new (void) + { + RDE_TC tc = ALLOC (RDE_TC_); + tc->max = RDE_STACK_INITIAL_SIZE; + tc->num = 0; + tc->str = NALLOC (RDE_STACK_INITIAL_SIZE, char); + tc->off = rde_stack_new (NULL); + return tc; + } + SCOPE void + rde_tc_del (RDE_TC tc) + { + rde_stack_del (tc->off); + ckfree (tc->str); + ckfree ((char*) tc); + } + SCOPE long int + rde_tc_size (RDE_TC tc) + { + return rde_stack_size (tc->off); + } + SCOPE void + rde_tc_clear (RDE_TC tc) + { + tc->num = 0; + rde_stack_trim (tc->off, 0); + } + SCOPE char* + rde_tc_append (RDE_TC tc, char* string, long int len) + { + long int base = tc->num; + long int off = tc->num; + char* ch; + int clen; + Tcl_UniChar uni; + if (len < 0) { + len = strlen (string); + } + + if (!len) { + return tc->str + base; + } + + if ((tc->num + len) >= tc->max) { + int new = len + (tc->max ? (2 * tc->max) : RDE_STACK_INITIAL_SIZE); + char* str = ckrealloc (tc->str, new * sizeof(char)); + ASSERT (str,"Memory allocation failure for token character array"); + tc->max = new; + tc->str = str; + } + tc->num += len; + ASSERT_BOUNDS(tc->num,tc->max); + ASSERT_BOUNDS(off,tc->max); + ASSERT_BOUNDS(off+len-1,tc->max); + ASSERT_BOUNDS(off+len-1,tc->num); + memcpy (tc->str + off, string, len); + + ch = string; + while (ch < (string + len)) { + ASSERT_BOUNDS(off,tc->num); + rde_stack_push (tc->off, (void*) off); + clen = Tcl_UtfToUniChar (ch, &uni); + off += clen; + ch += clen; + } + return tc->str + base; + } + SCOPE void + rde_tc_get (RDE_TC tc, int at, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + off = ov [at]; + if ((at+1) == oc) { + end = tc->num; + } else { + end = ov [at+1]; + } + TRACE (("rde_tc_get (RDE_TC %p, @ %d) => %d.[%d ... %d]/%d",tc,at,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + SCOPE void + rde_tc_get_s (RDE_TC tc, int at, int last, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + ASSERT_BOUNDS(last,oc); + off = ov [at]; + if ((last+1) == oc) { + end = tc->num; + } else { + end = ov [last+1]; + } + TRACE (("rde_tc_get_s (RDE_TC %p, @ %d .. %d) => %d.[%d ... %d]/%d",tc,at,last,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + + +#line 1 "rde_critcl/param.c" + + typedef struct RDE_PARAM_ { + Tcl_Channel IN; + Tcl_Obj* readbuf; + char* CC; + long int CC_len; + RDE_TC TC; + long int CL; + RDE_STACK LS; + ERROR_STATE* ER; + RDE_STACK ES; + long int ST; + Tcl_Obj* SV; + Tcl_HashTable NC; + + RDE_STACK ast ; + RDE_STACK mark ; + + long int numstr; + char** string; + + ClientData clientData; + } RDE_PARAM_; + typedef int (*UniCharClass) (int); + typedef enum test_class_id { + tc_alnum, + tc_alpha, + tc_ascii, + tc_control, + tc_ddigit, + tc_digit, + tc_graph, + tc_lower, + tc_printable, + tc_punct, + tc_space, + tc_upper, + tc_wordchar, + tc_xdigit + } test_class_id; + static void ast_node_free (void* n); + static void error_state_free (void* es); + static void error_set (RDE_PARAM p, int s); + static void nc_clear (RDE_PARAM p); + static int UniCharIsAscii (int character); + static int UniCharIsHexDigit (int character); + static int UniCharIsDecDigit (int character); + static void test_class (RDE_PARAM p, UniCharClass class, test_class_id id); + static int er_int_compare (const void* a, const void* b); + #define SV_INIT(p) \ + p->SV = NULL; \ + TRACE (("SV_INIT (%p => %p)", (p), (p)->SV)) + #define SV_SET(p,newsv) \ + if (((p)->SV) != (newsv)) { \ + TRACE (("SV_CLEAR/set (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = (newsv); \ + TRACE (("SV_SET (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_IncrRefCount ((p)->SV); \ + } \ + } + #define SV_CLEAR(p) \ + TRACE (("SV_CLEAR (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = NULL + #define ER_INIT(p) \ + p->ER = NULL; \ + TRACE (("ER_INIT (%p => %p)", (p), (p)->ER)) + #define ER_CLEAR(p) \ + error_state_free ((p)->ER); \ + (p)->ER = NULL + SCOPE RDE_PARAM + rde_param_new (long int nstr, char** strings) + { + RDE_PARAM p; + ENTER ("rde_param_new"); + TRACE (("\tINT %d strings @ %p", nstr, strings)); + p = ALLOC (RDE_PARAM_); + p->numstr = nstr; + p->string = strings; + p->readbuf = Tcl_NewObj (); + Tcl_IncrRefCount (p->readbuf); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_InitHashTable (&p->NC, TCL_ONE_WORD_KEYS); + p->IN = NULL; + p->CL = -1; + p->ST = 0; + ER_INIT (p); + SV_INIT (p); + p->CC = NULL; + p->CC_len = 0; + p->TC = rde_tc_new (); + p->ES = rde_stack_new (error_state_free); + p->LS = rde_stack_new (NULL); + p->ast = rde_stack_new (ast_node_free); + p->mark = rde_stack_new (NULL); + RETURN ("%p", p); + } + SCOPE void + rde_param_del (RDE_PARAM p) + { + ENTER ("rde_param_del"); + TRACE (("RDE_PARAM %p",p)); + ER_CLEAR (p); TRACE (("\ter_clear")); + SV_CLEAR (p); TRACE (("\tsv_clear")); + nc_clear (p); TRACE (("\tnc_clear")); + Tcl_DeleteHashTable (&p->NC); TRACE (("\tnc hashtable delete")); + rde_tc_del (p->TC); TRACE (("\ttc clear")); + rde_stack_del (p->ES); TRACE (("\tes clear")); + rde_stack_del (p->LS); TRACE (("\tls clear")); + rde_stack_del (p->ast); TRACE (("\tast clear")); + rde_stack_del (p->mark); TRACE (("\tmark clear")); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_DecrRefCount (p->readbuf); + ckfree ((char*) p); + RETURNVOID; + } + SCOPE void + rde_param_reset (RDE_PARAM p, Tcl_Channel chan) + { + ENTER ("rde_param_reset"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("Tcl_Channel %p",chan)); + p->IN = chan; + p->CL = -1; + p->ST = 0; + p->CC = NULL; + p->CC_len = 0; + ER_CLEAR (p); + SV_CLEAR (p); + nc_clear (p); + rde_tc_clear (p->TC); + rde_stack_trim (p->ES, 0); + rde_stack_trim (p->LS, 0); + rde_stack_trim (p->ast, 0); + rde_stack_trim (p->mark, 0); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + RETURNVOID; + } + SCOPE void + rde_param_update_strings (RDE_PARAM p, long int nstr, char** strings) + { + ENTER ("rde_param_update_strings"); + TRACE (("RDE_PARAM %p", p)); + TRACE (("INT %d strings", nstr)); + p->numstr = nstr; + p->string = strings; + RETURNVOID; + } + SCOPE void + rde_param_data (RDE_PARAM p, char* buf, long int len) + { + (void) rde_tc_append (p->TC, buf, len); + } + SCOPE void + rde_param_clientdata (RDE_PARAM p, ClientData clientData) + { + p->clientData = clientData; + } + static void + nc_clear (RDE_PARAM p) + { + Tcl_HashSearch hs; + Tcl_HashEntry* he; + Tcl_HashTable* tablePtr; + for(he = Tcl_FirstHashEntry(&p->NC, &hs); + he != NULL; + he = Tcl_FirstHashEntry(&p->NC, &hs)) { + Tcl_HashSearch hsc; + Tcl_HashEntry* hec; + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (he); + for(hec = Tcl_FirstHashEntry(tablePtr, &hsc); + hec != NULL; + hec = Tcl_NextHashEntry(&hsc)) { + NC_STATE* scs = Tcl_GetHashValue (hec); + error_state_free (scs->ER); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + ckfree ((char*) scs); + } + Tcl_DeleteHashTable (tablePtr); + ckfree ((char*) tablePtr); + Tcl_DeleteHashEntry (he); + } + } + SCOPE ClientData + rde_param_query_clientdata (RDE_PARAM p) + { + return p->clientData; + } + SCOPE void + rde_param_query_amark (RDE_PARAM p, long int* mc, long int** mv) + { + rde_stack_get (p->mark, mc, (void***) mv); + } + SCOPE void + rde_param_query_ast (RDE_PARAM p, long int* ac, Tcl_Obj*** av) + { + rde_stack_get (p->ast, ac, (void***) av); + } + SCOPE const char* + rde_param_query_in (RDE_PARAM p) + { + return p->IN + ? Tcl_GetChannelName (p->IN) + : ""; + } + SCOPE const char* + rde_param_query_cc (RDE_PARAM p, long int* len) + { + *len = p->CC_len; + return p->CC; + } + SCOPE int + rde_param_query_cl (RDE_PARAM p) + { + return p->CL; + } + SCOPE const ERROR_STATE* + rde_param_query_er (RDE_PARAM p) + { + return p->ER; + } + SCOPE Tcl_Obj* + rde_param_query_er_tcl (RDE_PARAM p, const ERROR_STATE* er) + { + Tcl_Obj* res; + if (!er) { + + res = Tcl_NewStringObj ("", 0); + } else { + Tcl_Obj* ov [2]; + Tcl_Obj** mov; + long int mc, i, j; + long int* mv; + int lastid; + const char* msg; + rde_stack_get (er->msg, &mc, (void***) &mv); + + qsort (mv, mc, sizeof (long int), er_int_compare); + + mov = NALLOC (mc, Tcl_Obj*); + lastid = -1; + for (i=0, j=0; i < mc; i++) { + ASSERT_BOUNDS (i,mc); + if (mv [i] == lastid) continue; + lastid = mv [i]; + ASSERT_BOUNDS(mv[i],p->numstr); + msg = p->string [mv[i]]; + ASSERT_BOUNDS (j,mc); + mov [j] = Tcl_NewStringObj (msg, -1); + j++; + } + + ov [0] = Tcl_NewIntObj (er->loc); + ov [1] = Tcl_NewListObj (j, mov); + res = Tcl_NewListObj (2, ov); + ckfree ((char*) mov); + } + return res; + } + SCOPE void + rde_param_query_es (RDE_PARAM p, long int* ec, ERROR_STATE*** ev) + { + rde_stack_get (p->ES, ec, (void***) ev); + } + SCOPE void + rde_param_query_ls (RDE_PARAM p, long int* lc, void*** lv) + { + rde_stack_get (p->LS, lc, lv); + } + SCOPE long int + rde_param_query_lstop (RDE_PARAM p) + { + (long int) rde_stack_top (p->LS); + } + SCOPE Tcl_HashTable* + rde_param_query_nc (RDE_PARAM p) + { + return &p->NC; + } + SCOPE int + rde_param_query_st (RDE_PARAM p) + { + return p->ST; + } + SCOPE Tcl_Obj* + rde_param_query_sv (RDE_PARAM p) + { + TRACE (("SV_QUERY %p => (%p)", (p), (p)->SV)); \ + return p->SV; + } + SCOPE long int + rde_param_query_tc_size (RDE_PARAM p) + { + return rde_tc_size (p->TC); + } + SCOPE void + rde_param_query_tc_get_s (RDE_PARAM p, long int at, long int last, char** ch, long int* len) + { + rde_tc_get_s (p->TC, at, last, ch, len); + } + SCOPE const char* + rde_param_query_string (RDE_PARAM p, long int id) + { + TRACE (("rde_param_query_string (RDE_PARAM %p, %d/%d)", p, id, p->numstr)); + ASSERT_BOUNDS(id,p->numstr); + return p->string [id]; + } + SCOPE void + rde_param_i_ast_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->mark, 1); + } + SCOPE void + rde_param_i_ast_pop_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_pop_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_push (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_ast_value_push (RDE_PARAM p) + { + ENTER ("rde_param_i_ast_value_push"); + TRACE (("RDE_PARAM %p",p)); + ASSERT(p->SV,"Unable to push undefined semantic value"); + TRACE (("rde_param_i_ast_value_push %p => (%p)", p, p->SV)); + TRACE (("SV = (%p rc%d '%s')", p->SV, p->SV->refCount, Tcl_GetString (p->SV))); + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + RETURNVOID; + } + static void + ast_node_free (void* n) + { + Tcl_DecrRefCount ((Tcl_Obj*) n); + } + SCOPE void + rde_param_i_error_clear (RDE_PARAM p) + { + ER_CLEAR (p); + } + SCOPE void + rde_param_i_error_nonterminal (RDE_PARAM p, int s) + { + + return; + long int pos; + if (!p->ER) return; + pos = 1 + (long int) rde_stack_top (p->LS); + if (p->ER->loc != pos) return; + error_set (p, s); + p->ER->loc = pos; + } + SCOPE void + rde_param_i_error_pop_merge (RDE_PARAM p) + { + ERROR_STATE* top = (ERROR_STATE*) rde_stack_top (p->ES); + + if (top == p->ER) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!top) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!p->ER) { + rde_stack_drop (p->ES, 1); + p->ER = top; + + return; + } + + if (top->loc < p->ER->loc) { + rde_stack_pop (p->ES, 1); + return; + } + + if (top->loc > p->ER->loc) { + rde_stack_drop (p->ES, 1); + error_state_free (p->ER); + p->ER = top; + + return; + } + + rde_stack_move (p->ER->msg, top->msg); + rde_stack_pop (p->ES, 1); + } + SCOPE void + rde_param_i_error_push (RDE_PARAM p) + { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + static void + error_set (RDE_PARAM p, int s) + { + error_state_free (p->ER); + p->ER = ALLOC (ERROR_STATE); + p->ER->refCount = 1; + p->ER->loc = p->CL; + p->ER->msg = rde_stack_new (NULL); + ASSERT_BOUNDS(s,p->numstr); + rde_stack_push (p->ER->msg, (void*) s); + } + static void + error_state_free (void* esx) + { + ERROR_STATE* es = esx; + if (!es) return; + es->refCount --; + if (es->refCount > 0) return; + rde_stack_del (es->msg); + ckfree ((char*) es); + } + SCOPE void + rde_param_i_loc_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_pop_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_push (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + } + SCOPE void + rde_param_i_loc_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + } + SCOPE void + rde_param_i_input_next (RDE_PARAM p, int m) + { + int leni; + char* ch; + ASSERT_BOUNDS(m,p->numstr); + p->CL ++; + if (p->CL < rde_tc_size (p->TC)) { + + rde_tc_get (p->TC, p->CL, &p->CC, &p->CC_len); + ASSERT_BOUNDS (p->CC_len, TCL_UTF_MAX); + p->ST = 1; + ER_CLEAR (p); + return; + } + if (!p->IN || + Tcl_Eof (p->IN) || + (Tcl_ReadChars (p->IN, p->readbuf, 1, 0) <= 0)) { + + p->ST = 0; + error_set (p, m); + return; + } + + ch = Tcl_GetStringFromObj (p->readbuf, &leni); + ASSERT_BOUNDS (leni, TCL_UTF_MAX); + p->CC = rde_tc_append (p->TC, ch, leni); + p->CC_len = leni; + p->ST = 1; + ER_CLEAR (p); + } + SCOPE void + rde_param_i_status_fail (RDE_PARAM p) + { + p->ST = 0; + } + SCOPE void + rde_param_i_status_ok (RDE_PARAM p) + { + p->ST = 1; + } + SCOPE void + rde_param_i_status_negate (RDE_PARAM p) + { + p->ST = !p->ST; + } + SCOPE int + rde_param_i_symbol_restore (RDE_PARAM p, int s) + { + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + + hPtr = Tcl_FindHashEntry (&p->NC, (char*) p->CL); + if (!hPtr) { return 0; } + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + hPtr = Tcl_FindHashEntry (tablePtr, (char*) s); + if (!hPtr) { return 0; } + + scs = Tcl_GetHashValue (hPtr); + p->CL = scs->CL; + p->ST = scs->ST; + error_state_free (p->ER); + p->ER = scs->ER; + if (p->ER) { p->ER->refCount ++; } + TRACE (("SV_RESTORE (%p) '%s'",scs->SV, scs->SV ? Tcl_GetString (scs->SV):"")); + SV_SET (p, scs->SV); + return 1; + } + SCOPE void + rde_param_i_symbol_save (RDE_PARAM p, int s) + { + long int at = (long int) rde_stack_top (p->LS); + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + int isnew; + ENTER ("rde_param_i_symbol_save"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("INT %d",s)); + + hPtr = Tcl_CreateHashEntry (&p->NC, (char*) at, &isnew); + if (isnew) { + tablePtr = ALLOC (Tcl_HashTable); + Tcl_InitHashTable (tablePtr, TCL_ONE_WORD_KEYS); + Tcl_SetHashValue (hPtr, tablePtr); + } else { + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + } + hPtr = Tcl_CreateHashEntry (tablePtr, (char*) s, &isnew); + if (isnew) { + + scs = ALLOC (NC_STATE); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "")); + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + Tcl_SetHashValue (hPtr, scs); + } else { + + scs = (NC_STATE*) Tcl_GetHashValue (hPtr); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE/over (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "" )); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + error_state_free (scs->ER); + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + } + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_test_alnum (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlnum, tc_alnum); + } + SCOPE void + rde_param_i_test_alpha (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlpha, tc_alpha); + } + SCOPE void + rde_param_i_test_ascii (RDE_PARAM p) + { + test_class (p, UniCharIsAscii, tc_ascii); + } + SCOPE void + rde_param_i_test_control (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsControl, tc_control); + } + SCOPE void + rde_param_i_test_char (RDE_PARAM p, const char* c, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = Tcl_UtfNcmp (p->CC, c, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_ddigit (RDE_PARAM p) + { + test_class (p, UniCharIsDecDigit, tc_ddigit); + } + SCOPE void + rde_param_i_test_digit (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsDigit, tc_digit); + } + SCOPE void + rde_param_i_test_graph (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsGraph, tc_graph); + } + SCOPE void + rde_param_i_test_lower (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsLower, tc_lower); + } + SCOPE void + rde_param_i_test_print (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPrint, tc_printable); + } + SCOPE void + rde_param_i_test_punct (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPunct, tc_punct); + } + SCOPE void + rde_param_i_test_range (RDE_PARAM p, char* s, char* e, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = + (Tcl_UtfNcmp (s, p->CC, 1) <= 0) && + (Tcl_UtfNcmp (p->CC, e, 1) <= 0); + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_space (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsSpace, tc_space); + } + SCOPE void + rde_param_i_test_upper (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsUpper, tc_upper); + } + SCOPE void + rde_param_i_test_wordchar (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsWordChar, tc_wordchar); + } + SCOPE void + rde_param_i_test_xdigit (RDE_PARAM p) + { + test_class (p, UniCharIsHexDigit, tc_xdigit); + } + static void + test_class (RDE_PARAM p, UniCharClass class, test_class_id id) + { + Tcl_UniChar ch; + Tcl_UtfToUniChar(p->CC, &ch); + ASSERT_BOUNDS(id,p->numstr); + p->ST = !!class (ch); + + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, id); + p->CL --; + } + } + static int + UniCharIsAscii (int character) + { + return (character >= 0) && (character < 0x80); + } + static int + UniCharIsHexDigit (int character) + { + return (character >= 0) && (character < 0x80) && isxdigit(character); + } + static int + UniCharIsDecDigit (int character) + { + return (character >= 0) && (character < 0x80) && isdigit(character); + } + SCOPE void + rde_param_i_value_clear (RDE_PARAM p) + { + SV_CLEAR (p); + } + SCOPE void + rde_param_i_value_leaf (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + Tcl_Obj* ov [3]; + long int pos = 1 + (long int) rde_stack_top (p->LS); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + newsv = Tcl_NewListObj (3, ov); + TRACE (("rde_param_i_value_leaf => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + } + SCOPE void + rde_param_i_value_reduce (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + int oc, i, j; + Tcl_Obj** ov; + long int ac; + Tcl_Obj** av; + long int pos = 1 + (long int) rde_stack_top (p->LS); + long int mark = (long int) rde_stack_top (p->mark); + long int asize = rde_stack_size (p->ast); + long int new = asize - mark; + ASSERT (new >= 0, "Bad number of elements to reduce"); + ov = NALLOC (3+new, Tcl_Obj*); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + rde_stack_get (p->ast, &ac, (void***) &av); + for (i = 3, j = mark; j < asize; i++, j++) { + ASSERT_BOUNDS (i, 3+new); + ASSERT_BOUNDS (j, ac); + ov [i] = av [j]; + } + ASSERT (i == 3+new, "Reduction result incomplete"); + newsv = Tcl_NewListObj (3+new, ov); + TRACE (("rde_param_i_value_reduce => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + ckfree ((char*) ov); + } + static int + er_int_compare (const void* a, const void* b) + { + long int ai = *((long int*) a); + long int bi = *((long int*) b); + if (ai < bi) { return -1; } + if (ai > bi) { return 1; } + return 0; + } + SCOPE int + rde_param_i_symbol_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE void + rde_param_i_symbol_done_d_reduce (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_reduce (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_d_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_symbol_done_d_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_next_char (RDE_PARAM p, char* c, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_char (p, c, m); + } + SCOPE void + rde_param_i_next_range (RDE_PARAM p, char* s, char* e, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_range (p, s, e, m); + } + SCOPE void + rde_param_i_next_alnum (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alnum (p); + } + SCOPE void + rde_param_i_next_alpha (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alpha (p); + } + SCOPE void + rde_param_i_next_ascii (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ascii (p); + } + SCOPE void + rde_param_i_next_control (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_control (p); + } + SCOPE void + rde_param_i_next_ddigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ddigit (p); + } + SCOPE void + rde_param_i_next_digit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_digit (p); + } + SCOPE void + rde_param_i_next_graph (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_graph (p); + } + SCOPE void + rde_param_i_next_lower (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_lower (p); + } + SCOPE void + rde_param_i_next_print (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_print (p); + } + SCOPE void + rde_param_i_next_punct (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_punct (p); + } + SCOPE void + rde_param_i_next_space (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_space (p); + } + SCOPE void + rde_param_i_next_upper (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_upper (p); + } + SCOPE void + rde_param_i_next_wordchar (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_wordchar (p); + } + SCOPE void + rde_param_i_next_xdigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_xdigit (p); + } + SCOPE void + rde_param_i_notahead_start_d (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_notahead_exit_d (RDE_PARAM p) + { + if (p->ST) { + rde_param_i_ast_pop_rewind (p); + } else { + rde_stack_pop (p->mark, 1); + } + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_notahead_exit (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_state_push_2 (RDE_PARAM p) + { + + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + SCOPE void + rde_param_i_state_push_void (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_push_value (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_merge_ok (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } + SCOPE int + rde_param_i_kleene_close (RDE_PARAM p) + { + int stop = !p->ST; + rde_param_i_error_pop_merge (p); + if (stop) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_kleene_abort (RDE_PARAM p) + { + int stop = !p->ST; + if (stop) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_seq_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_bra_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE void + rde_param_i_next_str (RDE_PARAM p, const char* str, int m) + { + int at = p->CL; + + while (*str) { + rde_param_i_input_next (p, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + rde_param_i_test_char (p, str, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + str = Tcl_UtfNext (str); + } + } + SCOPE void + rde_param_i_next_class (RDE_PARAM p, const char* class, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + while (*class) { + p->ST = Tcl_UtfNcmp (p->CC, class, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + return; + } + class = Tcl_UtfNext (class); + } + error_set (p, m); + p->CL --; + } + + + /* + * Declaring the parse functions + */ + + static void notahead_3 (RDE_PARAM p); + static void sequence_6 (RDE_PARAM p); + static void sym_TEST (RDE_PARAM p); + + /* + * Precomputed table of strings (symbols, error messages, etc.). + */ + + static char const* p_string [17] = { + /* 0 = */ "alnum", + /* 1 = */ "alpha", + /* 2 = */ "ascii", + /* 3 = */ "control", + /* 4 = */ "ddigit", + /* 5 = */ "digit", + /* 6 = */ "graph", + /* 7 = */ "lower", + /* 8 = */ "print", + /* 9 = */ "punct", + /* 10 = */ "space", + /* 11 = */ "upper", + /* 12 = */ "wordchar", + /* 13 = */ "xdigit", + /* 14 = */ "t a", + /* 15 = */ "n TEST", + /* 16 = */ "TEST" + }; + + /* + * Grammar Start Expression + */ + + static void MAIN (RDE_PARAM p) { + sym_TEST (p); + return; + } + + /* + * value Symbol 'TEST' + */ + + static void sym_TEST (RDE_PARAM p) { + /* + * x + * ! + * 'a' + * (IDENTIFIER) + */ + + if (rde_param_i_symbol_start (p, 16)) return ; + sequence_6 (p); + rde_param_i_symbol_done_leaf (p, 16, 15); + return; + } + + static void sequence_6 (RDE_PARAM p) { + /* + * x + * ! + * 'a' + * (IDENTIFIER) + */ + + rde_param_i_state_push_void (p); + notahead_3 (p); + if (rde_param_i_seq_void2void(p)) return; + /* Undefined symbol 'IDENTIFIER' */; + rde_param_i_status_fail (p); + rde_param_i_state_merge_void (p); + return; + } + + static void notahead_3 (RDE_PARAM p) { + /* + * ! + * 'a' + */ + + rde_param_i_loc_push (p); + rde_param_i_next_char (p, "a", 14); + rde_param_i_notahead_exit (p); + return; + } + + /* -*- c -*- */ + + typedef struct PARSERg { + long int counter; + char buf [50]; + } PARSERg; + + static void + PARSERgRelease (ClientData cd, Tcl_Interp* interp) + { + ckfree((char*) cd); + } + + static const char* + PARSERnewName (Tcl_Interp* interp) + { +#define KEY "tcllib/parser/PACKAGE/TEA" + + Tcl_InterpDeleteProc* proc = PARSERgRelease; + PARSERg* parserg; + + parserg = Tcl_GetAssocData (interp, KEY, &proc); + if (parserg == NULL) { + parserg = (PARSERg*) ckalloc (sizeof (PARSERg)); + parserg->counter = 0; + + Tcl_SetAssocData (interp, KEY, proc, + (ClientData) parserg); + } + + parserg->counter ++; + sprintf (parserg->buf, "PARSER%d", parserg->counter); + return parserg->buf; +#undef KEY + } + + static void + PARSERdeleteCmd (ClientData clientData) + { + /* + * Release the whole PARSER + * (Low-level engine only actually). + */ + rde_param_del ((RDE_PARAM) clientData); + } + + + /* * ** *** ***** ******** ************* + ** Functions implementing the object methods, and helper. + */ + + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp); + + static int parser_PARSE (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + int mode; + Tcl_Channel chan; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "chan"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, + Tcl_GetString (objv[2]), + &mode); + + if (!chan) { + return TCL_ERROR; + } + + rde_param_reset (p, chan); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + static int parser_PARSET (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + char* buf; + int len; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "text"); + return TCL_ERROR; + } + + buf = Tcl_GetStringFromObj (objv[2], &len); + + rde_param_reset (p, NULL); + rde_param_data (p, buf, len); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + /* See also rde_critcl/m.c, param_COMPLETE() */ + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp) + { + if (rde_param_query_st (p)) { + long int ac; + Tcl_Obj** av; + + rde_param_query_ast (p, &ac, &av); + + if (ac > 1) { + Tcl_Obj** lv = NALLOC (3+ac, Tcl_Obj*); + + memcpy(lv + 3, av, ac * sizeof (Tcl_Obj*)); + lv [0] = Tcl_NewObj (); + lv [1] = Tcl_NewIntObj (1 + rde_param_query_lstop (p)); + lv [2] = Tcl_NewIntObj (rde_param_query_cl (p)); + + Tcl_SetObjResult (interp, Tcl_NewListObj (3, lv)); + ckfree ((char*) lv); + + } else if (ac == 0) { + /* + * Match, but no AST. This is possible if the grammar + * consists of only the start expression. + */ + Tcl_SetObjResult (interp, Tcl_NewStringObj ("",-1)); + } else { + Tcl_SetObjResult (interp, av [0]); + } + + return TCL_OK; + } else { + Tcl_Obj* xv [1]; + const ERROR_STATE* er = rde_param_query_er (p); + Tcl_Obj* res = rde_param_query_er_tcl (p, er); + /* res = list (location, list(msg)) */ + + /* Stick the exception type-tag before the existing elements */ + xv [0] = Tcl_NewStringObj ("pt::rde",-1); + Tcl_ListObjReplace(interp, res, 0, 0, 1, xv); + + Tcl_SetErrorCode (interp, "PT", "RDE", "SYNTAX", NULL); + Tcl_SetObjResult (interp, res); + return TCL_ERROR; + } + } + + + /* * ** *** ***** ******** ************* + ** Object command, method dispatch. + */ + static int parser_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + RDE_PARAM p = (RDE_PARAM) cd; + int m, res; + + static CONST char* methods [] = { + "destroy", "parse", "parset", NULL + }; + enum methods { + M_DESTROY, M_PARSE, M_PARSET + }; + + if (objc < 2) { + Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option", + 0, &m) != TCL_OK) { + return TCL_ERROR; + } + + /* Dispatch to methods. They check the #args in + * detail before performing the requested + * functionality + */ + + switch (m) { + case M_DESTROY: + if (objc != 2) { + Tcl_WrongNumArgs (interp, 2, objv, NULL); + return TCL_ERROR; + } + + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) rde_param_query_clientdata (p)); + return TCL_OK; + + case M_PARSE: res = parser_PARSE (p, interp, objc, objv); break; + case M_PARSET: res = parser_PARSET (p, interp, objc, objv); break; + default: + /* Not coming to this place */ + ASSERT (0,"Reached unreachable location"); + } + + return res; + } + + /** * ** *** ***** ******** ************* + * Class command, i.e. object construction. + */ + static int ParserClassCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const*objv) { + /* + * Syntax: No arguments beyond the name + */ + + RDE_PARAM parser; + CONST char* name; + Tcl_Obj* fqn; + Tcl_CmdInfo ci; + Tcl_Command c; + +#define USAGE "?name?" + + if ((objc != 2) && (objc != 1)) { + Tcl_WrongNumArgs (interp, 1, objv, USAGE); + return TCL_ERROR; + } + + if (objc < 2) { + name = PARSERnewName (interp); + } else { + name = Tcl_GetString (objv [1]); + } + + if (!Tcl_StringMatch (name, "::*")) { + /* Relative name. Prefix with current namespace */ + + Tcl_Eval (interp, "namespace current"); + fqn = Tcl_GetObjResult (interp); + fqn = Tcl_DuplicateObj (fqn); + Tcl_IncrRefCount (fqn); + + if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { + Tcl_AppendToObj (fqn, "::", -1); + } + Tcl_AppendToObj (fqn, name, -1); + } else { + fqn = Tcl_NewStringObj (name, -1); + Tcl_IncrRefCount (fqn); + } + Tcl_ResetResult (interp); + + if (Tcl_GetCommandInfo (interp, + Tcl_GetString (fqn), + &ci)) { + Tcl_Obj* err; + + err = Tcl_NewObj (); + Tcl_AppendToObj (err, "command \"", -1); + Tcl_AppendObjToObj (err, fqn); + Tcl_AppendToObj (err, "\" already exists", -1); + + Tcl_DecrRefCount (fqn); + Tcl_SetObjResult (interp, err); + return TCL_ERROR; + } + + parser = rde_param_new (sizeof(p_string)/sizeof(char*), (char**) p_string); + c = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), + parser_objcmd, (ClientData) parser, + PARSERdeleteCmd); + rde_param_clientdata (parser, (ClientData) c); + Tcl_SetObjResult (interp, fqn); + Tcl_DecrRefCount (fqn); + return TCL_OK; + } + +int Package_Init(Tcl_Interp* interp) { + if (interp == 0) return TCL_ERROR; + + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + + if (Tcl_CreateObjCommand(interp, "PARSER", ParserClassCmd , NULL, NULL) == NULL) { + Tcl_SetResult(interp, "Can't create constructor", NULL); + return TCL_ERROR; + } + + + Tcl_PkgProvide(interp, "PACKAGE", "0.1"); + + return TCL_OK; +} ADDED modules/pt/tests/data/ok/peg_cparam-tea/11_epsilon Index: modules/pt/tests/data/ok/peg_cparam-tea/11_epsilon ================================================================== --- /dev/null +++ modules/pt/tests/data/ok/peg_cparam-tea/11_epsilon @@ -0,0 +1,1998 @@ +/************************************************************ +** +** TEA-based C/PARAM implementation of the parsing +** expression grammar +** +** TEMPLATE +** +** Generated from file TEST +** for user unknown +** +* * ** *** ***** ******** ************* *********************/ + #include + #include + #include + #include + #define SCOPE static + +#line 1 "rde_critcl/util.h" + + #ifndef _RDE_UTIL_H + #define _RDE_UTIL_H 1 + #ifndef SCOPE + #define SCOPE + #endif + #define ALLOC(type) (type *) ckalloc (sizeof (type)) + #define NALLOC(n,type) (type *) ckalloc ((n) * sizeof (type)) + #undef RDE_DEBUG + #define RDE_DEBUG 1 + #undef RDE_TRACE + #ifdef RDE_DEBUG + #define STOPAFTER(x) { static int count = (x); count --; if (!count) { Tcl_Panic ("stop"); } } + #define XSTR(x) #x + #define STR(x) XSTR(x) + #define RANGEOK(i,n) ((0 <= (i)) && (i < (n))) + #define ASSERT(x,msg) if (!(x)) { Tcl_Panic (msg " (" #x "), in file " __FILE__ " @line " STR(__LINE__));} + #define ASSERT_BOUNDS(i,n) ASSERT (RANGEOK(i,n),"array index out of bounds: " STR(i) " >= " STR(n)) + #else + #define STOPAFTER(x) + #define ASSERT(x,msg) + #define ASSERT_BOUNDS(i,n) + #endif + #ifdef RDE_TRACE + SCOPE void trace_enter (const char* fun); + SCOPE void trace_return (const char *pat, ...); + SCOPE void trace_printf (const char *pat, ...); + #define ENTER(fun) trace_enter (fun) + #define RETURN(format,x) trace_return (format,x) ; return x + #define RETURNVOID trace_return ("%s","(void)") ; return + #define TRACE0(x) trace_printf0 x + #define TRACE(x) trace_printf x + #else + #define ENTER(fun) + #define RETURN(f,x) return x + #define RETURNVOID return + #define TRACE0(x) + #define TRACE(x) + #endif + #endif + + +#line 1 "rde_critcl/stack.h" + + #ifndef _RDE_DS_STACK_H + #define _RDE_DS_STACK_H 1 + typedef void (*RDE_STACK_CELL_FREE) (void* cell); + typedef struct RDE_STACK_* RDE_STACK; + static const int RDE_STACK_INITIAL_SIZE = 256; + #endif + + +#line 1 "rde_critcl/tc.h" + + #ifndef _RDE_DS_TC_H + #define _RDE_DS_TC_H 1 + typedef struct RDE_TC_* RDE_TC; + #endif + + +#line 1 "rde_critcl/param.h" + + #ifndef _RDE_DS_PARAM_H + #define _RDE_DS_PARAM_H 1 + typedef struct RDE_PARAM_* RDE_PARAM; + typedef struct ERROR_STATE { + int refCount; + long int loc; + RDE_STACK msg; + } ERROR_STATE; + typedef struct NC_STATE { + long int CL; + long int ST; + Tcl_Obj* SV; + ERROR_STATE* ER; + } NC_STATE; + #endif + + +#line 1 "rde_critcl/util.c" + + #ifdef RDE_TRACE + typedef struct F_STACK { + const char* str; + struct F_STACK* down; + } F_STACK; + static F_STACK* top = 0; + static int level = 0; + static void + push (const char* str) + { + F_STACK* new = ALLOC (F_STACK); + new->str = str; + new->down = top; + top = new; + level += 4; + } + static void + pop (void) + { + F_STACK* next = top->down; + level -= 4; + ckfree ((char*)top); + top = next; + } + static void + indent (void) + { + int i; + for (i = 0; i < level; i++) { + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + if (top) { + fwrite(top->str, 1, strlen(top->str), stdout); + fflush (stdout); + } + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + SCOPE void + trace_enter (const char* fun) + { + push (fun); + indent(); + fwrite("ENTER\n", 1, 6, stdout); + fflush (stdout); + } + static char msg [1024*1024]; + SCOPE void + trace_return (const char *pat, ...) + { + int len; + va_list args; + indent(); + fwrite("RETURN = ", 1, 9, stdout); + fflush (stdout); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + pop(); + } + SCOPE void + trace_printf (const char *pat, ...) + { + int len; + va_list args; + indent(); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + SCOPE void + trace_printf0 (const char *pat, ...) + { + int len; + va_list args; + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + #endif + + +#line 1 "rde_critcl/stack.c" + + typedef struct RDE_STACK_ { + long int max; + long int top; + RDE_STACK_CELL_FREE freeCellProc; + void** cell; + } RDE_STACK_; + + SCOPE RDE_STACK + rde_stack_new (RDE_STACK_CELL_FREE freeCellProc) + { + RDE_STACK s = ALLOC (RDE_STACK_); + s->cell = NALLOC (RDE_STACK_INITIAL_SIZE, void*); + s->max = RDE_STACK_INITIAL_SIZE; + s->top = 0; + s->freeCellProc = freeCellProc; + return s; + } + SCOPE void + rde_stack_del (RDE_STACK s) + { + if (s->freeCellProc && s->top) { + long int i; + for (i=0; i < s->top; i++) { + ASSERT_BOUNDS(i,s->max); + s->freeCellProc ( s->cell [i] ); + } + } + ckfree ((char*) s->cell); + ckfree ((char*) s); + } + SCOPE void + rde_stack_push (RDE_STACK s, void* item) + { + if (s->top >= s->max) { + long int new = s->max ? (2 * s->max) : RDE_STACK_INITIAL_SIZE; + void** cell = (void**) ckrealloc ((char*) s->cell, new * sizeof(void*)); + ASSERT (cell,"Memory allocation failure for RDE stack"); + s->max = new; + s->cell = cell; + } + ASSERT_BOUNDS(s->top,s->max); + s->cell [s->top] = item; + s->top ++; + } + SCOPE void* + rde_stack_top (RDE_STACK s) + { + ASSERT_BOUNDS(s->top-1,s->max); + return s->cell [s->top - 1]; + } + SCOPE void + rde_stack_pop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + if (s->freeCellProc) { + while (n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + n --; + } + } else { + s->top -= n; + } + } + SCOPE void + rde_stack_trim (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad trimsize"); + if (s->freeCellProc) { + while (s->top > n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + } + } else { + s->top = n; + } + } + SCOPE void + rde_stack_drop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + s->top -= n; + } + SCOPE void + rde_stack_move (RDE_STACK dst, RDE_STACK src) + { + ASSERT (dst->freeCellProc == src->freeCellProc, "Ownership mismatch"); + + while (src->top > 0) { + src->top --; + ASSERT_BOUNDS(src->top,src->max); + rde_stack_push (dst, src->cell [src->top] ); + } + } + SCOPE void + rde_stack_get (RDE_STACK s, long int* cn, void*** cc) + { + *cn = s->top; + *cc = s->cell; + } + SCOPE long int + rde_stack_size (RDE_STACK s) + { + return s->top; + } + + +#line 1 "rde_critcl/tc.c" + + typedef struct RDE_TC_ { + int max; + int num; + char* str; + RDE_STACK off; + } RDE_TC_; + + SCOPE RDE_TC + rde_tc_new (void) + { + RDE_TC tc = ALLOC (RDE_TC_); + tc->max = RDE_STACK_INITIAL_SIZE; + tc->num = 0; + tc->str = NALLOC (RDE_STACK_INITIAL_SIZE, char); + tc->off = rde_stack_new (NULL); + return tc; + } + SCOPE void + rde_tc_del (RDE_TC tc) + { + rde_stack_del (tc->off); + ckfree (tc->str); + ckfree ((char*) tc); + } + SCOPE long int + rde_tc_size (RDE_TC tc) + { + return rde_stack_size (tc->off); + } + SCOPE void + rde_tc_clear (RDE_TC tc) + { + tc->num = 0; + rde_stack_trim (tc->off, 0); + } + SCOPE char* + rde_tc_append (RDE_TC tc, char* string, long int len) + { + long int base = tc->num; + long int off = tc->num; + char* ch; + int clen; + Tcl_UniChar uni; + if (len < 0) { + len = strlen (string); + } + + if (!len) { + return tc->str + base; + } + + if ((tc->num + len) >= tc->max) { + int new = len + (tc->max ? (2 * tc->max) : RDE_STACK_INITIAL_SIZE); + char* str = ckrealloc (tc->str, new * sizeof(char)); + ASSERT (str,"Memory allocation failure for token character array"); + tc->max = new; + tc->str = str; + } + tc->num += len; + ASSERT_BOUNDS(tc->num,tc->max); + ASSERT_BOUNDS(off,tc->max); + ASSERT_BOUNDS(off+len-1,tc->max); + ASSERT_BOUNDS(off+len-1,tc->num); + memcpy (tc->str + off, string, len); + + ch = string; + while (ch < (string + len)) { + ASSERT_BOUNDS(off,tc->num); + rde_stack_push (tc->off, (void*) off); + clen = Tcl_UtfToUniChar (ch, &uni); + off += clen; + ch += clen; + } + return tc->str + base; + } + SCOPE void + rde_tc_get (RDE_TC tc, int at, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + off = ov [at]; + if ((at+1) == oc) { + end = tc->num; + } else { + end = ov [at+1]; + } + TRACE (("rde_tc_get (RDE_TC %p, @ %d) => %d.[%d ... %d]/%d",tc,at,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + SCOPE void + rde_tc_get_s (RDE_TC tc, int at, int last, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + ASSERT_BOUNDS(last,oc); + off = ov [at]; + if ((last+1) == oc) { + end = tc->num; + } else { + end = ov [last+1]; + } + TRACE (("rde_tc_get_s (RDE_TC %p, @ %d .. %d) => %d.[%d ... %d]/%d",tc,at,last,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + + +#line 1 "rde_critcl/param.c" + + typedef struct RDE_PARAM_ { + Tcl_Channel IN; + Tcl_Obj* readbuf; + char* CC; + long int CC_len; + RDE_TC TC; + long int CL; + RDE_STACK LS; + ERROR_STATE* ER; + RDE_STACK ES; + long int ST; + Tcl_Obj* SV; + Tcl_HashTable NC; + + RDE_STACK ast ; + RDE_STACK mark ; + + long int numstr; + char** string; + + ClientData clientData; + } RDE_PARAM_; + typedef int (*UniCharClass) (int); + typedef enum test_class_id { + tc_alnum, + tc_alpha, + tc_ascii, + tc_control, + tc_ddigit, + tc_digit, + tc_graph, + tc_lower, + tc_printable, + tc_punct, + tc_space, + tc_upper, + tc_wordchar, + tc_xdigit + } test_class_id; + static void ast_node_free (void* n); + static void error_state_free (void* es); + static void error_set (RDE_PARAM p, int s); + static void nc_clear (RDE_PARAM p); + static int UniCharIsAscii (int character); + static int UniCharIsHexDigit (int character); + static int UniCharIsDecDigit (int character); + static void test_class (RDE_PARAM p, UniCharClass class, test_class_id id); + static int er_int_compare (const void* a, const void* b); + #define SV_INIT(p) \ + p->SV = NULL; \ + TRACE (("SV_INIT (%p => %p)", (p), (p)->SV)) + #define SV_SET(p,newsv) \ + if (((p)->SV) != (newsv)) { \ + TRACE (("SV_CLEAR/set (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = (newsv); \ + TRACE (("SV_SET (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_IncrRefCount ((p)->SV); \ + } \ + } + #define SV_CLEAR(p) \ + TRACE (("SV_CLEAR (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = NULL + #define ER_INIT(p) \ + p->ER = NULL; \ + TRACE (("ER_INIT (%p => %p)", (p), (p)->ER)) + #define ER_CLEAR(p) \ + error_state_free ((p)->ER); \ + (p)->ER = NULL + SCOPE RDE_PARAM + rde_param_new (long int nstr, char** strings) + { + RDE_PARAM p; + ENTER ("rde_param_new"); + TRACE (("\tINT %d strings @ %p", nstr, strings)); + p = ALLOC (RDE_PARAM_); + p->numstr = nstr; + p->string = strings; + p->readbuf = Tcl_NewObj (); + Tcl_IncrRefCount (p->readbuf); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_InitHashTable (&p->NC, TCL_ONE_WORD_KEYS); + p->IN = NULL; + p->CL = -1; + p->ST = 0; + ER_INIT (p); + SV_INIT (p); + p->CC = NULL; + p->CC_len = 0; + p->TC = rde_tc_new (); + p->ES = rde_stack_new (error_state_free); + p->LS = rde_stack_new (NULL); + p->ast = rde_stack_new (ast_node_free); + p->mark = rde_stack_new (NULL); + RETURN ("%p", p); + } + SCOPE void + rde_param_del (RDE_PARAM p) + { + ENTER ("rde_param_del"); + TRACE (("RDE_PARAM %p",p)); + ER_CLEAR (p); TRACE (("\ter_clear")); + SV_CLEAR (p); TRACE (("\tsv_clear")); + nc_clear (p); TRACE (("\tnc_clear")); + Tcl_DeleteHashTable (&p->NC); TRACE (("\tnc hashtable delete")); + rde_tc_del (p->TC); TRACE (("\ttc clear")); + rde_stack_del (p->ES); TRACE (("\tes clear")); + rde_stack_del (p->LS); TRACE (("\tls clear")); + rde_stack_del (p->ast); TRACE (("\tast clear")); + rde_stack_del (p->mark); TRACE (("\tmark clear")); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_DecrRefCount (p->readbuf); + ckfree ((char*) p); + RETURNVOID; + } + SCOPE void + rde_param_reset (RDE_PARAM p, Tcl_Channel chan) + { + ENTER ("rde_param_reset"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("Tcl_Channel %p",chan)); + p->IN = chan; + p->CL = -1; + p->ST = 0; + p->CC = NULL; + p->CC_len = 0; + ER_CLEAR (p); + SV_CLEAR (p); + nc_clear (p); + rde_tc_clear (p->TC); + rde_stack_trim (p->ES, 0); + rde_stack_trim (p->LS, 0); + rde_stack_trim (p->ast, 0); + rde_stack_trim (p->mark, 0); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + RETURNVOID; + } + SCOPE void + rde_param_update_strings (RDE_PARAM p, long int nstr, char** strings) + { + ENTER ("rde_param_update_strings"); + TRACE (("RDE_PARAM %p", p)); + TRACE (("INT %d strings", nstr)); + p->numstr = nstr; + p->string = strings; + RETURNVOID; + } + SCOPE void + rde_param_data (RDE_PARAM p, char* buf, long int len) + { + (void) rde_tc_append (p->TC, buf, len); + } + SCOPE void + rde_param_clientdata (RDE_PARAM p, ClientData clientData) + { + p->clientData = clientData; + } + static void + nc_clear (RDE_PARAM p) + { + Tcl_HashSearch hs; + Tcl_HashEntry* he; + Tcl_HashTable* tablePtr; + for(he = Tcl_FirstHashEntry(&p->NC, &hs); + he != NULL; + he = Tcl_FirstHashEntry(&p->NC, &hs)) { + Tcl_HashSearch hsc; + Tcl_HashEntry* hec; + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (he); + for(hec = Tcl_FirstHashEntry(tablePtr, &hsc); + hec != NULL; + hec = Tcl_NextHashEntry(&hsc)) { + NC_STATE* scs = Tcl_GetHashValue (hec); + error_state_free (scs->ER); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + ckfree ((char*) scs); + } + Tcl_DeleteHashTable (tablePtr); + ckfree ((char*) tablePtr); + Tcl_DeleteHashEntry (he); + } + } + SCOPE ClientData + rde_param_query_clientdata (RDE_PARAM p) + { + return p->clientData; + } + SCOPE void + rde_param_query_amark (RDE_PARAM p, long int* mc, long int** mv) + { + rde_stack_get (p->mark, mc, (void***) mv); + } + SCOPE void + rde_param_query_ast (RDE_PARAM p, long int* ac, Tcl_Obj*** av) + { + rde_stack_get (p->ast, ac, (void***) av); + } + SCOPE const char* + rde_param_query_in (RDE_PARAM p) + { + return p->IN + ? Tcl_GetChannelName (p->IN) + : ""; + } + SCOPE const char* + rde_param_query_cc (RDE_PARAM p, long int* len) + { + *len = p->CC_len; + return p->CC; + } + SCOPE int + rde_param_query_cl (RDE_PARAM p) + { + return p->CL; + } + SCOPE const ERROR_STATE* + rde_param_query_er (RDE_PARAM p) + { + return p->ER; + } + SCOPE Tcl_Obj* + rde_param_query_er_tcl (RDE_PARAM p, const ERROR_STATE* er) + { + Tcl_Obj* res; + if (!er) { + + res = Tcl_NewStringObj ("", 0); + } else { + Tcl_Obj* ov [2]; + Tcl_Obj** mov; + long int mc, i, j; + long int* mv; + int lastid; + const char* msg; + rde_stack_get (er->msg, &mc, (void***) &mv); + + qsort (mv, mc, sizeof (long int), er_int_compare); + + mov = NALLOC (mc, Tcl_Obj*); + lastid = -1; + for (i=0, j=0; i < mc; i++) { + ASSERT_BOUNDS (i,mc); + if (mv [i] == lastid) continue; + lastid = mv [i]; + ASSERT_BOUNDS(mv[i],p->numstr); + msg = p->string [mv[i]]; + ASSERT_BOUNDS (j,mc); + mov [j] = Tcl_NewStringObj (msg, -1); + j++; + } + + ov [0] = Tcl_NewIntObj (er->loc); + ov [1] = Tcl_NewListObj (j, mov); + res = Tcl_NewListObj (2, ov); + ckfree ((char*) mov); + } + return res; + } + SCOPE void + rde_param_query_es (RDE_PARAM p, long int* ec, ERROR_STATE*** ev) + { + rde_stack_get (p->ES, ec, (void***) ev); + } + SCOPE void + rde_param_query_ls (RDE_PARAM p, long int* lc, void*** lv) + { + rde_stack_get (p->LS, lc, lv); + } + SCOPE long int + rde_param_query_lstop (RDE_PARAM p) + { + (long int) rde_stack_top (p->LS); + } + SCOPE Tcl_HashTable* + rde_param_query_nc (RDE_PARAM p) + { + return &p->NC; + } + SCOPE int + rde_param_query_st (RDE_PARAM p) + { + return p->ST; + } + SCOPE Tcl_Obj* + rde_param_query_sv (RDE_PARAM p) + { + TRACE (("SV_QUERY %p => (%p)", (p), (p)->SV)); \ + return p->SV; + } + SCOPE long int + rde_param_query_tc_size (RDE_PARAM p) + { + return rde_tc_size (p->TC); + } + SCOPE void + rde_param_query_tc_get_s (RDE_PARAM p, long int at, long int last, char** ch, long int* len) + { + rde_tc_get_s (p->TC, at, last, ch, len); + } + SCOPE const char* + rde_param_query_string (RDE_PARAM p, long int id) + { + TRACE (("rde_param_query_string (RDE_PARAM %p, %d/%d)", p, id, p->numstr)); + ASSERT_BOUNDS(id,p->numstr); + return p->string [id]; + } + SCOPE void + rde_param_i_ast_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->mark, 1); + } + SCOPE void + rde_param_i_ast_pop_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_pop_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_push (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_ast_value_push (RDE_PARAM p) + { + ENTER ("rde_param_i_ast_value_push"); + TRACE (("RDE_PARAM %p",p)); + ASSERT(p->SV,"Unable to push undefined semantic value"); + TRACE (("rde_param_i_ast_value_push %p => (%p)", p, p->SV)); + TRACE (("SV = (%p rc%d '%s')", p->SV, p->SV->refCount, Tcl_GetString (p->SV))); + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + RETURNVOID; + } + static void + ast_node_free (void* n) + { + Tcl_DecrRefCount ((Tcl_Obj*) n); + } + SCOPE void + rde_param_i_error_clear (RDE_PARAM p) + { + ER_CLEAR (p); + } + SCOPE void + rde_param_i_error_nonterminal (RDE_PARAM p, int s) + { + + return; + long int pos; + if (!p->ER) return; + pos = 1 + (long int) rde_stack_top (p->LS); + if (p->ER->loc != pos) return; + error_set (p, s); + p->ER->loc = pos; + } + SCOPE void + rde_param_i_error_pop_merge (RDE_PARAM p) + { + ERROR_STATE* top = (ERROR_STATE*) rde_stack_top (p->ES); + + if (top == p->ER) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!top) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!p->ER) { + rde_stack_drop (p->ES, 1); + p->ER = top; + + return; + } + + if (top->loc < p->ER->loc) { + rde_stack_pop (p->ES, 1); + return; + } + + if (top->loc > p->ER->loc) { + rde_stack_drop (p->ES, 1); + error_state_free (p->ER); + p->ER = top; + + return; + } + + rde_stack_move (p->ER->msg, top->msg); + rde_stack_pop (p->ES, 1); + } + SCOPE void + rde_param_i_error_push (RDE_PARAM p) + { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + static void + error_set (RDE_PARAM p, int s) + { + error_state_free (p->ER); + p->ER = ALLOC (ERROR_STATE); + p->ER->refCount = 1; + p->ER->loc = p->CL; + p->ER->msg = rde_stack_new (NULL); + ASSERT_BOUNDS(s,p->numstr); + rde_stack_push (p->ER->msg, (void*) s); + } + static void + error_state_free (void* esx) + { + ERROR_STATE* es = esx; + if (!es) return; + es->refCount --; + if (es->refCount > 0) return; + rde_stack_del (es->msg); + ckfree ((char*) es); + } + SCOPE void + rde_param_i_loc_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_pop_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_push (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + } + SCOPE void + rde_param_i_loc_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + } + SCOPE void + rde_param_i_input_next (RDE_PARAM p, int m) + { + int leni; + char* ch; + ASSERT_BOUNDS(m,p->numstr); + p->CL ++; + if (p->CL < rde_tc_size (p->TC)) { + + rde_tc_get (p->TC, p->CL, &p->CC, &p->CC_len); + ASSERT_BOUNDS (p->CC_len, TCL_UTF_MAX); + p->ST = 1; + ER_CLEAR (p); + return; + } + if (!p->IN || + Tcl_Eof (p->IN) || + (Tcl_ReadChars (p->IN, p->readbuf, 1, 0) <= 0)) { + + p->ST = 0; + error_set (p, m); + return; + } + + ch = Tcl_GetStringFromObj (p->readbuf, &leni); + ASSERT_BOUNDS (leni, TCL_UTF_MAX); + p->CC = rde_tc_append (p->TC, ch, leni); + p->CC_len = leni; + p->ST = 1; + ER_CLEAR (p); + } + SCOPE void + rde_param_i_status_fail (RDE_PARAM p) + { + p->ST = 0; + } + SCOPE void + rde_param_i_status_ok (RDE_PARAM p) + { + p->ST = 1; + } + SCOPE void + rde_param_i_status_negate (RDE_PARAM p) + { + p->ST = !p->ST; + } + SCOPE int + rde_param_i_symbol_restore (RDE_PARAM p, int s) + { + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + + hPtr = Tcl_FindHashEntry (&p->NC, (char*) p->CL); + if (!hPtr) { return 0; } + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + hPtr = Tcl_FindHashEntry (tablePtr, (char*) s); + if (!hPtr) { return 0; } + + scs = Tcl_GetHashValue (hPtr); + p->CL = scs->CL; + p->ST = scs->ST; + error_state_free (p->ER); + p->ER = scs->ER; + if (p->ER) { p->ER->refCount ++; } + TRACE (("SV_RESTORE (%p) '%s'",scs->SV, scs->SV ? Tcl_GetString (scs->SV):"")); + SV_SET (p, scs->SV); + return 1; + } + SCOPE void + rde_param_i_symbol_save (RDE_PARAM p, int s) + { + long int at = (long int) rde_stack_top (p->LS); + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + int isnew; + ENTER ("rde_param_i_symbol_save"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("INT %d",s)); + + hPtr = Tcl_CreateHashEntry (&p->NC, (char*) at, &isnew); + if (isnew) { + tablePtr = ALLOC (Tcl_HashTable); + Tcl_InitHashTable (tablePtr, TCL_ONE_WORD_KEYS); + Tcl_SetHashValue (hPtr, tablePtr); + } else { + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + } + hPtr = Tcl_CreateHashEntry (tablePtr, (char*) s, &isnew); + if (isnew) { + + scs = ALLOC (NC_STATE); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "")); + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + Tcl_SetHashValue (hPtr, scs); + } else { + + scs = (NC_STATE*) Tcl_GetHashValue (hPtr); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE/over (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "" )); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + error_state_free (scs->ER); + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + } + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_test_alnum (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlnum, tc_alnum); + } + SCOPE void + rde_param_i_test_alpha (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlpha, tc_alpha); + } + SCOPE void + rde_param_i_test_ascii (RDE_PARAM p) + { + test_class (p, UniCharIsAscii, tc_ascii); + } + SCOPE void + rde_param_i_test_control (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsControl, tc_control); + } + SCOPE void + rde_param_i_test_char (RDE_PARAM p, const char* c, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = Tcl_UtfNcmp (p->CC, c, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_ddigit (RDE_PARAM p) + { + test_class (p, UniCharIsDecDigit, tc_ddigit); + } + SCOPE void + rde_param_i_test_digit (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsDigit, tc_digit); + } + SCOPE void + rde_param_i_test_graph (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsGraph, tc_graph); + } + SCOPE void + rde_param_i_test_lower (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsLower, tc_lower); + } + SCOPE void + rde_param_i_test_print (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPrint, tc_printable); + } + SCOPE void + rde_param_i_test_punct (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPunct, tc_punct); + } + SCOPE void + rde_param_i_test_range (RDE_PARAM p, char* s, char* e, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = + (Tcl_UtfNcmp (s, p->CC, 1) <= 0) && + (Tcl_UtfNcmp (p->CC, e, 1) <= 0); + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_space (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsSpace, tc_space); + } + SCOPE void + rde_param_i_test_upper (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsUpper, tc_upper); + } + SCOPE void + rde_param_i_test_wordchar (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsWordChar, tc_wordchar); + } + SCOPE void + rde_param_i_test_xdigit (RDE_PARAM p) + { + test_class (p, UniCharIsHexDigit, tc_xdigit); + } + static void + test_class (RDE_PARAM p, UniCharClass class, test_class_id id) + { + Tcl_UniChar ch; + Tcl_UtfToUniChar(p->CC, &ch); + ASSERT_BOUNDS(id,p->numstr); + p->ST = !!class (ch); + + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, id); + p->CL --; + } + } + static int + UniCharIsAscii (int character) + { + return (character >= 0) && (character < 0x80); + } + static int + UniCharIsHexDigit (int character) + { + return (character >= 0) && (character < 0x80) && isxdigit(character); + } + static int + UniCharIsDecDigit (int character) + { + return (character >= 0) && (character < 0x80) && isdigit(character); + } + SCOPE void + rde_param_i_value_clear (RDE_PARAM p) + { + SV_CLEAR (p); + } + SCOPE void + rde_param_i_value_leaf (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + Tcl_Obj* ov [3]; + long int pos = 1 + (long int) rde_stack_top (p->LS); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + newsv = Tcl_NewListObj (3, ov); + TRACE (("rde_param_i_value_leaf => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + } + SCOPE void + rde_param_i_value_reduce (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + int oc, i, j; + Tcl_Obj** ov; + long int ac; + Tcl_Obj** av; + long int pos = 1 + (long int) rde_stack_top (p->LS); + long int mark = (long int) rde_stack_top (p->mark); + long int asize = rde_stack_size (p->ast); + long int new = asize - mark; + ASSERT (new >= 0, "Bad number of elements to reduce"); + ov = NALLOC (3+new, Tcl_Obj*); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + rde_stack_get (p->ast, &ac, (void***) &av); + for (i = 3, j = mark; j < asize; i++, j++) { + ASSERT_BOUNDS (i, 3+new); + ASSERT_BOUNDS (j, ac); + ov [i] = av [j]; + } + ASSERT (i == 3+new, "Reduction result incomplete"); + newsv = Tcl_NewListObj (3+new, ov); + TRACE (("rde_param_i_value_reduce => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + ckfree ((char*) ov); + } + static int + er_int_compare (const void* a, const void* b) + { + long int ai = *((long int*) a); + long int bi = *((long int*) b); + if (ai < bi) { return -1; } + if (ai > bi) { return 1; } + return 0; + } + SCOPE int + rde_param_i_symbol_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE void + rde_param_i_symbol_done_d_reduce (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_reduce (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_d_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_symbol_done_d_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_next_char (RDE_PARAM p, char* c, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_char (p, c, m); + } + SCOPE void + rde_param_i_next_range (RDE_PARAM p, char* s, char* e, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_range (p, s, e, m); + } + SCOPE void + rde_param_i_next_alnum (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alnum (p); + } + SCOPE void + rde_param_i_next_alpha (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alpha (p); + } + SCOPE void + rde_param_i_next_ascii (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ascii (p); + } + SCOPE void + rde_param_i_next_control (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_control (p); + } + SCOPE void + rde_param_i_next_ddigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ddigit (p); + } + SCOPE void + rde_param_i_next_digit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_digit (p); + } + SCOPE void + rde_param_i_next_graph (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_graph (p); + } + SCOPE void + rde_param_i_next_lower (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_lower (p); + } + SCOPE void + rde_param_i_next_print (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_print (p); + } + SCOPE void + rde_param_i_next_punct (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_punct (p); + } + SCOPE void + rde_param_i_next_space (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_space (p); + } + SCOPE void + rde_param_i_next_upper (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_upper (p); + } + SCOPE void + rde_param_i_next_wordchar (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_wordchar (p); + } + SCOPE void + rde_param_i_next_xdigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_xdigit (p); + } + SCOPE void + rde_param_i_notahead_start_d (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_notahead_exit_d (RDE_PARAM p) + { + if (p->ST) { + rde_param_i_ast_pop_rewind (p); + } else { + rde_stack_pop (p->mark, 1); + } + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_notahead_exit (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_state_push_2 (RDE_PARAM p) + { + + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + SCOPE void + rde_param_i_state_push_void (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_push_value (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_merge_ok (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } + SCOPE int + rde_param_i_kleene_close (RDE_PARAM p) + { + int stop = !p->ST; + rde_param_i_error_pop_merge (p); + if (stop) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_kleene_abort (RDE_PARAM p) + { + int stop = !p->ST; + if (stop) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_seq_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_bra_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE void + rde_param_i_next_str (RDE_PARAM p, const char* str, int m) + { + int at = p->CL; + + while (*str) { + rde_param_i_input_next (p, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + rde_param_i_test_char (p, str, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + str = Tcl_UtfNext (str); + } + } + SCOPE void + rde_param_i_next_class (RDE_PARAM p, const char* class, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + while (*class) { + p->ST = Tcl_UtfNcmp (p->CC, class, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + return; + } + class = Tcl_UtfNext (class); + } + error_set (p, m); + p->CL --; + } + + + /* + * Declaring the parse functions + */ + + static void choice_3 (RDE_PARAM p); + + /* + * Precomputed table of strings (symbols, error messages, etc.). + */ + + static char const* p_string [15] = { + /* 0 = */ "alnum", + /* 1 = */ "alpha", + /* 2 = */ "ascii", + /* 3 = */ "control", + /* 4 = */ "ddigit", + /* 5 = */ "digit", + /* 6 = */ "graph", + /* 7 = */ "lower", + /* 8 = */ "print", + /* 9 = */ "punct", + /* 10 = */ "space", + /* 11 = */ "upper", + /* 12 = */ "wordchar", + /* 13 = */ "xdigit", + /* 14 = */ "t a" + }; + + /* + * Grammar Start Expression + */ + + static void MAIN (RDE_PARAM p) { + choice_3 (p); + return; + } + + static void choice_3 (RDE_PARAM p) { + /* + * / + * 'a' + * + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "a", 14); + if (rde_param_i_bra_void2void(p)) return; + rde_param_i_status_ok (p); + rde_param_i_state_merge_void (p); + return; + } + + /* -*- c -*- */ + + typedef struct PARSERg { + long int counter; + char buf [50]; + } PARSERg; + + static void + PARSERgRelease (ClientData cd, Tcl_Interp* interp) + { + ckfree((char*) cd); + } + + static const char* + PARSERnewName (Tcl_Interp* interp) + { +#define KEY "tcllib/parser/PACKAGE/TEA" + + Tcl_InterpDeleteProc* proc = PARSERgRelease; + PARSERg* parserg; + + parserg = Tcl_GetAssocData (interp, KEY, &proc); + if (parserg == NULL) { + parserg = (PARSERg*) ckalloc (sizeof (PARSERg)); + parserg->counter = 0; + + Tcl_SetAssocData (interp, KEY, proc, + (ClientData) parserg); + } + + parserg->counter ++; + sprintf (parserg->buf, "PARSER%d", parserg->counter); + return parserg->buf; +#undef KEY + } + + static void + PARSERdeleteCmd (ClientData clientData) + { + /* + * Release the whole PARSER + * (Low-level engine only actually). + */ + rde_param_del ((RDE_PARAM) clientData); + } + + + /* * ** *** ***** ******** ************* + ** Functions implementing the object methods, and helper. + */ + + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp); + + static int parser_PARSE (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + int mode; + Tcl_Channel chan; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "chan"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, + Tcl_GetString (objv[2]), + &mode); + + if (!chan) { + return TCL_ERROR; + } + + rde_param_reset (p, chan); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + static int parser_PARSET (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + char* buf; + int len; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "text"); + return TCL_ERROR; + } + + buf = Tcl_GetStringFromObj (objv[2], &len); + + rde_param_reset (p, NULL); + rde_param_data (p, buf, len); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + /* See also rde_critcl/m.c, param_COMPLETE() */ + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp) + { + if (rde_param_query_st (p)) { + long int ac; + Tcl_Obj** av; + + rde_param_query_ast (p, &ac, &av); + + if (ac > 1) { + Tcl_Obj** lv = NALLOC (3+ac, Tcl_Obj*); + + memcpy(lv + 3, av, ac * sizeof (Tcl_Obj*)); + lv [0] = Tcl_NewObj (); + lv [1] = Tcl_NewIntObj (1 + rde_param_query_lstop (p)); + lv [2] = Tcl_NewIntObj (rde_param_query_cl (p)); + + Tcl_SetObjResult (interp, Tcl_NewListObj (3, lv)); + ckfree ((char*) lv); + + } else if (ac == 0) { + /* + * Match, but no AST. This is possible if the grammar + * consists of only the start expression. + */ + Tcl_SetObjResult (interp, Tcl_NewStringObj ("",-1)); + } else { + Tcl_SetObjResult (interp, av [0]); + } + + return TCL_OK; + } else { + Tcl_Obj* xv [1]; + const ERROR_STATE* er = rde_param_query_er (p); + Tcl_Obj* res = rde_param_query_er_tcl (p, er); + /* res = list (location, list(msg)) */ + + /* Stick the exception type-tag before the existing elements */ + xv [0] = Tcl_NewStringObj ("pt::rde",-1); + Tcl_ListObjReplace(interp, res, 0, 0, 1, xv); + + Tcl_SetErrorCode (interp, "PT", "RDE", "SYNTAX", NULL); + Tcl_SetObjResult (interp, res); + return TCL_ERROR; + } + } + + + /* * ** *** ***** ******** ************* + ** Object command, method dispatch. + */ + static int parser_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + RDE_PARAM p = (RDE_PARAM) cd; + int m, res; + + static CONST char* methods [] = { + "destroy", "parse", "parset", NULL + }; + enum methods { + M_DESTROY, M_PARSE, M_PARSET + }; + + if (objc < 2) { + Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option", + 0, &m) != TCL_OK) { + return TCL_ERROR; + } + + /* Dispatch to methods. They check the #args in + * detail before performing the requested + * functionality + */ + + switch (m) { + case M_DESTROY: + if (objc != 2) { + Tcl_WrongNumArgs (interp, 2, objv, NULL); + return TCL_ERROR; + } + + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) rde_param_query_clientdata (p)); + return TCL_OK; + + case M_PARSE: res = parser_PARSE (p, interp, objc, objv); break; + case M_PARSET: res = parser_PARSET (p, interp, objc, objv); break; + default: + /* Not coming to this place */ + ASSERT (0,"Reached unreachable location"); + } + + return res; + } + + /** * ** *** ***** ******** ************* + * Class command, i.e. object construction. + */ + static int ParserClassCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const*objv) { + /* + * Syntax: No arguments beyond the name + */ + + RDE_PARAM parser; + CONST char* name; + Tcl_Obj* fqn; + Tcl_CmdInfo ci; + Tcl_Command c; + +#define USAGE "?name?" + + if ((objc != 2) && (objc != 1)) { + Tcl_WrongNumArgs (interp, 1, objv, USAGE); + return TCL_ERROR; + } + + if (objc < 2) { + name = PARSERnewName (interp); + } else { + name = Tcl_GetString (objv [1]); + } + + if (!Tcl_StringMatch (name, "::*")) { + /* Relative name. Prefix with current namespace */ + + Tcl_Eval (interp, "namespace current"); + fqn = Tcl_GetObjResult (interp); + fqn = Tcl_DuplicateObj (fqn); + Tcl_IncrRefCount (fqn); + + if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { + Tcl_AppendToObj (fqn, "::", -1); + } + Tcl_AppendToObj (fqn, name, -1); + } else { + fqn = Tcl_NewStringObj (name, -1); + Tcl_IncrRefCount (fqn); + } + Tcl_ResetResult (interp); + + if (Tcl_GetCommandInfo (interp, + Tcl_GetString (fqn), + &ci)) { + Tcl_Obj* err; + + err = Tcl_NewObj (); + Tcl_AppendToObj (err, "command \"", -1); + Tcl_AppendObjToObj (err, fqn); + Tcl_AppendToObj (err, "\" already exists", -1); + + Tcl_DecrRefCount (fqn); + Tcl_SetObjResult (interp, err); + return TCL_ERROR; + } + + parser = rde_param_new (sizeof(p_string)/sizeof(char*), (char**) p_string); + c = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), + parser_objcmd, (ClientData) parser, + PARSERdeleteCmd); + rde_param_clientdata (parser, (ClientData) c); + Tcl_SetObjResult (interp, fqn); + Tcl_DecrRefCount (fqn); + return TCL_OK; + } + +int Package_Init(Tcl_Interp* interp) { + if (interp == 0) return TCL_ERROR; + + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + + if (Tcl_CreateObjCommand(interp, "PARSER", ParserClassCmd , NULL, NULL) == NULL) { + Tcl_SetResult(interp, "Can't create constructor", NULL); + return TCL_ERROR; + } + + + Tcl_PkgProvide(interp, "PACKAGE", "0.1"); + + return TCL_OK; +} ADDED modules/pt/tests/data/ok/peg_cparam-tea/1_functions Index: modules/pt/tests/data/ok/peg_cparam-tea/1_functions ================================================================== --- /dev/null +++ modules/pt/tests/data/ok/peg_cparam-tea/1_functions @@ -0,0 +1,2059 @@ +/************************************************************ +** +** TEA-based C/PARAM implementation of the parsing +** expression grammar +** +** TEMPLATE +** +** Generated from file TEST +** for user unknown +** +* * ** *** ***** ******** ************* *********************/ + #include + #include + #include + #include + #define SCOPE static + +#line 1 "rde_critcl/util.h" + + #ifndef _RDE_UTIL_H + #define _RDE_UTIL_H 1 + #ifndef SCOPE + #define SCOPE + #endif + #define ALLOC(type) (type *) ckalloc (sizeof (type)) + #define NALLOC(n,type) (type *) ckalloc ((n) * sizeof (type)) + #undef RDE_DEBUG + #define RDE_DEBUG 1 + #undef RDE_TRACE + #ifdef RDE_DEBUG + #define STOPAFTER(x) { static int count = (x); count --; if (!count) { Tcl_Panic ("stop"); } } + #define XSTR(x) #x + #define STR(x) XSTR(x) + #define RANGEOK(i,n) ((0 <= (i)) && (i < (n))) + #define ASSERT(x,msg) if (!(x)) { Tcl_Panic (msg " (" #x "), in file " __FILE__ " @line " STR(__LINE__));} + #define ASSERT_BOUNDS(i,n) ASSERT (RANGEOK(i,n),"array index out of bounds: " STR(i) " >= " STR(n)) + #else + #define STOPAFTER(x) + #define ASSERT(x,msg) + #define ASSERT_BOUNDS(i,n) + #endif + #ifdef RDE_TRACE + SCOPE void trace_enter (const char* fun); + SCOPE void trace_return (const char *pat, ...); + SCOPE void trace_printf (const char *pat, ...); + #define ENTER(fun) trace_enter (fun) + #define RETURN(format,x) trace_return (format,x) ; return x + #define RETURNVOID trace_return ("%s","(void)") ; return + #define TRACE0(x) trace_printf0 x + #define TRACE(x) trace_printf x + #else + #define ENTER(fun) + #define RETURN(f,x) return x + #define RETURNVOID return + #define TRACE0(x) + #define TRACE(x) + #endif + #endif + + +#line 1 "rde_critcl/stack.h" + + #ifndef _RDE_DS_STACK_H + #define _RDE_DS_STACK_H 1 + typedef void (*RDE_STACK_CELL_FREE) (void* cell); + typedef struct RDE_STACK_* RDE_STACK; + static const int RDE_STACK_INITIAL_SIZE = 256; + #endif + + +#line 1 "rde_critcl/tc.h" + + #ifndef _RDE_DS_TC_H + #define _RDE_DS_TC_H 1 + typedef struct RDE_TC_* RDE_TC; + #endif + + +#line 1 "rde_critcl/param.h" + + #ifndef _RDE_DS_PARAM_H + #define _RDE_DS_PARAM_H 1 + typedef struct RDE_PARAM_* RDE_PARAM; + typedef struct ERROR_STATE { + int refCount; + long int loc; + RDE_STACK msg; + } ERROR_STATE; + typedef struct NC_STATE { + long int CL; + long int ST; + Tcl_Obj* SV; + ERROR_STATE* ER; + } NC_STATE; + #endif + + +#line 1 "rde_critcl/util.c" + + #ifdef RDE_TRACE + typedef struct F_STACK { + const char* str; + struct F_STACK* down; + } F_STACK; + static F_STACK* top = 0; + static int level = 0; + static void + push (const char* str) + { + F_STACK* new = ALLOC (F_STACK); + new->str = str; + new->down = top; + top = new; + level += 4; + } + static void + pop (void) + { + F_STACK* next = top->down; + level -= 4; + ckfree ((char*)top); + top = next; + } + static void + indent (void) + { + int i; + for (i = 0; i < level; i++) { + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + if (top) { + fwrite(top->str, 1, strlen(top->str), stdout); + fflush (stdout); + } + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + SCOPE void + trace_enter (const char* fun) + { + push (fun); + indent(); + fwrite("ENTER\n", 1, 6, stdout); + fflush (stdout); + } + static char msg [1024*1024]; + SCOPE void + trace_return (const char *pat, ...) + { + int len; + va_list args; + indent(); + fwrite("RETURN = ", 1, 9, stdout); + fflush (stdout); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + pop(); + } + SCOPE void + trace_printf (const char *pat, ...) + { + int len; + va_list args; + indent(); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + SCOPE void + trace_printf0 (const char *pat, ...) + { + int len; + va_list args; + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + #endif + + +#line 1 "rde_critcl/stack.c" + + typedef struct RDE_STACK_ { + long int max; + long int top; + RDE_STACK_CELL_FREE freeCellProc; + void** cell; + } RDE_STACK_; + + SCOPE RDE_STACK + rde_stack_new (RDE_STACK_CELL_FREE freeCellProc) + { + RDE_STACK s = ALLOC (RDE_STACK_); + s->cell = NALLOC (RDE_STACK_INITIAL_SIZE, void*); + s->max = RDE_STACK_INITIAL_SIZE; + s->top = 0; + s->freeCellProc = freeCellProc; + return s; + } + SCOPE void + rde_stack_del (RDE_STACK s) + { + if (s->freeCellProc && s->top) { + long int i; + for (i=0; i < s->top; i++) { + ASSERT_BOUNDS(i,s->max); + s->freeCellProc ( s->cell [i] ); + } + } + ckfree ((char*) s->cell); + ckfree ((char*) s); + } + SCOPE void + rde_stack_push (RDE_STACK s, void* item) + { + if (s->top >= s->max) { + long int new = s->max ? (2 * s->max) : RDE_STACK_INITIAL_SIZE; + void** cell = (void**) ckrealloc ((char*) s->cell, new * sizeof(void*)); + ASSERT (cell,"Memory allocation failure for RDE stack"); + s->max = new; + s->cell = cell; + } + ASSERT_BOUNDS(s->top,s->max); + s->cell [s->top] = item; + s->top ++; + } + SCOPE void* + rde_stack_top (RDE_STACK s) + { + ASSERT_BOUNDS(s->top-1,s->max); + return s->cell [s->top - 1]; + } + SCOPE void + rde_stack_pop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + if (s->freeCellProc) { + while (n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + n --; + } + } else { + s->top -= n; + } + } + SCOPE void + rde_stack_trim (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad trimsize"); + if (s->freeCellProc) { + while (s->top > n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + } + } else { + s->top = n; + } + } + SCOPE void + rde_stack_drop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + s->top -= n; + } + SCOPE void + rde_stack_move (RDE_STACK dst, RDE_STACK src) + { + ASSERT (dst->freeCellProc == src->freeCellProc, "Ownership mismatch"); + + while (src->top > 0) { + src->top --; + ASSERT_BOUNDS(src->top,src->max); + rde_stack_push (dst, src->cell [src->top] ); + } + } + SCOPE void + rde_stack_get (RDE_STACK s, long int* cn, void*** cc) + { + *cn = s->top; + *cc = s->cell; + } + SCOPE long int + rde_stack_size (RDE_STACK s) + { + return s->top; + } + + +#line 1 "rde_critcl/tc.c" + + typedef struct RDE_TC_ { + int max; + int num; + char* str; + RDE_STACK off; + } RDE_TC_; + + SCOPE RDE_TC + rde_tc_new (void) + { + RDE_TC tc = ALLOC (RDE_TC_); + tc->max = RDE_STACK_INITIAL_SIZE; + tc->num = 0; + tc->str = NALLOC (RDE_STACK_INITIAL_SIZE, char); + tc->off = rde_stack_new (NULL); + return tc; + } + SCOPE void + rde_tc_del (RDE_TC tc) + { + rde_stack_del (tc->off); + ckfree (tc->str); + ckfree ((char*) tc); + } + SCOPE long int + rde_tc_size (RDE_TC tc) + { + return rde_stack_size (tc->off); + } + SCOPE void + rde_tc_clear (RDE_TC tc) + { + tc->num = 0; + rde_stack_trim (tc->off, 0); + } + SCOPE char* + rde_tc_append (RDE_TC tc, char* string, long int len) + { + long int base = tc->num; + long int off = tc->num; + char* ch; + int clen; + Tcl_UniChar uni; + if (len < 0) { + len = strlen (string); + } + + if (!len) { + return tc->str + base; + } + + if ((tc->num + len) >= tc->max) { + int new = len + (tc->max ? (2 * tc->max) : RDE_STACK_INITIAL_SIZE); + char* str = ckrealloc (tc->str, new * sizeof(char)); + ASSERT (str,"Memory allocation failure for token character array"); + tc->max = new; + tc->str = str; + } + tc->num += len; + ASSERT_BOUNDS(tc->num,tc->max); + ASSERT_BOUNDS(off,tc->max); + ASSERT_BOUNDS(off+len-1,tc->max); + ASSERT_BOUNDS(off+len-1,tc->num); + memcpy (tc->str + off, string, len); + + ch = string; + while (ch < (string + len)) { + ASSERT_BOUNDS(off,tc->num); + rde_stack_push (tc->off, (void*) off); + clen = Tcl_UtfToUniChar (ch, &uni); + off += clen; + ch += clen; + } + return tc->str + base; + } + SCOPE void + rde_tc_get (RDE_TC tc, int at, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + off = ov [at]; + if ((at+1) == oc) { + end = tc->num; + } else { + end = ov [at+1]; + } + TRACE (("rde_tc_get (RDE_TC %p, @ %d) => %d.[%d ... %d]/%d",tc,at,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + SCOPE void + rde_tc_get_s (RDE_TC tc, int at, int last, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + ASSERT_BOUNDS(last,oc); + off = ov [at]; + if ((last+1) == oc) { + end = tc->num; + } else { + end = ov [last+1]; + } + TRACE (("rde_tc_get_s (RDE_TC %p, @ %d .. %d) => %d.[%d ... %d]/%d",tc,at,last,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + + +#line 1 "rde_critcl/param.c" + + typedef struct RDE_PARAM_ { + Tcl_Channel IN; + Tcl_Obj* readbuf; + char* CC; + long int CC_len; + RDE_TC TC; + long int CL; + RDE_STACK LS; + ERROR_STATE* ER; + RDE_STACK ES; + long int ST; + Tcl_Obj* SV; + Tcl_HashTable NC; + + RDE_STACK ast ; + RDE_STACK mark ; + + long int numstr; + char** string; + + ClientData clientData; + } RDE_PARAM_; + typedef int (*UniCharClass) (int); + typedef enum test_class_id { + tc_alnum, + tc_alpha, + tc_ascii, + tc_control, + tc_ddigit, + tc_digit, + tc_graph, + tc_lower, + tc_printable, + tc_punct, + tc_space, + tc_upper, + tc_wordchar, + tc_xdigit + } test_class_id; + static void ast_node_free (void* n); + static void error_state_free (void* es); + static void error_set (RDE_PARAM p, int s); + static void nc_clear (RDE_PARAM p); + static int UniCharIsAscii (int character); + static int UniCharIsHexDigit (int character); + static int UniCharIsDecDigit (int character); + static void test_class (RDE_PARAM p, UniCharClass class, test_class_id id); + static int er_int_compare (const void* a, const void* b); + #define SV_INIT(p) \ + p->SV = NULL; \ + TRACE (("SV_INIT (%p => %p)", (p), (p)->SV)) + #define SV_SET(p,newsv) \ + if (((p)->SV) != (newsv)) { \ + TRACE (("SV_CLEAR/set (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = (newsv); \ + TRACE (("SV_SET (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_IncrRefCount ((p)->SV); \ + } \ + } + #define SV_CLEAR(p) \ + TRACE (("SV_CLEAR (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = NULL + #define ER_INIT(p) \ + p->ER = NULL; \ + TRACE (("ER_INIT (%p => %p)", (p), (p)->ER)) + #define ER_CLEAR(p) \ + error_state_free ((p)->ER); \ + (p)->ER = NULL + SCOPE RDE_PARAM + rde_param_new (long int nstr, char** strings) + { + RDE_PARAM p; + ENTER ("rde_param_new"); + TRACE (("\tINT %d strings @ %p", nstr, strings)); + p = ALLOC (RDE_PARAM_); + p->numstr = nstr; + p->string = strings; + p->readbuf = Tcl_NewObj (); + Tcl_IncrRefCount (p->readbuf); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_InitHashTable (&p->NC, TCL_ONE_WORD_KEYS); + p->IN = NULL; + p->CL = -1; + p->ST = 0; + ER_INIT (p); + SV_INIT (p); + p->CC = NULL; + p->CC_len = 0; + p->TC = rde_tc_new (); + p->ES = rde_stack_new (error_state_free); + p->LS = rde_stack_new (NULL); + p->ast = rde_stack_new (ast_node_free); + p->mark = rde_stack_new (NULL); + RETURN ("%p", p); + } + SCOPE void + rde_param_del (RDE_PARAM p) + { + ENTER ("rde_param_del"); + TRACE (("RDE_PARAM %p",p)); + ER_CLEAR (p); TRACE (("\ter_clear")); + SV_CLEAR (p); TRACE (("\tsv_clear")); + nc_clear (p); TRACE (("\tnc_clear")); + Tcl_DeleteHashTable (&p->NC); TRACE (("\tnc hashtable delete")); + rde_tc_del (p->TC); TRACE (("\ttc clear")); + rde_stack_del (p->ES); TRACE (("\tes clear")); + rde_stack_del (p->LS); TRACE (("\tls clear")); + rde_stack_del (p->ast); TRACE (("\tast clear")); + rde_stack_del (p->mark); TRACE (("\tmark clear")); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_DecrRefCount (p->readbuf); + ckfree ((char*) p); + RETURNVOID; + } + SCOPE void + rde_param_reset (RDE_PARAM p, Tcl_Channel chan) + { + ENTER ("rde_param_reset"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("Tcl_Channel %p",chan)); + p->IN = chan; + p->CL = -1; + p->ST = 0; + p->CC = NULL; + p->CC_len = 0; + ER_CLEAR (p); + SV_CLEAR (p); + nc_clear (p); + rde_tc_clear (p->TC); + rde_stack_trim (p->ES, 0); + rde_stack_trim (p->LS, 0); + rde_stack_trim (p->ast, 0); + rde_stack_trim (p->mark, 0); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + RETURNVOID; + } + SCOPE void + rde_param_update_strings (RDE_PARAM p, long int nstr, char** strings) + { + ENTER ("rde_param_update_strings"); + TRACE (("RDE_PARAM %p", p)); + TRACE (("INT %d strings", nstr)); + p->numstr = nstr; + p->string = strings; + RETURNVOID; + } + SCOPE void + rde_param_data (RDE_PARAM p, char* buf, long int len) + { + (void) rde_tc_append (p->TC, buf, len); + } + SCOPE void + rde_param_clientdata (RDE_PARAM p, ClientData clientData) + { + p->clientData = clientData; + } + static void + nc_clear (RDE_PARAM p) + { + Tcl_HashSearch hs; + Tcl_HashEntry* he; + Tcl_HashTable* tablePtr; + for(he = Tcl_FirstHashEntry(&p->NC, &hs); + he != NULL; + he = Tcl_FirstHashEntry(&p->NC, &hs)) { + Tcl_HashSearch hsc; + Tcl_HashEntry* hec; + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (he); + for(hec = Tcl_FirstHashEntry(tablePtr, &hsc); + hec != NULL; + hec = Tcl_NextHashEntry(&hsc)) { + NC_STATE* scs = Tcl_GetHashValue (hec); + error_state_free (scs->ER); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + ckfree ((char*) scs); + } + Tcl_DeleteHashTable (tablePtr); + ckfree ((char*) tablePtr); + Tcl_DeleteHashEntry (he); + } + } + SCOPE ClientData + rde_param_query_clientdata (RDE_PARAM p) + { + return p->clientData; + } + SCOPE void + rde_param_query_amark (RDE_PARAM p, long int* mc, long int** mv) + { + rde_stack_get (p->mark, mc, (void***) mv); + } + SCOPE void + rde_param_query_ast (RDE_PARAM p, long int* ac, Tcl_Obj*** av) + { + rde_stack_get (p->ast, ac, (void***) av); + } + SCOPE const char* + rde_param_query_in (RDE_PARAM p) + { + return p->IN + ? Tcl_GetChannelName (p->IN) + : ""; + } + SCOPE const char* + rde_param_query_cc (RDE_PARAM p, long int* len) + { + *len = p->CC_len; + return p->CC; + } + SCOPE int + rde_param_query_cl (RDE_PARAM p) + { + return p->CL; + } + SCOPE const ERROR_STATE* + rde_param_query_er (RDE_PARAM p) + { + return p->ER; + } + SCOPE Tcl_Obj* + rde_param_query_er_tcl (RDE_PARAM p, const ERROR_STATE* er) + { + Tcl_Obj* res; + if (!er) { + + res = Tcl_NewStringObj ("", 0); + } else { + Tcl_Obj* ov [2]; + Tcl_Obj** mov; + long int mc, i, j; + long int* mv; + int lastid; + const char* msg; + rde_stack_get (er->msg, &mc, (void***) &mv); + + qsort (mv, mc, sizeof (long int), er_int_compare); + + mov = NALLOC (mc, Tcl_Obj*); + lastid = -1; + for (i=0, j=0; i < mc; i++) { + ASSERT_BOUNDS (i,mc); + if (mv [i] == lastid) continue; + lastid = mv [i]; + ASSERT_BOUNDS(mv[i],p->numstr); + msg = p->string [mv[i]]; + ASSERT_BOUNDS (j,mc); + mov [j] = Tcl_NewStringObj (msg, -1); + j++; + } + + ov [0] = Tcl_NewIntObj (er->loc); + ov [1] = Tcl_NewListObj (j, mov); + res = Tcl_NewListObj (2, ov); + ckfree ((char*) mov); + } + return res; + } + SCOPE void + rde_param_query_es (RDE_PARAM p, long int* ec, ERROR_STATE*** ev) + { + rde_stack_get (p->ES, ec, (void***) ev); + } + SCOPE void + rde_param_query_ls (RDE_PARAM p, long int* lc, void*** lv) + { + rde_stack_get (p->LS, lc, lv); + } + SCOPE long int + rde_param_query_lstop (RDE_PARAM p) + { + (long int) rde_stack_top (p->LS); + } + SCOPE Tcl_HashTable* + rde_param_query_nc (RDE_PARAM p) + { + return &p->NC; + } + SCOPE int + rde_param_query_st (RDE_PARAM p) + { + return p->ST; + } + SCOPE Tcl_Obj* + rde_param_query_sv (RDE_PARAM p) + { + TRACE (("SV_QUERY %p => (%p)", (p), (p)->SV)); \ + return p->SV; + } + SCOPE long int + rde_param_query_tc_size (RDE_PARAM p) + { + return rde_tc_size (p->TC); + } + SCOPE void + rde_param_query_tc_get_s (RDE_PARAM p, long int at, long int last, char** ch, long int* len) + { + rde_tc_get_s (p->TC, at, last, ch, len); + } + SCOPE const char* + rde_param_query_string (RDE_PARAM p, long int id) + { + TRACE (("rde_param_query_string (RDE_PARAM %p, %d/%d)", p, id, p->numstr)); + ASSERT_BOUNDS(id,p->numstr); + return p->string [id]; + } + SCOPE void + rde_param_i_ast_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->mark, 1); + } + SCOPE void + rde_param_i_ast_pop_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_pop_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_push (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_ast_value_push (RDE_PARAM p) + { + ENTER ("rde_param_i_ast_value_push"); + TRACE (("RDE_PARAM %p",p)); + ASSERT(p->SV,"Unable to push undefined semantic value"); + TRACE (("rde_param_i_ast_value_push %p => (%p)", p, p->SV)); + TRACE (("SV = (%p rc%d '%s')", p->SV, p->SV->refCount, Tcl_GetString (p->SV))); + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + RETURNVOID; + } + static void + ast_node_free (void* n) + { + Tcl_DecrRefCount ((Tcl_Obj*) n); + } + SCOPE void + rde_param_i_error_clear (RDE_PARAM p) + { + ER_CLEAR (p); + } + SCOPE void + rde_param_i_error_nonterminal (RDE_PARAM p, int s) + { + + return; + long int pos; + if (!p->ER) return; + pos = 1 + (long int) rde_stack_top (p->LS); + if (p->ER->loc != pos) return; + error_set (p, s); + p->ER->loc = pos; + } + SCOPE void + rde_param_i_error_pop_merge (RDE_PARAM p) + { + ERROR_STATE* top = (ERROR_STATE*) rde_stack_top (p->ES); + + if (top == p->ER) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!top) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!p->ER) { + rde_stack_drop (p->ES, 1); + p->ER = top; + + return; + } + + if (top->loc < p->ER->loc) { + rde_stack_pop (p->ES, 1); + return; + } + + if (top->loc > p->ER->loc) { + rde_stack_drop (p->ES, 1); + error_state_free (p->ER); + p->ER = top; + + return; + } + + rde_stack_move (p->ER->msg, top->msg); + rde_stack_pop (p->ES, 1); + } + SCOPE void + rde_param_i_error_push (RDE_PARAM p) + { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + static void + error_set (RDE_PARAM p, int s) + { + error_state_free (p->ER); + p->ER = ALLOC (ERROR_STATE); + p->ER->refCount = 1; + p->ER->loc = p->CL; + p->ER->msg = rde_stack_new (NULL); + ASSERT_BOUNDS(s,p->numstr); + rde_stack_push (p->ER->msg, (void*) s); + } + static void + error_state_free (void* esx) + { + ERROR_STATE* es = esx; + if (!es) return; + es->refCount --; + if (es->refCount > 0) return; + rde_stack_del (es->msg); + ckfree ((char*) es); + } + SCOPE void + rde_param_i_loc_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_pop_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_push (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + } + SCOPE void + rde_param_i_loc_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + } + SCOPE void + rde_param_i_input_next (RDE_PARAM p, int m) + { + int leni; + char* ch; + ASSERT_BOUNDS(m,p->numstr); + p->CL ++; + if (p->CL < rde_tc_size (p->TC)) { + + rde_tc_get (p->TC, p->CL, &p->CC, &p->CC_len); + ASSERT_BOUNDS (p->CC_len, TCL_UTF_MAX); + p->ST = 1; + ER_CLEAR (p); + return; + } + if (!p->IN || + Tcl_Eof (p->IN) || + (Tcl_ReadChars (p->IN, p->readbuf, 1, 0) <= 0)) { + + p->ST = 0; + error_set (p, m); + return; + } + + ch = Tcl_GetStringFromObj (p->readbuf, &leni); + ASSERT_BOUNDS (leni, TCL_UTF_MAX); + p->CC = rde_tc_append (p->TC, ch, leni); + p->CC_len = leni; + p->ST = 1; + ER_CLEAR (p); + } + SCOPE void + rde_param_i_status_fail (RDE_PARAM p) + { + p->ST = 0; + } + SCOPE void + rde_param_i_status_ok (RDE_PARAM p) + { + p->ST = 1; + } + SCOPE void + rde_param_i_status_negate (RDE_PARAM p) + { + p->ST = !p->ST; + } + SCOPE int + rde_param_i_symbol_restore (RDE_PARAM p, int s) + { + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + + hPtr = Tcl_FindHashEntry (&p->NC, (char*) p->CL); + if (!hPtr) { return 0; } + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + hPtr = Tcl_FindHashEntry (tablePtr, (char*) s); + if (!hPtr) { return 0; } + + scs = Tcl_GetHashValue (hPtr); + p->CL = scs->CL; + p->ST = scs->ST; + error_state_free (p->ER); + p->ER = scs->ER; + if (p->ER) { p->ER->refCount ++; } + TRACE (("SV_RESTORE (%p) '%s'",scs->SV, scs->SV ? Tcl_GetString (scs->SV):"")); + SV_SET (p, scs->SV); + return 1; + } + SCOPE void + rde_param_i_symbol_save (RDE_PARAM p, int s) + { + long int at = (long int) rde_stack_top (p->LS); + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + int isnew; + ENTER ("rde_param_i_symbol_save"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("INT %d",s)); + + hPtr = Tcl_CreateHashEntry (&p->NC, (char*) at, &isnew); + if (isnew) { + tablePtr = ALLOC (Tcl_HashTable); + Tcl_InitHashTable (tablePtr, TCL_ONE_WORD_KEYS); + Tcl_SetHashValue (hPtr, tablePtr); + } else { + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + } + hPtr = Tcl_CreateHashEntry (tablePtr, (char*) s, &isnew); + if (isnew) { + + scs = ALLOC (NC_STATE); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "")); + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + Tcl_SetHashValue (hPtr, scs); + } else { + + scs = (NC_STATE*) Tcl_GetHashValue (hPtr); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE/over (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "" )); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + error_state_free (scs->ER); + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + } + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_test_alnum (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlnum, tc_alnum); + } + SCOPE void + rde_param_i_test_alpha (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlpha, tc_alpha); + } + SCOPE void + rde_param_i_test_ascii (RDE_PARAM p) + { + test_class (p, UniCharIsAscii, tc_ascii); + } + SCOPE void + rde_param_i_test_control (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsControl, tc_control); + } + SCOPE void + rde_param_i_test_char (RDE_PARAM p, const char* c, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = Tcl_UtfNcmp (p->CC, c, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_ddigit (RDE_PARAM p) + { + test_class (p, UniCharIsDecDigit, tc_ddigit); + } + SCOPE void + rde_param_i_test_digit (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsDigit, tc_digit); + } + SCOPE void + rde_param_i_test_graph (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsGraph, tc_graph); + } + SCOPE void + rde_param_i_test_lower (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsLower, tc_lower); + } + SCOPE void + rde_param_i_test_print (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPrint, tc_printable); + } + SCOPE void + rde_param_i_test_punct (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPunct, tc_punct); + } + SCOPE void + rde_param_i_test_range (RDE_PARAM p, char* s, char* e, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = + (Tcl_UtfNcmp (s, p->CC, 1) <= 0) && + (Tcl_UtfNcmp (p->CC, e, 1) <= 0); + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_space (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsSpace, tc_space); + } + SCOPE void + rde_param_i_test_upper (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsUpper, tc_upper); + } + SCOPE void + rde_param_i_test_wordchar (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsWordChar, tc_wordchar); + } + SCOPE void + rde_param_i_test_xdigit (RDE_PARAM p) + { + test_class (p, UniCharIsHexDigit, tc_xdigit); + } + static void + test_class (RDE_PARAM p, UniCharClass class, test_class_id id) + { + Tcl_UniChar ch; + Tcl_UtfToUniChar(p->CC, &ch); + ASSERT_BOUNDS(id,p->numstr); + p->ST = !!class (ch); + + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, id); + p->CL --; + } + } + static int + UniCharIsAscii (int character) + { + return (character >= 0) && (character < 0x80); + } + static int + UniCharIsHexDigit (int character) + { + return (character >= 0) && (character < 0x80) && isxdigit(character); + } + static int + UniCharIsDecDigit (int character) + { + return (character >= 0) && (character < 0x80) && isdigit(character); + } + SCOPE void + rde_param_i_value_clear (RDE_PARAM p) + { + SV_CLEAR (p); + } + SCOPE void + rde_param_i_value_leaf (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + Tcl_Obj* ov [3]; + long int pos = 1 + (long int) rde_stack_top (p->LS); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + newsv = Tcl_NewListObj (3, ov); + TRACE (("rde_param_i_value_leaf => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + } + SCOPE void + rde_param_i_value_reduce (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + int oc, i, j; + Tcl_Obj** ov; + long int ac; + Tcl_Obj** av; + long int pos = 1 + (long int) rde_stack_top (p->LS); + long int mark = (long int) rde_stack_top (p->mark); + long int asize = rde_stack_size (p->ast); + long int new = asize - mark; + ASSERT (new >= 0, "Bad number of elements to reduce"); + ov = NALLOC (3+new, Tcl_Obj*); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + rde_stack_get (p->ast, &ac, (void***) &av); + for (i = 3, j = mark; j < asize; i++, j++) { + ASSERT_BOUNDS (i, 3+new); + ASSERT_BOUNDS (j, ac); + ov [i] = av [j]; + } + ASSERT (i == 3+new, "Reduction result incomplete"); + newsv = Tcl_NewListObj (3+new, ov); + TRACE (("rde_param_i_value_reduce => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + ckfree ((char*) ov); + } + static int + er_int_compare (const void* a, const void* b) + { + long int ai = *((long int*) a); + long int bi = *((long int*) b); + if (ai < bi) { return -1; } + if (ai > bi) { return 1; } + return 0; + } + SCOPE int + rde_param_i_symbol_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE void + rde_param_i_symbol_done_d_reduce (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_reduce (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_d_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_symbol_done_d_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_next_char (RDE_PARAM p, char* c, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_char (p, c, m); + } + SCOPE void + rde_param_i_next_range (RDE_PARAM p, char* s, char* e, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_range (p, s, e, m); + } + SCOPE void + rde_param_i_next_alnum (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alnum (p); + } + SCOPE void + rde_param_i_next_alpha (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alpha (p); + } + SCOPE void + rde_param_i_next_ascii (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ascii (p); + } + SCOPE void + rde_param_i_next_control (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_control (p); + } + SCOPE void + rde_param_i_next_ddigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ddigit (p); + } + SCOPE void + rde_param_i_next_digit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_digit (p); + } + SCOPE void + rde_param_i_next_graph (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_graph (p); + } + SCOPE void + rde_param_i_next_lower (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_lower (p); + } + SCOPE void + rde_param_i_next_print (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_print (p); + } + SCOPE void + rde_param_i_next_punct (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_punct (p); + } + SCOPE void + rde_param_i_next_space (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_space (p); + } + SCOPE void + rde_param_i_next_upper (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_upper (p); + } + SCOPE void + rde_param_i_next_wordchar (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_wordchar (p); + } + SCOPE void + rde_param_i_next_xdigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_xdigit (p); + } + SCOPE void + rde_param_i_notahead_start_d (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_notahead_exit_d (RDE_PARAM p) + { + if (p->ST) { + rde_param_i_ast_pop_rewind (p); + } else { + rde_stack_pop (p->mark, 1); + } + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_notahead_exit (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_state_push_2 (RDE_PARAM p) + { + + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + SCOPE void + rde_param_i_state_push_void (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_push_value (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_merge_ok (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } + SCOPE int + rde_param_i_kleene_close (RDE_PARAM p) + { + int stop = !p->ST; + rde_param_i_error_pop_merge (p); + if (stop) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_kleene_abort (RDE_PARAM p) + { + int stop = !p->ST; + if (stop) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_seq_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_bra_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE void + rde_param_i_next_str (RDE_PARAM p, const char* str, int m) + { + int at = p->CL; + + while (*str) { + rde_param_i_input_next (p, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + rde_param_i_test_char (p, str, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + str = Tcl_UtfNext (str); + } + } + SCOPE void + rde_param_i_next_class (RDE_PARAM p, const char* class, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + while (*class) { + p->ST = Tcl_UtfNcmp (p->CC, class, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + return; + } + class = Tcl_UtfNext (class); + } + error_set (p, m); + p->CL --; + } + + + /* + * Declaring the parse functions + */ + + static void sym_Expression (RDE_PARAM p); + static void sym_Function (RDE_PARAM p); + static void sequence_9 (RDE_PARAM p); + static void sym_Sinus (RDE_PARAM p); + + /* + * Precomputed table of strings (symbols, error messages, etc.). + */ + + static char const* p_string [22] = { + /* 0 = */ "alnum", + /* 1 = */ "alpha", + /* 2 = */ "ascii", + /* 3 = */ "control", + /* 4 = */ "ddigit", + /* 5 = */ "digit", + /* 6 = */ "graph", + /* 7 = */ "lower", + /* 8 = */ "print", + /* 9 = */ "punct", + /* 10 = */ "space", + /* 11 = */ "upper", + /* 12 = */ "wordchar", + /* 13 = */ "xdigit", + /* 14 = */ "n Expression", + /* 15 = */ "Expression", + /* 16 = */ "n Function", + /* 17 = */ "Function", + /* 18 = */ "str sin\50", + /* 19 = */ "t \51", + /* 20 = */ "n Sinus", + /* 21 = */ "Sinus" + }; + + /* + * Grammar Start Expression + */ + + static void MAIN (RDE_PARAM p) { + sym_Expression (p); + return; + } + + /* + * value Symbol 'Expression' + */ + + static void sym_Expression (RDE_PARAM p) { + /* + * (Function) + */ + + if (rde_param_i_symbol_start_d (p, 15)) return ; + sym_Function (p); + rde_param_i_symbol_done_d_reduce (p, 15, 14); + return; + } + + /* + * value Symbol 'Function' + */ + + static void sym_Function (RDE_PARAM p) { + /* + * (Sinus) + */ + + if (rde_param_i_symbol_start_d (p, 17)) return ; + sym_Sinus (p); + rde_param_i_symbol_done_d_reduce (p, 17, 16); + return; + } + + /* + * value Symbol 'Sinus' + */ + + static void sym_Sinus (RDE_PARAM p) { + /* + * x + * "sin\(" + * (Expression) + * '\)' + */ + + if (rde_param_i_symbol_start_d (p, 21)) return ; + sequence_9 (p); + rde_param_i_symbol_done_d_reduce (p, 21, 20); + return; + } + + static void sequence_9 (RDE_PARAM p) { + /* + * x + * "sin\(" + * (Expression) + * '\)' + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "sin\50", 18); + if (rde_param_i_seq_void2value(p)) return; + sym_Expression (p); + if (rde_param_i_seq_value2value(p)) return; + rde_param_i_next_char (p, "\51", 19); + rde_param_i_state_merge_value (p); + return; + } + + /* -*- c -*- */ + + typedef struct PARSERg { + long int counter; + char buf [50]; + } PARSERg; + + static void + PARSERgRelease (ClientData cd, Tcl_Interp* interp) + { + ckfree((char*) cd); + } + + static const char* + PARSERnewName (Tcl_Interp* interp) + { +#define KEY "tcllib/parser/PACKAGE/TEA" + + Tcl_InterpDeleteProc* proc = PARSERgRelease; + PARSERg* parserg; + + parserg = Tcl_GetAssocData (interp, KEY, &proc); + if (parserg == NULL) { + parserg = (PARSERg*) ckalloc (sizeof (PARSERg)); + parserg->counter = 0; + + Tcl_SetAssocData (interp, KEY, proc, + (ClientData) parserg); + } + + parserg->counter ++; + sprintf (parserg->buf, "PARSER%d", parserg->counter); + return parserg->buf; +#undef KEY + } + + static void + PARSERdeleteCmd (ClientData clientData) + { + /* + * Release the whole PARSER + * (Low-level engine only actually). + */ + rde_param_del ((RDE_PARAM) clientData); + } + + + /* * ** *** ***** ******** ************* + ** Functions implementing the object methods, and helper. + */ + + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp); + + static int parser_PARSE (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + int mode; + Tcl_Channel chan; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "chan"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, + Tcl_GetString (objv[2]), + &mode); + + if (!chan) { + return TCL_ERROR; + } + + rde_param_reset (p, chan); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + static int parser_PARSET (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + char* buf; + int len; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "text"); + return TCL_ERROR; + } + + buf = Tcl_GetStringFromObj (objv[2], &len); + + rde_param_reset (p, NULL); + rde_param_data (p, buf, len); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + /* See also rde_critcl/m.c, param_COMPLETE() */ + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp) + { + if (rde_param_query_st (p)) { + long int ac; + Tcl_Obj** av; + + rde_param_query_ast (p, &ac, &av); + + if (ac > 1) { + Tcl_Obj** lv = NALLOC (3+ac, Tcl_Obj*); + + memcpy(lv + 3, av, ac * sizeof (Tcl_Obj*)); + lv [0] = Tcl_NewObj (); + lv [1] = Tcl_NewIntObj (1 + rde_param_query_lstop (p)); + lv [2] = Tcl_NewIntObj (rde_param_query_cl (p)); + + Tcl_SetObjResult (interp, Tcl_NewListObj (3, lv)); + ckfree ((char*) lv); + + } else if (ac == 0) { + /* + * Match, but no AST. This is possible if the grammar + * consists of only the start expression. + */ + Tcl_SetObjResult (interp, Tcl_NewStringObj ("",-1)); + } else { + Tcl_SetObjResult (interp, av [0]); + } + + return TCL_OK; + } else { + Tcl_Obj* xv [1]; + const ERROR_STATE* er = rde_param_query_er (p); + Tcl_Obj* res = rde_param_query_er_tcl (p, er); + /* res = list (location, list(msg)) */ + + /* Stick the exception type-tag before the existing elements */ + xv [0] = Tcl_NewStringObj ("pt::rde",-1); + Tcl_ListObjReplace(interp, res, 0, 0, 1, xv); + + Tcl_SetErrorCode (interp, "PT", "RDE", "SYNTAX", NULL); + Tcl_SetObjResult (interp, res); + return TCL_ERROR; + } + } + + + /* * ** *** ***** ******** ************* + ** Object command, method dispatch. + */ + static int parser_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + RDE_PARAM p = (RDE_PARAM) cd; + int m, res; + + static CONST char* methods [] = { + "destroy", "parse", "parset", NULL + }; + enum methods { + M_DESTROY, M_PARSE, M_PARSET + }; + + if (objc < 2) { + Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option", + 0, &m) != TCL_OK) { + return TCL_ERROR; + } + + /* Dispatch to methods. They check the #args in + * detail before performing the requested + * functionality + */ + + switch (m) { + case M_DESTROY: + if (objc != 2) { + Tcl_WrongNumArgs (interp, 2, objv, NULL); + return TCL_ERROR; + } + + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) rde_param_query_clientdata (p)); + return TCL_OK; + + case M_PARSE: res = parser_PARSE (p, interp, objc, objv); break; + case M_PARSET: res = parser_PARSET (p, interp, objc, objv); break; + default: + /* Not coming to this place */ + ASSERT (0,"Reached unreachable location"); + } + + return res; + } + + /** * ** *** ***** ******** ************* + * Class command, i.e. object construction. + */ + static int ParserClassCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const*objv) { + /* + * Syntax: No arguments beyond the name + */ + + RDE_PARAM parser; + CONST char* name; + Tcl_Obj* fqn; + Tcl_CmdInfo ci; + Tcl_Command c; + +#define USAGE "?name?" + + if ((objc != 2) && (objc != 1)) { + Tcl_WrongNumArgs (interp, 1, objv, USAGE); + return TCL_ERROR; + } + + if (objc < 2) { + name = PARSERnewName (interp); + } else { + name = Tcl_GetString (objv [1]); + } + + if (!Tcl_StringMatch (name, "::*")) { + /* Relative name. Prefix with current namespace */ + + Tcl_Eval (interp, "namespace current"); + fqn = Tcl_GetObjResult (interp); + fqn = Tcl_DuplicateObj (fqn); + Tcl_IncrRefCount (fqn); + + if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { + Tcl_AppendToObj (fqn, "::", -1); + } + Tcl_AppendToObj (fqn, name, -1); + } else { + fqn = Tcl_NewStringObj (name, -1); + Tcl_IncrRefCount (fqn); + } + Tcl_ResetResult (interp); + + if (Tcl_GetCommandInfo (interp, + Tcl_GetString (fqn), + &ci)) { + Tcl_Obj* err; + + err = Tcl_NewObj (); + Tcl_AppendToObj (err, "command \"", -1); + Tcl_AppendObjToObj (err, fqn); + Tcl_AppendToObj (err, "\" already exists", -1); + + Tcl_DecrRefCount (fqn); + Tcl_SetObjResult (interp, err); + return TCL_ERROR; + } + + parser = rde_param_new (sizeof(p_string)/sizeof(char*), (char**) p_string); + c = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), + parser_objcmd, (ClientData) parser, + PARSERdeleteCmd); + rde_param_clientdata (parser, (ClientData) c); + Tcl_SetObjResult (interp, fqn); + Tcl_DecrRefCount (fqn); + return TCL_OK; + } + +int Package_Init(Tcl_Interp* interp) { + if (interp == 0) return TCL_ERROR; + + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + + if (Tcl_CreateObjCommand(interp, "PARSER", ParserClassCmd , NULL, NULL) == NULL) { + Tcl_SetResult(interp, "Can't create constructor", NULL); + return TCL_ERROR; + } + + + Tcl_PkgProvide(interp, "PACKAGE", "0.1"); + + return TCL_OK; +} ADDED modules/pt/tests/data/ok/peg_cparam-tea/2_fun_arithmetic Index: modules/pt/tests/data/ok/peg_cparam-tea/2_fun_arithmetic ================================================================== --- /dev/null +++ modules/pt/tests/data/ok/peg_cparam-tea/2_fun_arithmetic @@ -0,0 +1,2408 @@ +/************************************************************ +** +** TEA-based C/PARAM implementation of the parsing +** expression grammar +** +** TEMPLATE +** +** Generated from file TEST +** for user unknown +** +* * ** *** ***** ******** ************* *********************/ + #include + #include + #include + #include + #define SCOPE static + +#line 1 "rde_critcl/util.h" + + #ifndef _RDE_UTIL_H + #define _RDE_UTIL_H 1 + #ifndef SCOPE + #define SCOPE + #endif + #define ALLOC(type) (type *) ckalloc (sizeof (type)) + #define NALLOC(n,type) (type *) ckalloc ((n) * sizeof (type)) + #undef RDE_DEBUG + #define RDE_DEBUG 1 + #undef RDE_TRACE + #ifdef RDE_DEBUG + #define STOPAFTER(x) { static int count = (x); count --; if (!count) { Tcl_Panic ("stop"); } } + #define XSTR(x) #x + #define STR(x) XSTR(x) + #define RANGEOK(i,n) ((0 <= (i)) && (i < (n))) + #define ASSERT(x,msg) if (!(x)) { Tcl_Panic (msg " (" #x "), in file " __FILE__ " @line " STR(__LINE__));} + #define ASSERT_BOUNDS(i,n) ASSERT (RANGEOK(i,n),"array index out of bounds: " STR(i) " >= " STR(n)) + #else + #define STOPAFTER(x) + #define ASSERT(x,msg) + #define ASSERT_BOUNDS(i,n) + #endif + #ifdef RDE_TRACE + SCOPE void trace_enter (const char* fun); + SCOPE void trace_return (const char *pat, ...); + SCOPE void trace_printf (const char *pat, ...); + #define ENTER(fun) trace_enter (fun) + #define RETURN(format,x) trace_return (format,x) ; return x + #define RETURNVOID trace_return ("%s","(void)") ; return + #define TRACE0(x) trace_printf0 x + #define TRACE(x) trace_printf x + #else + #define ENTER(fun) + #define RETURN(f,x) return x + #define RETURNVOID return + #define TRACE0(x) + #define TRACE(x) + #endif + #endif + + +#line 1 "rde_critcl/stack.h" + + #ifndef _RDE_DS_STACK_H + #define _RDE_DS_STACK_H 1 + typedef void (*RDE_STACK_CELL_FREE) (void* cell); + typedef struct RDE_STACK_* RDE_STACK; + static const int RDE_STACK_INITIAL_SIZE = 256; + #endif + + +#line 1 "rde_critcl/tc.h" + + #ifndef _RDE_DS_TC_H + #define _RDE_DS_TC_H 1 + typedef struct RDE_TC_* RDE_TC; + #endif + + +#line 1 "rde_critcl/param.h" + + #ifndef _RDE_DS_PARAM_H + #define _RDE_DS_PARAM_H 1 + typedef struct RDE_PARAM_* RDE_PARAM; + typedef struct ERROR_STATE { + int refCount; + long int loc; + RDE_STACK msg; + } ERROR_STATE; + typedef struct NC_STATE { + long int CL; + long int ST; + Tcl_Obj* SV; + ERROR_STATE* ER; + } NC_STATE; + #endif + + +#line 1 "rde_critcl/util.c" + + #ifdef RDE_TRACE + typedef struct F_STACK { + const char* str; + struct F_STACK* down; + } F_STACK; + static F_STACK* top = 0; + static int level = 0; + static void + push (const char* str) + { + F_STACK* new = ALLOC (F_STACK); + new->str = str; + new->down = top; + top = new; + level += 4; + } + static void + pop (void) + { + F_STACK* next = top->down; + level -= 4; + ckfree ((char*)top); + top = next; + } + static void + indent (void) + { + int i; + for (i = 0; i < level; i++) { + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + if (top) { + fwrite(top->str, 1, strlen(top->str), stdout); + fflush (stdout); + } + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + SCOPE void + trace_enter (const char* fun) + { + push (fun); + indent(); + fwrite("ENTER\n", 1, 6, stdout); + fflush (stdout); + } + static char msg [1024*1024]; + SCOPE void + trace_return (const char *pat, ...) + { + int len; + va_list args; + indent(); + fwrite("RETURN = ", 1, 9, stdout); + fflush (stdout); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + pop(); + } + SCOPE void + trace_printf (const char *pat, ...) + { + int len; + va_list args; + indent(); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + SCOPE void + trace_printf0 (const char *pat, ...) + { + int len; + va_list args; + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + #endif + + +#line 1 "rde_critcl/stack.c" + + typedef struct RDE_STACK_ { + long int max; + long int top; + RDE_STACK_CELL_FREE freeCellProc; + void** cell; + } RDE_STACK_; + + SCOPE RDE_STACK + rde_stack_new (RDE_STACK_CELL_FREE freeCellProc) + { + RDE_STACK s = ALLOC (RDE_STACK_); + s->cell = NALLOC (RDE_STACK_INITIAL_SIZE, void*); + s->max = RDE_STACK_INITIAL_SIZE; + s->top = 0; + s->freeCellProc = freeCellProc; + return s; + } + SCOPE void + rde_stack_del (RDE_STACK s) + { + if (s->freeCellProc && s->top) { + long int i; + for (i=0; i < s->top; i++) { + ASSERT_BOUNDS(i,s->max); + s->freeCellProc ( s->cell [i] ); + } + } + ckfree ((char*) s->cell); + ckfree ((char*) s); + } + SCOPE void + rde_stack_push (RDE_STACK s, void* item) + { + if (s->top >= s->max) { + long int new = s->max ? (2 * s->max) : RDE_STACK_INITIAL_SIZE; + void** cell = (void**) ckrealloc ((char*) s->cell, new * sizeof(void*)); + ASSERT (cell,"Memory allocation failure for RDE stack"); + s->max = new; + s->cell = cell; + } + ASSERT_BOUNDS(s->top,s->max); + s->cell [s->top] = item; + s->top ++; + } + SCOPE void* + rde_stack_top (RDE_STACK s) + { + ASSERT_BOUNDS(s->top-1,s->max); + return s->cell [s->top - 1]; + } + SCOPE void + rde_stack_pop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + if (s->freeCellProc) { + while (n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + n --; + } + } else { + s->top -= n; + } + } + SCOPE void + rde_stack_trim (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad trimsize"); + if (s->freeCellProc) { + while (s->top > n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + } + } else { + s->top = n; + } + } + SCOPE void + rde_stack_drop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + s->top -= n; + } + SCOPE void + rde_stack_move (RDE_STACK dst, RDE_STACK src) + { + ASSERT (dst->freeCellProc == src->freeCellProc, "Ownership mismatch"); + + while (src->top > 0) { + src->top --; + ASSERT_BOUNDS(src->top,src->max); + rde_stack_push (dst, src->cell [src->top] ); + } + } + SCOPE void + rde_stack_get (RDE_STACK s, long int* cn, void*** cc) + { + *cn = s->top; + *cc = s->cell; + } + SCOPE long int + rde_stack_size (RDE_STACK s) + { + return s->top; + } + + +#line 1 "rde_critcl/tc.c" + + typedef struct RDE_TC_ { + int max; + int num; + char* str; + RDE_STACK off; + } RDE_TC_; + + SCOPE RDE_TC + rde_tc_new (void) + { + RDE_TC tc = ALLOC (RDE_TC_); + tc->max = RDE_STACK_INITIAL_SIZE; + tc->num = 0; + tc->str = NALLOC (RDE_STACK_INITIAL_SIZE, char); + tc->off = rde_stack_new (NULL); + return tc; + } + SCOPE void + rde_tc_del (RDE_TC tc) + { + rde_stack_del (tc->off); + ckfree (tc->str); + ckfree ((char*) tc); + } + SCOPE long int + rde_tc_size (RDE_TC tc) + { + return rde_stack_size (tc->off); + } + SCOPE void + rde_tc_clear (RDE_TC tc) + { + tc->num = 0; + rde_stack_trim (tc->off, 0); + } + SCOPE char* + rde_tc_append (RDE_TC tc, char* string, long int len) + { + long int base = tc->num; + long int off = tc->num; + char* ch; + int clen; + Tcl_UniChar uni; + if (len < 0) { + len = strlen (string); + } + + if (!len) { + return tc->str + base; + } + + if ((tc->num + len) >= tc->max) { + int new = len + (tc->max ? (2 * tc->max) : RDE_STACK_INITIAL_SIZE); + char* str = ckrealloc (tc->str, new * sizeof(char)); + ASSERT (str,"Memory allocation failure for token character array"); + tc->max = new; + tc->str = str; + } + tc->num += len; + ASSERT_BOUNDS(tc->num,tc->max); + ASSERT_BOUNDS(off,tc->max); + ASSERT_BOUNDS(off+len-1,tc->max); + ASSERT_BOUNDS(off+len-1,tc->num); + memcpy (tc->str + off, string, len); + + ch = string; + while (ch < (string + len)) { + ASSERT_BOUNDS(off,tc->num); + rde_stack_push (tc->off, (void*) off); + clen = Tcl_UtfToUniChar (ch, &uni); + off += clen; + ch += clen; + } + return tc->str + base; + } + SCOPE void + rde_tc_get (RDE_TC tc, int at, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + off = ov [at]; + if ((at+1) == oc) { + end = tc->num; + } else { + end = ov [at+1]; + } + TRACE (("rde_tc_get (RDE_TC %p, @ %d) => %d.[%d ... %d]/%d",tc,at,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + SCOPE void + rde_tc_get_s (RDE_TC tc, int at, int last, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + ASSERT_BOUNDS(last,oc); + off = ov [at]; + if ((last+1) == oc) { + end = tc->num; + } else { + end = ov [last+1]; + } + TRACE (("rde_tc_get_s (RDE_TC %p, @ %d .. %d) => %d.[%d ... %d]/%d",tc,at,last,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + + +#line 1 "rde_critcl/param.c" + + typedef struct RDE_PARAM_ { + Tcl_Channel IN; + Tcl_Obj* readbuf; + char* CC; + long int CC_len; + RDE_TC TC; + long int CL; + RDE_STACK LS; + ERROR_STATE* ER; + RDE_STACK ES; + long int ST; + Tcl_Obj* SV; + Tcl_HashTable NC; + + RDE_STACK ast ; + RDE_STACK mark ; + + long int numstr; + char** string; + + ClientData clientData; + } RDE_PARAM_; + typedef int (*UniCharClass) (int); + typedef enum test_class_id { + tc_alnum, + tc_alpha, + tc_ascii, + tc_control, + tc_ddigit, + tc_digit, + tc_graph, + tc_lower, + tc_printable, + tc_punct, + tc_space, + tc_upper, + tc_wordchar, + tc_xdigit + } test_class_id; + static void ast_node_free (void* n); + static void error_state_free (void* es); + static void error_set (RDE_PARAM p, int s); + static void nc_clear (RDE_PARAM p); + static int UniCharIsAscii (int character); + static int UniCharIsHexDigit (int character); + static int UniCharIsDecDigit (int character); + static void test_class (RDE_PARAM p, UniCharClass class, test_class_id id); + static int er_int_compare (const void* a, const void* b); + #define SV_INIT(p) \ + p->SV = NULL; \ + TRACE (("SV_INIT (%p => %p)", (p), (p)->SV)) + #define SV_SET(p,newsv) \ + if (((p)->SV) != (newsv)) { \ + TRACE (("SV_CLEAR/set (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = (newsv); \ + TRACE (("SV_SET (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_IncrRefCount ((p)->SV); \ + } \ + } + #define SV_CLEAR(p) \ + TRACE (("SV_CLEAR (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = NULL + #define ER_INIT(p) \ + p->ER = NULL; \ + TRACE (("ER_INIT (%p => %p)", (p), (p)->ER)) + #define ER_CLEAR(p) \ + error_state_free ((p)->ER); \ + (p)->ER = NULL + SCOPE RDE_PARAM + rde_param_new (long int nstr, char** strings) + { + RDE_PARAM p; + ENTER ("rde_param_new"); + TRACE (("\tINT %d strings @ %p", nstr, strings)); + p = ALLOC (RDE_PARAM_); + p->numstr = nstr; + p->string = strings; + p->readbuf = Tcl_NewObj (); + Tcl_IncrRefCount (p->readbuf); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_InitHashTable (&p->NC, TCL_ONE_WORD_KEYS); + p->IN = NULL; + p->CL = -1; + p->ST = 0; + ER_INIT (p); + SV_INIT (p); + p->CC = NULL; + p->CC_len = 0; + p->TC = rde_tc_new (); + p->ES = rde_stack_new (error_state_free); + p->LS = rde_stack_new (NULL); + p->ast = rde_stack_new (ast_node_free); + p->mark = rde_stack_new (NULL); + RETURN ("%p", p); + } + SCOPE void + rde_param_del (RDE_PARAM p) + { + ENTER ("rde_param_del"); + TRACE (("RDE_PARAM %p",p)); + ER_CLEAR (p); TRACE (("\ter_clear")); + SV_CLEAR (p); TRACE (("\tsv_clear")); + nc_clear (p); TRACE (("\tnc_clear")); + Tcl_DeleteHashTable (&p->NC); TRACE (("\tnc hashtable delete")); + rde_tc_del (p->TC); TRACE (("\ttc clear")); + rde_stack_del (p->ES); TRACE (("\tes clear")); + rde_stack_del (p->LS); TRACE (("\tls clear")); + rde_stack_del (p->ast); TRACE (("\tast clear")); + rde_stack_del (p->mark); TRACE (("\tmark clear")); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_DecrRefCount (p->readbuf); + ckfree ((char*) p); + RETURNVOID; + } + SCOPE void + rde_param_reset (RDE_PARAM p, Tcl_Channel chan) + { + ENTER ("rde_param_reset"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("Tcl_Channel %p",chan)); + p->IN = chan; + p->CL = -1; + p->ST = 0; + p->CC = NULL; + p->CC_len = 0; + ER_CLEAR (p); + SV_CLEAR (p); + nc_clear (p); + rde_tc_clear (p->TC); + rde_stack_trim (p->ES, 0); + rde_stack_trim (p->LS, 0); + rde_stack_trim (p->ast, 0); + rde_stack_trim (p->mark, 0); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + RETURNVOID; + } + SCOPE void + rde_param_update_strings (RDE_PARAM p, long int nstr, char** strings) + { + ENTER ("rde_param_update_strings"); + TRACE (("RDE_PARAM %p", p)); + TRACE (("INT %d strings", nstr)); + p->numstr = nstr; + p->string = strings; + RETURNVOID; + } + SCOPE void + rde_param_data (RDE_PARAM p, char* buf, long int len) + { + (void) rde_tc_append (p->TC, buf, len); + } + SCOPE void + rde_param_clientdata (RDE_PARAM p, ClientData clientData) + { + p->clientData = clientData; + } + static void + nc_clear (RDE_PARAM p) + { + Tcl_HashSearch hs; + Tcl_HashEntry* he; + Tcl_HashTable* tablePtr; + for(he = Tcl_FirstHashEntry(&p->NC, &hs); + he != NULL; + he = Tcl_FirstHashEntry(&p->NC, &hs)) { + Tcl_HashSearch hsc; + Tcl_HashEntry* hec; + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (he); + for(hec = Tcl_FirstHashEntry(tablePtr, &hsc); + hec != NULL; + hec = Tcl_NextHashEntry(&hsc)) { + NC_STATE* scs = Tcl_GetHashValue (hec); + error_state_free (scs->ER); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + ckfree ((char*) scs); + } + Tcl_DeleteHashTable (tablePtr); + ckfree ((char*) tablePtr); + Tcl_DeleteHashEntry (he); + } + } + SCOPE ClientData + rde_param_query_clientdata (RDE_PARAM p) + { + return p->clientData; + } + SCOPE void + rde_param_query_amark (RDE_PARAM p, long int* mc, long int** mv) + { + rde_stack_get (p->mark, mc, (void***) mv); + } + SCOPE void + rde_param_query_ast (RDE_PARAM p, long int* ac, Tcl_Obj*** av) + { + rde_stack_get (p->ast, ac, (void***) av); + } + SCOPE const char* + rde_param_query_in (RDE_PARAM p) + { + return p->IN + ? Tcl_GetChannelName (p->IN) + : ""; + } + SCOPE const char* + rde_param_query_cc (RDE_PARAM p, long int* len) + { + *len = p->CC_len; + return p->CC; + } + SCOPE int + rde_param_query_cl (RDE_PARAM p) + { + return p->CL; + } + SCOPE const ERROR_STATE* + rde_param_query_er (RDE_PARAM p) + { + return p->ER; + } + SCOPE Tcl_Obj* + rde_param_query_er_tcl (RDE_PARAM p, const ERROR_STATE* er) + { + Tcl_Obj* res; + if (!er) { + + res = Tcl_NewStringObj ("", 0); + } else { + Tcl_Obj* ov [2]; + Tcl_Obj** mov; + long int mc, i, j; + long int* mv; + int lastid; + const char* msg; + rde_stack_get (er->msg, &mc, (void***) &mv); + + qsort (mv, mc, sizeof (long int), er_int_compare); + + mov = NALLOC (mc, Tcl_Obj*); + lastid = -1; + for (i=0, j=0; i < mc; i++) { + ASSERT_BOUNDS (i,mc); + if (mv [i] == lastid) continue; + lastid = mv [i]; + ASSERT_BOUNDS(mv[i],p->numstr); + msg = p->string [mv[i]]; + ASSERT_BOUNDS (j,mc); + mov [j] = Tcl_NewStringObj (msg, -1); + j++; + } + + ov [0] = Tcl_NewIntObj (er->loc); + ov [1] = Tcl_NewListObj (j, mov); + res = Tcl_NewListObj (2, ov); + ckfree ((char*) mov); + } + return res; + } + SCOPE void + rde_param_query_es (RDE_PARAM p, long int* ec, ERROR_STATE*** ev) + { + rde_stack_get (p->ES, ec, (void***) ev); + } + SCOPE void + rde_param_query_ls (RDE_PARAM p, long int* lc, void*** lv) + { + rde_stack_get (p->LS, lc, lv); + } + SCOPE long int + rde_param_query_lstop (RDE_PARAM p) + { + (long int) rde_stack_top (p->LS); + } + SCOPE Tcl_HashTable* + rde_param_query_nc (RDE_PARAM p) + { + return &p->NC; + } + SCOPE int + rde_param_query_st (RDE_PARAM p) + { + return p->ST; + } + SCOPE Tcl_Obj* + rde_param_query_sv (RDE_PARAM p) + { + TRACE (("SV_QUERY %p => (%p)", (p), (p)->SV)); \ + return p->SV; + } + SCOPE long int + rde_param_query_tc_size (RDE_PARAM p) + { + return rde_tc_size (p->TC); + } + SCOPE void + rde_param_query_tc_get_s (RDE_PARAM p, long int at, long int last, char** ch, long int* len) + { + rde_tc_get_s (p->TC, at, last, ch, len); + } + SCOPE const char* + rde_param_query_string (RDE_PARAM p, long int id) + { + TRACE (("rde_param_query_string (RDE_PARAM %p, %d/%d)", p, id, p->numstr)); + ASSERT_BOUNDS(id,p->numstr); + return p->string [id]; + } + SCOPE void + rde_param_i_ast_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->mark, 1); + } + SCOPE void + rde_param_i_ast_pop_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_pop_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_push (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_ast_value_push (RDE_PARAM p) + { + ENTER ("rde_param_i_ast_value_push"); + TRACE (("RDE_PARAM %p",p)); + ASSERT(p->SV,"Unable to push undefined semantic value"); + TRACE (("rde_param_i_ast_value_push %p => (%p)", p, p->SV)); + TRACE (("SV = (%p rc%d '%s')", p->SV, p->SV->refCount, Tcl_GetString (p->SV))); + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + RETURNVOID; + } + static void + ast_node_free (void* n) + { + Tcl_DecrRefCount ((Tcl_Obj*) n); + } + SCOPE void + rde_param_i_error_clear (RDE_PARAM p) + { + ER_CLEAR (p); + } + SCOPE void + rde_param_i_error_nonterminal (RDE_PARAM p, int s) + { + + return; + long int pos; + if (!p->ER) return; + pos = 1 + (long int) rde_stack_top (p->LS); + if (p->ER->loc != pos) return; + error_set (p, s); + p->ER->loc = pos; + } + SCOPE void + rde_param_i_error_pop_merge (RDE_PARAM p) + { + ERROR_STATE* top = (ERROR_STATE*) rde_stack_top (p->ES); + + if (top == p->ER) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!top) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!p->ER) { + rde_stack_drop (p->ES, 1); + p->ER = top; + + return; + } + + if (top->loc < p->ER->loc) { + rde_stack_pop (p->ES, 1); + return; + } + + if (top->loc > p->ER->loc) { + rde_stack_drop (p->ES, 1); + error_state_free (p->ER); + p->ER = top; + + return; + } + + rde_stack_move (p->ER->msg, top->msg); + rde_stack_pop (p->ES, 1); + } + SCOPE void + rde_param_i_error_push (RDE_PARAM p) + { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + static void + error_set (RDE_PARAM p, int s) + { + error_state_free (p->ER); + p->ER = ALLOC (ERROR_STATE); + p->ER->refCount = 1; + p->ER->loc = p->CL; + p->ER->msg = rde_stack_new (NULL); + ASSERT_BOUNDS(s,p->numstr); + rde_stack_push (p->ER->msg, (void*) s); + } + static void + error_state_free (void* esx) + { + ERROR_STATE* es = esx; + if (!es) return; + es->refCount --; + if (es->refCount > 0) return; + rde_stack_del (es->msg); + ckfree ((char*) es); + } + SCOPE void + rde_param_i_loc_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_pop_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_push (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + } + SCOPE void + rde_param_i_loc_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + } + SCOPE void + rde_param_i_input_next (RDE_PARAM p, int m) + { + int leni; + char* ch; + ASSERT_BOUNDS(m,p->numstr); + p->CL ++; + if (p->CL < rde_tc_size (p->TC)) { + + rde_tc_get (p->TC, p->CL, &p->CC, &p->CC_len); + ASSERT_BOUNDS (p->CC_len, TCL_UTF_MAX); + p->ST = 1; + ER_CLEAR (p); + return; + } + if (!p->IN || + Tcl_Eof (p->IN) || + (Tcl_ReadChars (p->IN, p->readbuf, 1, 0) <= 0)) { + + p->ST = 0; + error_set (p, m); + return; + } + + ch = Tcl_GetStringFromObj (p->readbuf, &leni); + ASSERT_BOUNDS (leni, TCL_UTF_MAX); + p->CC = rde_tc_append (p->TC, ch, leni); + p->CC_len = leni; + p->ST = 1; + ER_CLEAR (p); + } + SCOPE void + rde_param_i_status_fail (RDE_PARAM p) + { + p->ST = 0; + } + SCOPE void + rde_param_i_status_ok (RDE_PARAM p) + { + p->ST = 1; + } + SCOPE void + rde_param_i_status_negate (RDE_PARAM p) + { + p->ST = !p->ST; + } + SCOPE int + rde_param_i_symbol_restore (RDE_PARAM p, int s) + { + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + + hPtr = Tcl_FindHashEntry (&p->NC, (char*) p->CL); + if (!hPtr) { return 0; } + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + hPtr = Tcl_FindHashEntry (tablePtr, (char*) s); + if (!hPtr) { return 0; } + + scs = Tcl_GetHashValue (hPtr); + p->CL = scs->CL; + p->ST = scs->ST; + error_state_free (p->ER); + p->ER = scs->ER; + if (p->ER) { p->ER->refCount ++; } + TRACE (("SV_RESTORE (%p) '%s'",scs->SV, scs->SV ? Tcl_GetString (scs->SV):"")); + SV_SET (p, scs->SV); + return 1; + } + SCOPE void + rde_param_i_symbol_save (RDE_PARAM p, int s) + { + long int at = (long int) rde_stack_top (p->LS); + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + int isnew; + ENTER ("rde_param_i_symbol_save"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("INT %d",s)); + + hPtr = Tcl_CreateHashEntry (&p->NC, (char*) at, &isnew); + if (isnew) { + tablePtr = ALLOC (Tcl_HashTable); + Tcl_InitHashTable (tablePtr, TCL_ONE_WORD_KEYS); + Tcl_SetHashValue (hPtr, tablePtr); + } else { + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + } + hPtr = Tcl_CreateHashEntry (tablePtr, (char*) s, &isnew); + if (isnew) { + + scs = ALLOC (NC_STATE); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "")); + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + Tcl_SetHashValue (hPtr, scs); + } else { + + scs = (NC_STATE*) Tcl_GetHashValue (hPtr); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE/over (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "" )); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + error_state_free (scs->ER); + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + } + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_test_alnum (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlnum, tc_alnum); + } + SCOPE void + rde_param_i_test_alpha (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlpha, tc_alpha); + } + SCOPE void + rde_param_i_test_ascii (RDE_PARAM p) + { + test_class (p, UniCharIsAscii, tc_ascii); + } + SCOPE void + rde_param_i_test_control (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsControl, tc_control); + } + SCOPE void + rde_param_i_test_char (RDE_PARAM p, const char* c, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = Tcl_UtfNcmp (p->CC, c, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_ddigit (RDE_PARAM p) + { + test_class (p, UniCharIsDecDigit, tc_ddigit); + } + SCOPE void + rde_param_i_test_digit (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsDigit, tc_digit); + } + SCOPE void + rde_param_i_test_graph (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsGraph, tc_graph); + } + SCOPE void + rde_param_i_test_lower (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsLower, tc_lower); + } + SCOPE void + rde_param_i_test_print (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPrint, tc_printable); + } + SCOPE void + rde_param_i_test_punct (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPunct, tc_punct); + } + SCOPE void + rde_param_i_test_range (RDE_PARAM p, char* s, char* e, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = + (Tcl_UtfNcmp (s, p->CC, 1) <= 0) && + (Tcl_UtfNcmp (p->CC, e, 1) <= 0); + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_space (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsSpace, tc_space); + } + SCOPE void + rde_param_i_test_upper (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsUpper, tc_upper); + } + SCOPE void + rde_param_i_test_wordchar (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsWordChar, tc_wordchar); + } + SCOPE void + rde_param_i_test_xdigit (RDE_PARAM p) + { + test_class (p, UniCharIsHexDigit, tc_xdigit); + } + static void + test_class (RDE_PARAM p, UniCharClass class, test_class_id id) + { + Tcl_UniChar ch; + Tcl_UtfToUniChar(p->CC, &ch); + ASSERT_BOUNDS(id,p->numstr); + p->ST = !!class (ch); + + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, id); + p->CL --; + } + } + static int + UniCharIsAscii (int character) + { + return (character >= 0) && (character < 0x80); + } + static int + UniCharIsHexDigit (int character) + { + return (character >= 0) && (character < 0x80) && isxdigit(character); + } + static int + UniCharIsDecDigit (int character) + { + return (character >= 0) && (character < 0x80) && isdigit(character); + } + SCOPE void + rde_param_i_value_clear (RDE_PARAM p) + { + SV_CLEAR (p); + } + SCOPE void + rde_param_i_value_leaf (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + Tcl_Obj* ov [3]; + long int pos = 1 + (long int) rde_stack_top (p->LS); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + newsv = Tcl_NewListObj (3, ov); + TRACE (("rde_param_i_value_leaf => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + } + SCOPE void + rde_param_i_value_reduce (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + int oc, i, j; + Tcl_Obj** ov; + long int ac; + Tcl_Obj** av; + long int pos = 1 + (long int) rde_stack_top (p->LS); + long int mark = (long int) rde_stack_top (p->mark); + long int asize = rde_stack_size (p->ast); + long int new = asize - mark; + ASSERT (new >= 0, "Bad number of elements to reduce"); + ov = NALLOC (3+new, Tcl_Obj*); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + rde_stack_get (p->ast, &ac, (void***) &av); + for (i = 3, j = mark; j < asize; i++, j++) { + ASSERT_BOUNDS (i, 3+new); + ASSERT_BOUNDS (j, ac); + ov [i] = av [j]; + } + ASSERT (i == 3+new, "Reduction result incomplete"); + newsv = Tcl_NewListObj (3+new, ov); + TRACE (("rde_param_i_value_reduce => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + ckfree ((char*) ov); + } + static int + er_int_compare (const void* a, const void* b) + { + long int ai = *((long int*) a); + long int bi = *((long int*) b); + if (ai < bi) { return -1; } + if (ai > bi) { return 1; } + return 0; + } + SCOPE int + rde_param_i_symbol_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE void + rde_param_i_symbol_done_d_reduce (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_reduce (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_d_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_symbol_done_d_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_next_char (RDE_PARAM p, char* c, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_char (p, c, m); + } + SCOPE void + rde_param_i_next_range (RDE_PARAM p, char* s, char* e, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_range (p, s, e, m); + } + SCOPE void + rde_param_i_next_alnum (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alnum (p); + } + SCOPE void + rde_param_i_next_alpha (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alpha (p); + } + SCOPE void + rde_param_i_next_ascii (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ascii (p); + } + SCOPE void + rde_param_i_next_control (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_control (p); + } + SCOPE void + rde_param_i_next_ddigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ddigit (p); + } + SCOPE void + rde_param_i_next_digit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_digit (p); + } + SCOPE void + rde_param_i_next_graph (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_graph (p); + } + SCOPE void + rde_param_i_next_lower (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_lower (p); + } + SCOPE void + rde_param_i_next_print (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_print (p); + } + SCOPE void + rde_param_i_next_punct (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_punct (p); + } + SCOPE void + rde_param_i_next_space (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_space (p); + } + SCOPE void + rde_param_i_next_upper (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_upper (p); + } + SCOPE void + rde_param_i_next_wordchar (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_wordchar (p); + } + SCOPE void + rde_param_i_next_xdigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_xdigit (p); + } + SCOPE void + rde_param_i_notahead_start_d (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_notahead_exit_d (RDE_PARAM p) + { + if (p->ST) { + rde_param_i_ast_pop_rewind (p); + } else { + rde_stack_pop (p->mark, 1); + } + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_notahead_exit (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_state_push_2 (RDE_PARAM p) + { + + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + SCOPE void + rde_param_i_state_push_void (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_push_value (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_merge_ok (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } + SCOPE int + rde_param_i_kleene_close (RDE_PARAM p) + { + int stop = !p->ST; + rde_param_i_error_pop_merge (p); + if (stop) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_kleene_abort (RDE_PARAM p) + { + int stop = !p->ST; + if (stop) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_seq_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_bra_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE void + rde_param_i_next_str (RDE_PARAM p, const char* str, int m) + { + int at = p->CL; + + while (*str) { + rde_param_i_input_next (p, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + rde_param_i_test_char (p, str, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + str = Tcl_UtfNext (str); + } + } + SCOPE void + rde_param_i_next_class (RDE_PARAM p, const char* class, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + while (*class) { + p->ST = Tcl_UtfNcmp (p->CC, class, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + return; + } + class = Tcl_UtfNext (class); + } + error_set (p, m); + p->CL --; + } + + + /* + * Declaring the parse functions + */ + + static void sym_AddOp (RDE_PARAM p); + static void sym_Digit (RDE_PARAM p); + static void sequence_10 (RDE_PARAM p); + static void sequence_15 (RDE_PARAM p); + static void kleene_17 (RDE_PARAM p); + static void sequence_19 (RDE_PARAM p); + static void choice_21 (RDE_PARAM p); + static void sym_Expression (RDE_PARAM p); + static void sequence_27 (RDE_PARAM p); + static void kleene_29 (RDE_PARAM p); + static void sequence_31 (RDE_PARAM p); + static void sym_Factor (RDE_PARAM p); + static void sym_Function (RDE_PARAM p); + static void sym_MulOp (RDE_PARAM p); + static void optional_39 (RDE_PARAM p); + static void poskleene_42 (RDE_PARAM p); + static void sequence_44 (RDE_PARAM p); + static void sym_Number (RDE_PARAM p); + static void sym_Sign (RDE_PARAM p); + static void sequence_52 (RDE_PARAM p); + static void sym_Sinus (RDE_PARAM p); + static void sym_Term (RDE_PARAM p); + + /* + * Precomputed table of strings (symbols, error messages, etc.). + */ + + static char const* p_string [40] = { + /* 0 = */ "alnum", + /* 1 = */ "alpha", + /* 2 = */ "ascii", + /* 3 = */ "control", + /* 4 = */ "ddigit", + /* 5 = */ "digit", + /* 6 = */ "graph", + /* 7 = */ "lower", + /* 8 = */ "print", + /* 9 = */ "punct", + /* 10 = */ "space", + /* 11 = */ "upper", + /* 12 = */ "wordchar", + /* 13 = */ "xdigit", + /* 14 = */ "cl -+", + /* 15 = */ "n AddOp", + /* 16 = */ "AddOp", + /* 17 = */ "cl 0123456789", + /* 18 = */ "n Digit", + /* 19 = */ "Digit", + /* 20 = */ "t \50", + /* 21 = */ "t \51", + /* 22 = */ "n Expression", + /* 23 = */ "Expression", + /* 24 = */ "n Factor", + /* 25 = */ "Factor", + /* 26 = */ "n Function", + /* 27 = */ "Function", + /* 28 = */ "cl */", + /* 29 = */ "n MulOp", + /* 30 = */ "MulOp", + /* 31 = */ "n Number", + /* 32 = */ "Number", + /* 33 = */ "n Sign", + /* 34 = */ "Sign", + /* 35 = */ "str sin\50", + /* 36 = */ "n Sinus", + /* 37 = */ "Sinus", + /* 38 = */ "n Term", + /* 39 = */ "Term" + }; + + /* + * Grammar Start Expression + */ + + static void MAIN (RDE_PARAM p) { + sym_Expression (p); + return; + } + + /* + * value Symbol 'AddOp' + */ + + static void sym_AddOp (RDE_PARAM p) { + /* + * [-+] + */ + + if (rde_param_i_symbol_start (p, 16)) return ; + rde_param_i_next_class (p, "-+", 14); + rde_param_i_symbol_done_leaf (p, 16, 15); + return; + } + + /* + * value Symbol 'Digit' + */ + + static void sym_Digit (RDE_PARAM p) { + /* + * [0123456789] + */ + + if (rde_param_i_symbol_start (p, 19)) return ; + rde_param_i_next_class (p, "0123456789", 17); + rde_param_i_symbol_done_leaf (p, 19, 18); + return; + } + + /* + * value Symbol 'Expression' + */ + + static void sym_Expression (RDE_PARAM p) { + /* + * / + * (Function) + * x + * '\(' + * (Expression) + * '\)' + * x + * (Factor) + * * + * x + * (MulOp) + * (Factor) + */ + + if (rde_param_i_symbol_start_d (p, 23)) return ; + choice_21 (p); + rde_param_i_symbol_done_d_reduce (p, 23, 22); + return; + } + + static void choice_21 (RDE_PARAM p) { + /* + * / + * (Function) + * x + * '\(' + * (Expression) + * '\)' + * x + * (Factor) + * * + * x + * (MulOp) + * (Factor) + */ + + rde_param_i_state_push_value (p); + sym_Function (p); + if (rde_param_i_bra_value2value(p)) return; + sequence_10 (p); + if (rde_param_i_bra_value2value(p)) return; + sequence_19 (p); + rde_param_i_state_merge_value (p); + return; + } + + static void sequence_10 (RDE_PARAM p) { + /* + * x + * '\(' + * (Expression) + * '\)' + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "\50", 20); + if (rde_param_i_seq_void2value(p)) return; + sym_Expression (p); + if (rde_param_i_seq_value2value(p)) return; + rde_param_i_next_char (p, "\51", 21); + rde_param_i_state_merge_value (p); + return; + } + + static void sequence_19 (RDE_PARAM p) { + /* + * x + * (Factor) + * * + * x + * (MulOp) + * (Factor) + */ + + rde_param_i_state_push_value (p); + sym_Factor (p); + if (rde_param_i_seq_value2value(p)) return; + kleene_17 (p); + rde_param_i_state_merge_value (p); + return; + } + + static void kleene_17 (RDE_PARAM p) { + /* + * * + * x + * (MulOp) + * (Factor) + */ + + while (1) { + rde_param_i_state_push_2 (p); + sequence_15 (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + static void sequence_15 (RDE_PARAM p) { + /* + * x + * (MulOp) + * (Factor) + */ + + rde_param_i_state_push_value (p); + sym_MulOp (p); + if (rde_param_i_seq_value2value(p)) return; + sym_Factor (p); + rde_param_i_state_merge_value (p); + return; + } + + /* + * value Symbol 'Factor' + */ + + static void sym_Factor (RDE_PARAM p) { + /* + * x + * (Term) + * * + * x + * (AddOp) + * (Term) + */ + + if (rde_param_i_symbol_start_d (p, 25)) return ; + sequence_31 (p); + rde_param_i_symbol_done_d_reduce (p, 25, 24); + return; + } + + static void sequence_31 (RDE_PARAM p) { + /* + * x + * (Term) + * * + * x + * (AddOp) + * (Term) + */ + + rde_param_i_state_push_value (p); + sym_Term (p); + if (rde_param_i_seq_value2value(p)) return; + kleene_29 (p); + rde_param_i_state_merge_value (p); + return; + } + + static void kleene_29 (RDE_PARAM p) { + /* + * * + * x + * (AddOp) + * (Term) + */ + + while (1) { + rde_param_i_state_push_2 (p); + sequence_27 (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + static void sequence_27 (RDE_PARAM p) { + /* + * x + * (AddOp) + * (Term) + */ + + rde_param_i_state_push_value (p); + sym_AddOp (p); + if (rde_param_i_seq_value2value(p)) return; + sym_Term (p); + rde_param_i_state_merge_value (p); + return; + } + + /* + * value Symbol 'Function' + */ + + static void sym_Function (RDE_PARAM p) { + /* + * (Sinus) + */ + + if (rde_param_i_symbol_start_d (p, 27)) return ; + sym_Sinus (p); + rde_param_i_symbol_done_d_reduce (p, 27, 26); + return; + } + + /* + * value Symbol 'MulOp' + */ + + static void sym_MulOp (RDE_PARAM p) { + /* + * [\u002a\u002f] + */ + + if (rde_param_i_symbol_start (p, 30)) return ; + rde_param_i_next_class (p, "*/", 28); + rde_param_i_symbol_done_leaf (p, 30, 29); + return; + } + + /* + * value Symbol 'Number' + */ + + static void sym_Number (RDE_PARAM p) { + /* + * x + * ? + * (Sign) + * + + * (Digit) + */ + + if (rde_param_i_symbol_start_d (p, 32)) return ; + sequence_44 (p); + rde_param_i_symbol_done_d_reduce (p, 32, 31); + return; + } + + static void sequence_44 (RDE_PARAM p) { + /* + * x + * ? + * (Sign) + * + + * (Digit) + */ + + rde_param_i_state_push_value (p); + optional_39 (p); + if (rde_param_i_seq_value2value(p)) return; + poskleene_42 (p); + rde_param_i_state_merge_value (p); + return; + } + + static void optional_39 (RDE_PARAM p) { + /* + * ? + * (Sign) + */ + + rde_param_i_state_push_2 (p); + sym_Sign (p); + rde_param_i_state_merge_ok (p); + return; + } + + static void poskleene_42 (RDE_PARAM p) { + /* + * + + * (Digit) + */ + + rde_param_i_loc_push (p); + sym_Digit (p); + if (rde_param_i_kleene_abort(p)) return; + while (1) { + rde_param_i_state_push_2 (p); + sym_Digit (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + /* + * value Symbol 'Sign' + */ + + static void sym_Sign (RDE_PARAM p) { + /* + * [-+] + */ + + if (rde_param_i_symbol_start (p, 34)) return ; + rde_param_i_next_class (p, "-+", 14); + rde_param_i_symbol_done_leaf (p, 34, 33); + return; + } + + /* + * value Symbol 'Sinus' + */ + + static void sym_Sinus (RDE_PARAM p) { + /* + * x + * "sin\(" + * (Expression) + * '\)' + */ + + if (rde_param_i_symbol_start_d (p, 37)) return ; + sequence_52 (p); + rde_param_i_symbol_done_d_reduce (p, 37, 36); + return; + } + + static void sequence_52 (RDE_PARAM p) { + /* + * x + * "sin\(" + * (Expression) + * '\)' + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "sin\50", 35); + if (rde_param_i_seq_void2value(p)) return; + sym_Expression (p); + if (rde_param_i_seq_value2value(p)) return; + rde_param_i_next_char (p, "\51", 21); + rde_param_i_state_merge_value (p); + return; + } + + /* + * value Symbol 'Term' + */ + + static void sym_Term (RDE_PARAM p) { + /* + * (Number) + */ + + if (rde_param_i_symbol_start_d (p, 39)) return ; + sym_Number (p); + rde_param_i_symbol_done_d_reduce (p, 39, 38); + return; + } + + /* -*- c -*- */ + + typedef struct PARSERg { + long int counter; + char buf [50]; + } PARSERg; + + static void + PARSERgRelease (ClientData cd, Tcl_Interp* interp) + { + ckfree((char*) cd); + } + + static const char* + PARSERnewName (Tcl_Interp* interp) + { +#define KEY "tcllib/parser/PACKAGE/TEA" + + Tcl_InterpDeleteProc* proc = PARSERgRelease; + PARSERg* parserg; + + parserg = Tcl_GetAssocData (interp, KEY, &proc); + if (parserg == NULL) { + parserg = (PARSERg*) ckalloc (sizeof (PARSERg)); + parserg->counter = 0; + + Tcl_SetAssocData (interp, KEY, proc, + (ClientData) parserg); + } + + parserg->counter ++; + sprintf (parserg->buf, "PARSER%d", parserg->counter); + return parserg->buf; +#undef KEY + } + + static void + PARSERdeleteCmd (ClientData clientData) + { + /* + * Release the whole PARSER + * (Low-level engine only actually). + */ + rde_param_del ((RDE_PARAM) clientData); + } + + + /* * ** *** ***** ******** ************* + ** Functions implementing the object methods, and helper. + */ + + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp); + + static int parser_PARSE (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + int mode; + Tcl_Channel chan; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "chan"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, + Tcl_GetString (objv[2]), + &mode); + + if (!chan) { + return TCL_ERROR; + } + + rde_param_reset (p, chan); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + static int parser_PARSET (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + char* buf; + int len; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "text"); + return TCL_ERROR; + } + + buf = Tcl_GetStringFromObj (objv[2], &len); + + rde_param_reset (p, NULL); + rde_param_data (p, buf, len); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + /* See also rde_critcl/m.c, param_COMPLETE() */ + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp) + { + if (rde_param_query_st (p)) { + long int ac; + Tcl_Obj** av; + + rde_param_query_ast (p, &ac, &av); + + if (ac > 1) { + Tcl_Obj** lv = NALLOC (3+ac, Tcl_Obj*); + + memcpy(lv + 3, av, ac * sizeof (Tcl_Obj*)); + lv [0] = Tcl_NewObj (); + lv [1] = Tcl_NewIntObj (1 + rde_param_query_lstop (p)); + lv [2] = Tcl_NewIntObj (rde_param_query_cl (p)); + + Tcl_SetObjResult (interp, Tcl_NewListObj (3, lv)); + ckfree ((char*) lv); + + } else if (ac == 0) { + /* + * Match, but no AST. This is possible if the grammar + * consists of only the start expression. + */ + Tcl_SetObjResult (interp, Tcl_NewStringObj ("",-1)); + } else { + Tcl_SetObjResult (interp, av [0]); + } + + return TCL_OK; + } else { + Tcl_Obj* xv [1]; + const ERROR_STATE* er = rde_param_query_er (p); + Tcl_Obj* res = rde_param_query_er_tcl (p, er); + /* res = list (location, list(msg)) */ + + /* Stick the exception type-tag before the existing elements */ + xv [0] = Tcl_NewStringObj ("pt::rde",-1); + Tcl_ListObjReplace(interp, res, 0, 0, 1, xv); + + Tcl_SetErrorCode (interp, "PT", "RDE", "SYNTAX", NULL); + Tcl_SetObjResult (interp, res); + return TCL_ERROR; + } + } + + + /* * ** *** ***** ******** ************* + ** Object command, method dispatch. + */ + static int parser_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + RDE_PARAM p = (RDE_PARAM) cd; + int m, res; + + static CONST char* methods [] = { + "destroy", "parse", "parset", NULL + }; + enum methods { + M_DESTROY, M_PARSE, M_PARSET + }; + + if (objc < 2) { + Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option", + 0, &m) != TCL_OK) { + return TCL_ERROR; + } + + /* Dispatch to methods. They check the #args in + * detail before performing the requested + * functionality + */ + + switch (m) { + case M_DESTROY: + if (objc != 2) { + Tcl_WrongNumArgs (interp, 2, objv, NULL); + return TCL_ERROR; + } + + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) rde_param_query_clientdata (p)); + return TCL_OK; + + case M_PARSE: res = parser_PARSE (p, interp, objc, objv); break; + case M_PARSET: res = parser_PARSET (p, interp, objc, objv); break; + default: + /* Not coming to this place */ + ASSERT (0,"Reached unreachable location"); + } + + return res; + } + + /** * ** *** ***** ******** ************* + * Class command, i.e. object construction. + */ + static int ParserClassCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const*objv) { + /* + * Syntax: No arguments beyond the name + */ + + RDE_PARAM parser; + CONST char* name; + Tcl_Obj* fqn; + Tcl_CmdInfo ci; + Tcl_Command c; + +#define USAGE "?name?" + + if ((objc != 2) && (objc != 1)) { + Tcl_WrongNumArgs (interp, 1, objv, USAGE); + return TCL_ERROR; + } + + if (objc < 2) { + name = PARSERnewName (interp); + } else { + name = Tcl_GetString (objv [1]); + } + + if (!Tcl_StringMatch (name, "::*")) { + /* Relative name. Prefix with current namespace */ + + Tcl_Eval (interp, "namespace current"); + fqn = Tcl_GetObjResult (interp); + fqn = Tcl_DuplicateObj (fqn); + Tcl_IncrRefCount (fqn); + + if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { + Tcl_AppendToObj (fqn, "::", -1); + } + Tcl_AppendToObj (fqn, name, -1); + } else { + fqn = Tcl_NewStringObj (name, -1); + Tcl_IncrRefCount (fqn); + } + Tcl_ResetResult (interp); + + if (Tcl_GetCommandInfo (interp, + Tcl_GetString (fqn), + &ci)) { + Tcl_Obj* err; + + err = Tcl_NewObj (); + Tcl_AppendToObj (err, "command \"", -1); + Tcl_AppendObjToObj (err, fqn); + Tcl_AppendToObj (err, "\" already exists", -1); + + Tcl_DecrRefCount (fqn); + Tcl_SetObjResult (interp, err); + return TCL_ERROR; + } + + parser = rde_param_new (sizeof(p_string)/sizeof(char*), (char**) p_string); + c = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), + parser_objcmd, (ClientData) parser, + PARSERdeleteCmd); + rde_param_clientdata (parser, (ClientData) c); + Tcl_SetObjResult (interp, fqn); + Tcl_DecrRefCount (fqn); + return TCL_OK; + } + +int Package_Init(Tcl_Interp* interp) { + if (interp == 0) return TCL_ERROR; + + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + + if (Tcl_CreateObjCommand(interp, "PARSER", ParserClassCmd , NULL, NULL) == NULL) { + Tcl_SetResult(interp, "Can't create constructor", NULL); + return TCL_ERROR; + } + + + Tcl_PkgProvide(interp, "PACKAGE", "0.1"); + + return TCL_OK; +} ADDED modules/pt/tests/data/ok/peg_cparam-tea/3_peg_itself Index: modules/pt/tests/data/ok/peg_cparam-tea/3_peg_itself ================================================================== --- /dev/null +++ modules/pt/tests/data/ok/peg_cparam-tea/3_peg_itself @@ -0,0 +1,4947 @@ +/************************************************************ +** +** TEA-based C/PARAM implementation of the parsing +** expression grammar +** +** TEMPLATE +** +** Generated from file TEST +** for user unknown +** +* * ** *** ***** ******** ************* *********************/ + #include + #include + #include + #include + #define SCOPE static + +#line 1 "rde_critcl/util.h" + + #ifndef _RDE_UTIL_H + #define _RDE_UTIL_H 1 + #ifndef SCOPE + #define SCOPE + #endif + #define ALLOC(type) (type *) ckalloc (sizeof (type)) + #define NALLOC(n,type) (type *) ckalloc ((n) * sizeof (type)) + #undef RDE_DEBUG + #define RDE_DEBUG 1 + #undef RDE_TRACE + #ifdef RDE_DEBUG + #define STOPAFTER(x) { static int count = (x); count --; if (!count) { Tcl_Panic ("stop"); } } + #define XSTR(x) #x + #define STR(x) XSTR(x) + #define RANGEOK(i,n) ((0 <= (i)) && (i < (n))) + #define ASSERT(x,msg) if (!(x)) { Tcl_Panic (msg " (" #x "), in file " __FILE__ " @line " STR(__LINE__));} + #define ASSERT_BOUNDS(i,n) ASSERT (RANGEOK(i,n),"array index out of bounds: " STR(i) " >= " STR(n)) + #else + #define STOPAFTER(x) + #define ASSERT(x,msg) + #define ASSERT_BOUNDS(i,n) + #endif + #ifdef RDE_TRACE + SCOPE void trace_enter (const char* fun); + SCOPE void trace_return (const char *pat, ...); + SCOPE void trace_printf (const char *pat, ...); + #define ENTER(fun) trace_enter (fun) + #define RETURN(format,x) trace_return (format,x) ; return x + #define RETURNVOID trace_return ("%s","(void)") ; return + #define TRACE0(x) trace_printf0 x + #define TRACE(x) trace_printf x + #else + #define ENTER(fun) + #define RETURN(f,x) return x + #define RETURNVOID return + #define TRACE0(x) + #define TRACE(x) + #endif + #endif + + +#line 1 "rde_critcl/stack.h" + + #ifndef _RDE_DS_STACK_H + #define _RDE_DS_STACK_H 1 + typedef void (*RDE_STACK_CELL_FREE) (void* cell); + typedef struct RDE_STACK_* RDE_STACK; + static const int RDE_STACK_INITIAL_SIZE = 256; + #endif + + +#line 1 "rde_critcl/tc.h" + + #ifndef _RDE_DS_TC_H + #define _RDE_DS_TC_H 1 + typedef struct RDE_TC_* RDE_TC; + #endif + + +#line 1 "rde_critcl/param.h" + + #ifndef _RDE_DS_PARAM_H + #define _RDE_DS_PARAM_H 1 + typedef struct RDE_PARAM_* RDE_PARAM; + typedef struct ERROR_STATE { + int refCount; + long int loc; + RDE_STACK msg; + } ERROR_STATE; + typedef struct NC_STATE { + long int CL; + long int ST; + Tcl_Obj* SV; + ERROR_STATE* ER; + } NC_STATE; + #endif + + +#line 1 "rde_critcl/util.c" + + #ifdef RDE_TRACE + typedef struct F_STACK { + const char* str; + struct F_STACK* down; + } F_STACK; + static F_STACK* top = 0; + static int level = 0; + static void + push (const char* str) + { + F_STACK* new = ALLOC (F_STACK); + new->str = str; + new->down = top; + top = new; + level += 4; + } + static void + pop (void) + { + F_STACK* next = top->down; + level -= 4; + ckfree ((char*)top); + top = next; + } + static void + indent (void) + { + int i; + for (i = 0; i < level; i++) { + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + if (top) { + fwrite(top->str, 1, strlen(top->str), stdout); + fflush (stdout); + } + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + SCOPE void + trace_enter (const char* fun) + { + push (fun); + indent(); + fwrite("ENTER\n", 1, 6, stdout); + fflush (stdout); + } + static char msg [1024*1024]; + SCOPE void + trace_return (const char *pat, ...) + { + int len; + va_list args; + indent(); + fwrite("RETURN = ", 1, 9, stdout); + fflush (stdout); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + pop(); + } + SCOPE void + trace_printf (const char *pat, ...) + { + int len; + va_list args; + indent(); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + SCOPE void + trace_printf0 (const char *pat, ...) + { + int len; + va_list args; + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + #endif + + +#line 1 "rde_critcl/stack.c" + + typedef struct RDE_STACK_ { + long int max; + long int top; + RDE_STACK_CELL_FREE freeCellProc; + void** cell; + } RDE_STACK_; + + SCOPE RDE_STACK + rde_stack_new (RDE_STACK_CELL_FREE freeCellProc) + { + RDE_STACK s = ALLOC (RDE_STACK_); + s->cell = NALLOC (RDE_STACK_INITIAL_SIZE, void*); + s->max = RDE_STACK_INITIAL_SIZE; + s->top = 0; + s->freeCellProc = freeCellProc; + return s; + } + SCOPE void + rde_stack_del (RDE_STACK s) + { + if (s->freeCellProc && s->top) { + long int i; + for (i=0; i < s->top; i++) { + ASSERT_BOUNDS(i,s->max); + s->freeCellProc ( s->cell [i] ); + } + } + ckfree ((char*) s->cell); + ckfree ((char*) s); + } + SCOPE void + rde_stack_push (RDE_STACK s, void* item) + { + if (s->top >= s->max) { + long int new = s->max ? (2 * s->max) : RDE_STACK_INITIAL_SIZE; + void** cell = (void**) ckrealloc ((char*) s->cell, new * sizeof(void*)); + ASSERT (cell,"Memory allocation failure for RDE stack"); + s->max = new; + s->cell = cell; + } + ASSERT_BOUNDS(s->top,s->max); + s->cell [s->top] = item; + s->top ++; + } + SCOPE void* + rde_stack_top (RDE_STACK s) + { + ASSERT_BOUNDS(s->top-1,s->max); + return s->cell [s->top - 1]; + } + SCOPE void + rde_stack_pop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + if (s->freeCellProc) { + while (n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + n --; + } + } else { + s->top -= n; + } + } + SCOPE void + rde_stack_trim (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad trimsize"); + if (s->freeCellProc) { + while (s->top > n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + } + } else { + s->top = n; + } + } + SCOPE void + rde_stack_drop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + s->top -= n; + } + SCOPE void + rde_stack_move (RDE_STACK dst, RDE_STACK src) + { + ASSERT (dst->freeCellProc == src->freeCellProc, "Ownership mismatch"); + + while (src->top > 0) { + src->top --; + ASSERT_BOUNDS(src->top,src->max); + rde_stack_push (dst, src->cell [src->top] ); + } + } + SCOPE void + rde_stack_get (RDE_STACK s, long int* cn, void*** cc) + { + *cn = s->top; + *cc = s->cell; + } + SCOPE long int + rde_stack_size (RDE_STACK s) + { + return s->top; + } + + +#line 1 "rde_critcl/tc.c" + + typedef struct RDE_TC_ { + int max; + int num; + char* str; + RDE_STACK off; + } RDE_TC_; + + SCOPE RDE_TC + rde_tc_new (void) + { + RDE_TC tc = ALLOC (RDE_TC_); + tc->max = RDE_STACK_INITIAL_SIZE; + tc->num = 0; + tc->str = NALLOC (RDE_STACK_INITIAL_SIZE, char); + tc->off = rde_stack_new (NULL); + return tc; + } + SCOPE void + rde_tc_del (RDE_TC tc) + { + rde_stack_del (tc->off); + ckfree (tc->str); + ckfree ((char*) tc); + } + SCOPE long int + rde_tc_size (RDE_TC tc) + { + return rde_stack_size (tc->off); + } + SCOPE void + rde_tc_clear (RDE_TC tc) + { + tc->num = 0; + rde_stack_trim (tc->off, 0); + } + SCOPE char* + rde_tc_append (RDE_TC tc, char* string, long int len) + { + long int base = tc->num; + long int off = tc->num; + char* ch; + int clen; + Tcl_UniChar uni; + if (len < 0) { + len = strlen (string); + } + + if (!len) { + return tc->str + base; + } + + if ((tc->num + len) >= tc->max) { + int new = len + (tc->max ? (2 * tc->max) : RDE_STACK_INITIAL_SIZE); + char* str = ckrealloc (tc->str, new * sizeof(char)); + ASSERT (str,"Memory allocation failure for token character array"); + tc->max = new; + tc->str = str; + } + tc->num += len; + ASSERT_BOUNDS(tc->num,tc->max); + ASSERT_BOUNDS(off,tc->max); + ASSERT_BOUNDS(off+len-1,tc->max); + ASSERT_BOUNDS(off+len-1,tc->num); + memcpy (tc->str + off, string, len); + + ch = string; + while (ch < (string + len)) { + ASSERT_BOUNDS(off,tc->num); + rde_stack_push (tc->off, (void*) off); + clen = Tcl_UtfToUniChar (ch, &uni); + off += clen; + ch += clen; + } + return tc->str + base; + } + SCOPE void + rde_tc_get (RDE_TC tc, int at, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + off = ov [at]; + if ((at+1) == oc) { + end = tc->num; + } else { + end = ov [at+1]; + } + TRACE (("rde_tc_get (RDE_TC %p, @ %d) => %d.[%d ... %d]/%d",tc,at,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + SCOPE void + rde_tc_get_s (RDE_TC tc, int at, int last, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + ASSERT_BOUNDS(last,oc); + off = ov [at]; + if ((last+1) == oc) { + end = tc->num; + } else { + end = ov [last+1]; + } + TRACE (("rde_tc_get_s (RDE_TC %p, @ %d .. %d) => %d.[%d ... %d]/%d",tc,at,last,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + + +#line 1 "rde_critcl/param.c" + + typedef struct RDE_PARAM_ { + Tcl_Channel IN; + Tcl_Obj* readbuf; + char* CC; + long int CC_len; + RDE_TC TC; + long int CL; + RDE_STACK LS; + ERROR_STATE* ER; + RDE_STACK ES; + long int ST; + Tcl_Obj* SV; + Tcl_HashTable NC; + + RDE_STACK ast ; + RDE_STACK mark ; + + long int numstr; + char** string; + + ClientData clientData; + } RDE_PARAM_; + typedef int (*UniCharClass) (int); + typedef enum test_class_id { + tc_alnum, + tc_alpha, + tc_ascii, + tc_control, + tc_ddigit, + tc_digit, + tc_graph, + tc_lower, + tc_printable, + tc_punct, + tc_space, + tc_upper, + tc_wordchar, + tc_xdigit + } test_class_id; + static void ast_node_free (void* n); + static void error_state_free (void* es); + static void error_set (RDE_PARAM p, int s); + static void nc_clear (RDE_PARAM p); + static int UniCharIsAscii (int character); + static int UniCharIsHexDigit (int character); + static int UniCharIsDecDigit (int character); + static void test_class (RDE_PARAM p, UniCharClass class, test_class_id id); + static int er_int_compare (const void* a, const void* b); + #define SV_INIT(p) \ + p->SV = NULL; \ + TRACE (("SV_INIT (%p => %p)", (p), (p)->SV)) + #define SV_SET(p,newsv) \ + if (((p)->SV) != (newsv)) { \ + TRACE (("SV_CLEAR/set (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = (newsv); \ + TRACE (("SV_SET (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_IncrRefCount ((p)->SV); \ + } \ + } + #define SV_CLEAR(p) \ + TRACE (("SV_CLEAR (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = NULL + #define ER_INIT(p) \ + p->ER = NULL; \ + TRACE (("ER_INIT (%p => %p)", (p), (p)->ER)) + #define ER_CLEAR(p) \ + error_state_free ((p)->ER); \ + (p)->ER = NULL + SCOPE RDE_PARAM + rde_param_new (long int nstr, char** strings) + { + RDE_PARAM p; + ENTER ("rde_param_new"); + TRACE (("\tINT %d strings @ %p", nstr, strings)); + p = ALLOC (RDE_PARAM_); + p->numstr = nstr; + p->string = strings; + p->readbuf = Tcl_NewObj (); + Tcl_IncrRefCount (p->readbuf); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_InitHashTable (&p->NC, TCL_ONE_WORD_KEYS); + p->IN = NULL; + p->CL = -1; + p->ST = 0; + ER_INIT (p); + SV_INIT (p); + p->CC = NULL; + p->CC_len = 0; + p->TC = rde_tc_new (); + p->ES = rde_stack_new (error_state_free); + p->LS = rde_stack_new (NULL); + p->ast = rde_stack_new (ast_node_free); + p->mark = rde_stack_new (NULL); + RETURN ("%p", p); + } + SCOPE void + rde_param_del (RDE_PARAM p) + { + ENTER ("rde_param_del"); + TRACE (("RDE_PARAM %p",p)); + ER_CLEAR (p); TRACE (("\ter_clear")); + SV_CLEAR (p); TRACE (("\tsv_clear")); + nc_clear (p); TRACE (("\tnc_clear")); + Tcl_DeleteHashTable (&p->NC); TRACE (("\tnc hashtable delete")); + rde_tc_del (p->TC); TRACE (("\ttc clear")); + rde_stack_del (p->ES); TRACE (("\tes clear")); + rde_stack_del (p->LS); TRACE (("\tls clear")); + rde_stack_del (p->ast); TRACE (("\tast clear")); + rde_stack_del (p->mark); TRACE (("\tmark clear")); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_DecrRefCount (p->readbuf); + ckfree ((char*) p); + RETURNVOID; + } + SCOPE void + rde_param_reset (RDE_PARAM p, Tcl_Channel chan) + { + ENTER ("rde_param_reset"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("Tcl_Channel %p",chan)); + p->IN = chan; + p->CL = -1; + p->ST = 0; + p->CC = NULL; + p->CC_len = 0; + ER_CLEAR (p); + SV_CLEAR (p); + nc_clear (p); + rde_tc_clear (p->TC); + rde_stack_trim (p->ES, 0); + rde_stack_trim (p->LS, 0); + rde_stack_trim (p->ast, 0); + rde_stack_trim (p->mark, 0); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + RETURNVOID; + } + SCOPE void + rde_param_update_strings (RDE_PARAM p, long int nstr, char** strings) + { + ENTER ("rde_param_update_strings"); + TRACE (("RDE_PARAM %p", p)); + TRACE (("INT %d strings", nstr)); + p->numstr = nstr; + p->string = strings; + RETURNVOID; + } + SCOPE void + rde_param_data (RDE_PARAM p, char* buf, long int len) + { + (void) rde_tc_append (p->TC, buf, len); + } + SCOPE void + rde_param_clientdata (RDE_PARAM p, ClientData clientData) + { + p->clientData = clientData; + } + static void + nc_clear (RDE_PARAM p) + { + Tcl_HashSearch hs; + Tcl_HashEntry* he; + Tcl_HashTable* tablePtr; + for(he = Tcl_FirstHashEntry(&p->NC, &hs); + he != NULL; + he = Tcl_FirstHashEntry(&p->NC, &hs)) { + Tcl_HashSearch hsc; + Tcl_HashEntry* hec; + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (he); + for(hec = Tcl_FirstHashEntry(tablePtr, &hsc); + hec != NULL; + hec = Tcl_NextHashEntry(&hsc)) { + NC_STATE* scs = Tcl_GetHashValue (hec); + error_state_free (scs->ER); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + ckfree ((char*) scs); + } + Tcl_DeleteHashTable (tablePtr); + ckfree ((char*) tablePtr); + Tcl_DeleteHashEntry (he); + } + } + SCOPE ClientData + rde_param_query_clientdata (RDE_PARAM p) + { + return p->clientData; + } + SCOPE void + rde_param_query_amark (RDE_PARAM p, long int* mc, long int** mv) + { + rde_stack_get (p->mark, mc, (void***) mv); + } + SCOPE void + rde_param_query_ast (RDE_PARAM p, long int* ac, Tcl_Obj*** av) + { + rde_stack_get (p->ast, ac, (void***) av); + } + SCOPE const char* + rde_param_query_in (RDE_PARAM p) + { + return p->IN + ? Tcl_GetChannelName (p->IN) + : ""; + } + SCOPE const char* + rde_param_query_cc (RDE_PARAM p, long int* len) + { + *len = p->CC_len; + return p->CC; + } + SCOPE int + rde_param_query_cl (RDE_PARAM p) + { + return p->CL; + } + SCOPE const ERROR_STATE* + rde_param_query_er (RDE_PARAM p) + { + return p->ER; + } + SCOPE Tcl_Obj* + rde_param_query_er_tcl (RDE_PARAM p, const ERROR_STATE* er) + { + Tcl_Obj* res; + if (!er) { + + res = Tcl_NewStringObj ("", 0); + } else { + Tcl_Obj* ov [2]; + Tcl_Obj** mov; + long int mc, i, j; + long int* mv; + int lastid; + const char* msg; + rde_stack_get (er->msg, &mc, (void***) &mv); + + qsort (mv, mc, sizeof (long int), er_int_compare); + + mov = NALLOC (mc, Tcl_Obj*); + lastid = -1; + for (i=0, j=0; i < mc; i++) { + ASSERT_BOUNDS (i,mc); + if (mv [i] == lastid) continue; + lastid = mv [i]; + ASSERT_BOUNDS(mv[i],p->numstr); + msg = p->string [mv[i]]; + ASSERT_BOUNDS (j,mc); + mov [j] = Tcl_NewStringObj (msg, -1); + j++; + } + + ov [0] = Tcl_NewIntObj (er->loc); + ov [1] = Tcl_NewListObj (j, mov); + res = Tcl_NewListObj (2, ov); + ckfree ((char*) mov); + } + return res; + } + SCOPE void + rde_param_query_es (RDE_PARAM p, long int* ec, ERROR_STATE*** ev) + { + rde_stack_get (p->ES, ec, (void***) ev); + } + SCOPE void + rde_param_query_ls (RDE_PARAM p, long int* lc, void*** lv) + { + rde_stack_get (p->LS, lc, lv); + } + SCOPE long int + rde_param_query_lstop (RDE_PARAM p) + { + (long int) rde_stack_top (p->LS); + } + SCOPE Tcl_HashTable* + rde_param_query_nc (RDE_PARAM p) + { + return &p->NC; + } + SCOPE int + rde_param_query_st (RDE_PARAM p) + { + return p->ST; + } + SCOPE Tcl_Obj* + rde_param_query_sv (RDE_PARAM p) + { + TRACE (("SV_QUERY %p => (%p)", (p), (p)->SV)); \ + return p->SV; + } + SCOPE long int + rde_param_query_tc_size (RDE_PARAM p) + { + return rde_tc_size (p->TC); + } + SCOPE void + rde_param_query_tc_get_s (RDE_PARAM p, long int at, long int last, char** ch, long int* len) + { + rde_tc_get_s (p->TC, at, last, ch, len); + } + SCOPE const char* + rde_param_query_string (RDE_PARAM p, long int id) + { + TRACE (("rde_param_query_string (RDE_PARAM %p, %d/%d)", p, id, p->numstr)); + ASSERT_BOUNDS(id,p->numstr); + return p->string [id]; + } + SCOPE void + rde_param_i_ast_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->mark, 1); + } + SCOPE void + rde_param_i_ast_pop_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_pop_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_push (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_ast_value_push (RDE_PARAM p) + { + ENTER ("rde_param_i_ast_value_push"); + TRACE (("RDE_PARAM %p",p)); + ASSERT(p->SV,"Unable to push undefined semantic value"); + TRACE (("rde_param_i_ast_value_push %p => (%p)", p, p->SV)); + TRACE (("SV = (%p rc%d '%s')", p->SV, p->SV->refCount, Tcl_GetString (p->SV))); + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + RETURNVOID; + } + static void + ast_node_free (void* n) + { + Tcl_DecrRefCount ((Tcl_Obj*) n); + } + SCOPE void + rde_param_i_error_clear (RDE_PARAM p) + { + ER_CLEAR (p); + } + SCOPE void + rde_param_i_error_nonterminal (RDE_PARAM p, int s) + { + + return; + long int pos; + if (!p->ER) return; + pos = 1 + (long int) rde_stack_top (p->LS); + if (p->ER->loc != pos) return; + error_set (p, s); + p->ER->loc = pos; + } + SCOPE void + rde_param_i_error_pop_merge (RDE_PARAM p) + { + ERROR_STATE* top = (ERROR_STATE*) rde_stack_top (p->ES); + + if (top == p->ER) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!top) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!p->ER) { + rde_stack_drop (p->ES, 1); + p->ER = top; + + return; + } + + if (top->loc < p->ER->loc) { + rde_stack_pop (p->ES, 1); + return; + } + + if (top->loc > p->ER->loc) { + rde_stack_drop (p->ES, 1); + error_state_free (p->ER); + p->ER = top; + + return; + } + + rde_stack_move (p->ER->msg, top->msg); + rde_stack_pop (p->ES, 1); + } + SCOPE void + rde_param_i_error_push (RDE_PARAM p) + { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + static void + error_set (RDE_PARAM p, int s) + { + error_state_free (p->ER); + p->ER = ALLOC (ERROR_STATE); + p->ER->refCount = 1; + p->ER->loc = p->CL; + p->ER->msg = rde_stack_new (NULL); + ASSERT_BOUNDS(s,p->numstr); + rde_stack_push (p->ER->msg, (void*) s); + } + static void + error_state_free (void* esx) + { + ERROR_STATE* es = esx; + if (!es) return; + es->refCount --; + if (es->refCount > 0) return; + rde_stack_del (es->msg); + ckfree ((char*) es); + } + SCOPE void + rde_param_i_loc_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_pop_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_push (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + } + SCOPE void + rde_param_i_loc_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + } + SCOPE void + rde_param_i_input_next (RDE_PARAM p, int m) + { + int leni; + char* ch; + ASSERT_BOUNDS(m,p->numstr); + p->CL ++; + if (p->CL < rde_tc_size (p->TC)) { + + rde_tc_get (p->TC, p->CL, &p->CC, &p->CC_len); + ASSERT_BOUNDS (p->CC_len, TCL_UTF_MAX); + p->ST = 1; + ER_CLEAR (p); + return; + } + if (!p->IN || + Tcl_Eof (p->IN) || + (Tcl_ReadChars (p->IN, p->readbuf, 1, 0) <= 0)) { + + p->ST = 0; + error_set (p, m); + return; + } + + ch = Tcl_GetStringFromObj (p->readbuf, &leni); + ASSERT_BOUNDS (leni, TCL_UTF_MAX); + p->CC = rde_tc_append (p->TC, ch, leni); + p->CC_len = leni; + p->ST = 1; + ER_CLEAR (p); + } + SCOPE void + rde_param_i_status_fail (RDE_PARAM p) + { + p->ST = 0; + } + SCOPE void + rde_param_i_status_ok (RDE_PARAM p) + { + p->ST = 1; + } + SCOPE void + rde_param_i_status_negate (RDE_PARAM p) + { + p->ST = !p->ST; + } + SCOPE int + rde_param_i_symbol_restore (RDE_PARAM p, int s) + { + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + + hPtr = Tcl_FindHashEntry (&p->NC, (char*) p->CL); + if (!hPtr) { return 0; } + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + hPtr = Tcl_FindHashEntry (tablePtr, (char*) s); + if (!hPtr) { return 0; } + + scs = Tcl_GetHashValue (hPtr); + p->CL = scs->CL; + p->ST = scs->ST; + error_state_free (p->ER); + p->ER = scs->ER; + if (p->ER) { p->ER->refCount ++; } + TRACE (("SV_RESTORE (%p) '%s'",scs->SV, scs->SV ? Tcl_GetString (scs->SV):"")); + SV_SET (p, scs->SV); + return 1; + } + SCOPE void + rde_param_i_symbol_save (RDE_PARAM p, int s) + { + long int at = (long int) rde_stack_top (p->LS); + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + int isnew; + ENTER ("rde_param_i_symbol_save"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("INT %d",s)); + + hPtr = Tcl_CreateHashEntry (&p->NC, (char*) at, &isnew); + if (isnew) { + tablePtr = ALLOC (Tcl_HashTable); + Tcl_InitHashTable (tablePtr, TCL_ONE_WORD_KEYS); + Tcl_SetHashValue (hPtr, tablePtr); + } else { + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + } + hPtr = Tcl_CreateHashEntry (tablePtr, (char*) s, &isnew); + if (isnew) { + + scs = ALLOC (NC_STATE); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "")); + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + Tcl_SetHashValue (hPtr, scs); + } else { + + scs = (NC_STATE*) Tcl_GetHashValue (hPtr); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE/over (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "" )); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + error_state_free (scs->ER); + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + } + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_test_alnum (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlnum, tc_alnum); + } + SCOPE void + rde_param_i_test_alpha (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlpha, tc_alpha); + } + SCOPE void + rde_param_i_test_ascii (RDE_PARAM p) + { + test_class (p, UniCharIsAscii, tc_ascii); + } + SCOPE void + rde_param_i_test_control (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsControl, tc_control); + } + SCOPE void + rde_param_i_test_char (RDE_PARAM p, const char* c, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = Tcl_UtfNcmp (p->CC, c, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_ddigit (RDE_PARAM p) + { + test_class (p, UniCharIsDecDigit, tc_ddigit); + } + SCOPE void + rde_param_i_test_digit (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsDigit, tc_digit); + } + SCOPE void + rde_param_i_test_graph (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsGraph, tc_graph); + } + SCOPE void + rde_param_i_test_lower (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsLower, tc_lower); + } + SCOPE void + rde_param_i_test_print (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPrint, tc_printable); + } + SCOPE void + rde_param_i_test_punct (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPunct, tc_punct); + } + SCOPE void + rde_param_i_test_range (RDE_PARAM p, char* s, char* e, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = + (Tcl_UtfNcmp (s, p->CC, 1) <= 0) && + (Tcl_UtfNcmp (p->CC, e, 1) <= 0); + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_space (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsSpace, tc_space); + } + SCOPE void + rde_param_i_test_upper (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsUpper, tc_upper); + } + SCOPE void + rde_param_i_test_wordchar (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsWordChar, tc_wordchar); + } + SCOPE void + rde_param_i_test_xdigit (RDE_PARAM p) + { + test_class (p, UniCharIsHexDigit, tc_xdigit); + } + static void + test_class (RDE_PARAM p, UniCharClass class, test_class_id id) + { + Tcl_UniChar ch; + Tcl_UtfToUniChar(p->CC, &ch); + ASSERT_BOUNDS(id,p->numstr); + p->ST = !!class (ch); + + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, id); + p->CL --; + } + } + static int + UniCharIsAscii (int character) + { + return (character >= 0) && (character < 0x80); + } + static int + UniCharIsHexDigit (int character) + { + return (character >= 0) && (character < 0x80) && isxdigit(character); + } + static int + UniCharIsDecDigit (int character) + { + return (character >= 0) && (character < 0x80) && isdigit(character); + } + SCOPE void + rde_param_i_value_clear (RDE_PARAM p) + { + SV_CLEAR (p); + } + SCOPE void + rde_param_i_value_leaf (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + Tcl_Obj* ov [3]; + long int pos = 1 + (long int) rde_stack_top (p->LS); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + newsv = Tcl_NewListObj (3, ov); + TRACE (("rde_param_i_value_leaf => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + } + SCOPE void + rde_param_i_value_reduce (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + int oc, i, j; + Tcl_Obj** ov; + long int ac; + Tcl_Obj** av; + long int pos = 1 + (long int) rde_stack_top (p->LS); + long int mark = (long int) rde_stack_top (p->mark); + long int asize = rde_stack_size (p->ast); + long int new = asize - mark; + ASSERT (new >= 0, "Bad number of elements to reduce"); + ov = NALLOC (3+new, Tcl_Obj*); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + rde_stack_get (p->ast, &ac, (void***) &av); + for (i = 3, j = mark; j < asize; i++, j++) { + ASSERT_BOUNDS (i, 3+new); + ASSERT_BOUNDS (j, ac); + ov [i] = av [j]; + } + ASSERT (i == 3+new, "Reduction result incomplete"); + newsv = Tcl_NewListObj (3+new, ov); + TRACE (("rde_param_i_value_reduce => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + ckfree ((char*) ov); + } + static int + er_int_compare (const void* a, const void* b) + { + long int ai = *((long int*) a); + long int bi = *((long int*) b); + if (ai < bi) { return -1; } + if (ai > bi) { return 1; } + return 0; + } + SCOPE int + rde_param_i_symbol_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE void + rde_param_i_symbol_done_d_reduce (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_reduce (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_d_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_symbol_done_d_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_next_char (RDE_PARAM p, char* c, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_char (p, c, m); + } + SCOPE void + rde_param_i_next_range (RDE_PARAM p, char* s, char* e, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_range (p, s, e, m); + } + SCOPE void + rde_param_i_next_alnum (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alnum (p); + } + SCOPE void + rde_param_i_next_alpha (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alpha (p); + } + SCOPE void + rde_param_i_next_ascii (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ascii (p); + } + SCOPE void + rde_param_i_next_control (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_control (p); + } + SCOPE void + rde_param_i_next_ddigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ddigit (p); + } + SCOPE void + rde_param_i_next_digit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_digit (p); + } + SCOPE void + rde_param_i_next_graph (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_graph (p); + } + SCOPE void + rde_param_i_next_lower (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_lower (p); + } + SCOPE void + rde_param_i_next_print (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_print (p); + } + SCOPE void + rde_param_i_next_punct (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_punct (p); + } + SCOPE void + rde_param_i_next_space (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_space (p); + } + SCOPE void + rde_param_i_next_upper (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_upper (p); + } + SCOPE void + rde_param_i_next_wordchar (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_wordchar (p); + } + SCOPE void + rde_param_i_next_xdigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_xdigit (p); + } + SCOPE void + rde_param_i_notahead_start_d (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_notahead_exit_d (RDE_PARAM p) + { + if (p->ST) { + rde_param_i_ast_pop_rewind (p); + } else { + rde_stack_pop (p->mark, 1); + } + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_notahead_exit (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_state_push_2 (RDE_PARAM p) + { + + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + SCOPE void + rde_param_i_state_push_void (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_push_value (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_merge_ok (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } + SCOPE int + rde_param_i_kleene_close (RDE_PARAM p) + { + int stop = !p->ST; + rde_param_i_error_pop_merge (p); + if (stop) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_kleene_abort (RDE_PARAM p) + { + int stop = !p->ST; + if (stop) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_seq_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_bra_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE void + rde_param_i_next_str (RDE_PARAM p, const char* str, int m) + { + int at = p->CL; + + while (*str) { + rde_param_i_input_next (p, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + rde_param_i_test_char (p, str, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + str = Tcl_UtfNext (str); + } + } + SCOPE void + rde_param_i_next_class (RDE_PARAM p, const char* class, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + while (*class) { + p->ST = Tcl_UtfNcmp (p->CC, class, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + return; + } + class = Tcl_UtfNext (class); + } + error_set (p, m); + p->CL --; + } + + + /* + * Declaring the parse functions + */ + + static void sequence_4 (RDE_PARAM p); + static void sym_ALNUM (RDE_PARAM p); + static void sequence_9 (RDE_PARAM p); + static void sym_ALPHA (RDE_PARAM p); + static void sequence_14 (RDE_PARAM p); + static void sym_AND (RDE_PARAM p); + static void sym_APOSTROPH (RDE_PARAM p); + static void sequence_21 (RDE_PARAM p); + static void sym_ASCII (RDE_PARAM p); + static void choice_26 (RDE_PARAM p); + static void sequence_29 (RDE_PARAM p); + static void sym_Attribute (RDE_PARAM p); + static void choice_37 (RDE_PARAM p); + static void sym_Char (RDE_PARAM p); + static void sequence_44 (RDE_PARAM p); + static void sym_CharOctalFull (RDE_PARAM p); + static void optional_50 (RDE_PARAM p); + static void sequence_52 (RDE_PARAM p); + static void sym_CharOctalPart (RDE_PARAM p); + static void sequence_57 (RDE_PARAM p); + static void sym_CharSpecial (RDE_PARAM p); + static void notahead_61 (RDE_PARAM p); + static void sequence_64 (RDE_PARAM p); + static void sym_CharUnescaped (RDE_PARAM p); + static void optional_72 (RDE_PARAM p); + static void sequence_74 (RDE_PARAM p); + static void optional_76 (RDE_PARAM p); + static void sequence_78 (RDE_PARAM p); + static void optional_80 (RDE_PARAM p); + static void sequence_82 (RDE_PARAM p); + static void sym_CharUnicode (RDE_PARAM p); + static void notahead_87 (RDE_PARAM p); + static void sequence_90 (RDE_PARAM p); + static void kleene_92 (RDE_PARAM p); + static void sequence_96 (RDE_PARAM p); + static void sym_Class (RDE_PARAM p); + static void sequence_101 (RDE_PARAM p); + static void sym_CLOSE (RDE_PARAM p); + static void sym_CLOSEB (RDE_PARAM p); + static void sequence_108 (RDE_PARAM p); + static void sym_COLON (RDE_PARAM p); + static void notahead_113 (RDE_PARAM p); + static void sequence_116 (RDE_PARAM p); + static void kleene_118 (RDE_PARAM p); + static void sequence_121 (RDE_PARAM p); + static void sym_COMMENT (RDE_PARAM p); + static void sequence_126 (RDE_PARAM p); + static void sym_CONTROL (RDE_PARAM p); + static void sym_DAPOSTROPH (RDE_PARAM p); + static void sequence_133 (RDE_PARAM p); + static void sym_DDIGIT (RDE_PARAM p); + static void optional_137 (RDE_PARAM p); + static void sequence_143 (RDE_PARAM p); + static void sym_Definition (RDE_PARAM p); + static void sequence_148 (RDE_PARAM p); + static void sym_DIGIT (RDE_PARAM p); + static void sequence_153 (RDE_PARAM p); + static void sym_DOT (RDE_PARAM p); + static void notahead_157 (RDE_PARAM p); + static void sym_EOF (RDE_PARAM p); + static void sym_EOL (RDE_PARAM p); + static void sequence_165 (RDE_PARAM p); + static void kleene_167 (RDE_PARAM p); + static void sequence_169 (RDE_PARAM p); + static void sym_Expression (RDE_PARAM p); + static void sequence_176 (RDE_PARAM p); + static void sym_Final (RDE_PARAM p); + static void kleene_182 (RDE_PARAM p); + static void sequence_186 (RDE_PARAM p); + static void sym_Grammar (RDE_PARAM p); + static void sequence_191 (RDE_PARAM p); + static void sym_GRAPH (RDE_PARAM p); + static void sequence_197 (RDE_PARAM p); + static void sym_Header (RDE_PARAM p); + static void choice_202 (RDE_PARAM p); + static void choice_206 (RDE_PARAM p); + static void kleene_208 (RDE_PARAM p); + static void sequence_210 (RDE_PARAM p); + static void sym_Ident (RDE_PARAM p); + static void sequence_215 (RDE_PARAM p); + static void sym_Identifier (RDE_PARAM p); + static void sequence_220 (RDE_PARAM p); + static void sym_IS (RDE_PARAM p); + static void sequence_225 (RDE_PARAM p); + static void sym_LEAF (RDE_PARAM p); + static void notahead_230 (RDE_PARAM p); + static void sequence_233 (RDE_PARAM p); + static void kleene_235 (RDE_PARAM p); + static void sequence_239 (RDE_PARAM p); + static void notahead_243 (RDE_PARAM p); + static void sequence_246 (RDE_PARAM p); + static void kleene_248 (RDE_PARAM p); + static void sequence_252 (RDE_PARAM p); + static void choice_254 (RDE_PARAM p); + static void sym_Literal (RDE_PARAM p); + static void sequence_259 (RDE_PARAM p); + static void sym_LOWER (RDE_PARAM p); + static void sequence_264 (RDE_PARAM p); + static void sym_NOT (RDE_PARAM p); + static void sequence_269 (RDE_PARAM p); + static void sym_OPEN (RDE_PARAM p); + static void sym_OPENB (RDE_PARAM p); + static void notahead_278 (RDE_PARAM p); + static void sequence_281 (RDE_PARAM p); + static void sym_PEG (RDE_PARAM p); + static void sequence_286 (RDE_PARAM p); + static void sym_PLUS (RDE_PARAM p); + static void choice_291 (RDE_PARAM p); + static void optional_293 (RDE_PARAM p); + static void sequence_296 (RDE_PARAM p); + static void sym_Prefix (RDE_PARAM p); + static void sequence_317 (RDE_PARAM p); + static void choice_322 (RDE_PARAM p); + static void sym_Primary (RDE_PARAM p); + static void sequence_327 (RDE_PARAM p); + static void sym_PRINTABLE (RDE_PARAM p); + static void sequence_332 (RDE_PARAM p); + static void sym_PUNCT (RDE_PARAM p); + static void sequence_337 (RDE_PARAM p); + static void sym_QUESTION (RDE_PARAM p); + static void sequence_343 (RDE_PARAM p); + static void choice_346 (RDE_PARAM p); + static void sym_Range (RDE_PARAM p); + static void sequence_351 (RDE_PARAM p); + static void sym_SEMICOLON (RDE_PARAM p); + static void poskleene_355 (RDE_PARAM p); + static void sym_Sequence (RDE_PARAM p); + static void sequence_360 (RDE_PARAM p); + static void sym_SLASH (RDE_PARAM p); + static void sequence_365 (RDE_PARAM p); + static void sym_SPACE (RDE_PARAM p); + static void sequence_370 (RDE_PARAM p); + static void sym_STAR (RDE_PARAM p); + static void sym_StartExpr (RDE_PARAM p); + static void choice_382 (RDE_PARAM p); + static void optional_384 (RDE_PARAM p); + static void sequence_386 (RDE_PARAM p); + static void sym_Suffix (RDE_PARAM p); + static void sym_TO (RDE_PARAM p); + static void sequence_393 (RDE_PARAM p); + static void sym_UPPER (RDE_PARAM p); + static void sequence_398 (RDE_PARAM p); + static void sym_VOID (RDE_PARAM p); + static void choice_403 (RDE_PARAM p); + static void kleene_405 (RDE_PARAM p); + static void sym_WHITESPACE (RDE_PARAM p); + static void sequence_410 (RDE_PARAM p); + static void sym_WORDCHAR (RDE_PARAM p); + static void sequence_415 (RDE_PARAM p); + static void sym_XDIGIT (RDE_PARAM p); + + /* + * Precomputed table of strings (symbols, error messages, etc.). + */ + + static char const* p_string [178] = { + /* 0 = */ "alnum", + /* 1 = */ "alpha", + /* 2 = */ "ascii", + /* 3 = */ "control", + /* 4 = */ "ddigit", + /* 5 = */ "digit", + /* 6 = */ "graph", + /* 7 = */ "lower", + /* 8 = */ "print", + /* 9 = */ "punct", + /* 10 = */ "space", + /* 11 = */ "upper", + /* 12 = */ "wordchar", + /* 13 = */ "xdigit", + /* 14 = */ "str ", + /* 15 = */ "n ALNUM", + /* 16 = */ "ALNUM", + /* 17 = */ "str ", + /* 18 = */ "n ALPHA", + /* 19 = */ "ALPHA", + /* 20 = */ "t &", + /* 21 = */ "n AND", + /* 22 = */ "AND", + /* 23 = */ "t '", + /* 24 = */ "n APOSTROPH", + /* 25 = */ "APOSTROPH", + /* 26 = */ "str ", + /* 27 = */ "n ASCII", + /* 28 = */ "ASCII", + /* 29 = */ "n Attribute", + /* 30 = */ "Attribute", + /* 31 = */ "n Char", + /* 32 = */ "Char", + /* 33 = */ "t \134", + /* 34 = */ ".. 0 2", + /* 35 = */ ".. 0 7", + /* 36 = */ "n CharOctalFull", + /* 37 = */ "CharOctalFull", + /* 38 = */ "n CharOctalPart", + /* 39 = */ "CharOctalPart", + /* 40 = */ "cl nrt'\42\133\135\134", + /* 41 = */ "n CharSpecial", + /* 42 = */ "CharSpecial", + /* 43 = */ "dot", + /* 44 = */ "n CharUnescaped", + /* 45 = */ "CharUnescaped", + /* 46 = */ "str \134u", + /* 47 = */ "n CharUnicode", + /* 48 = */ "CharUnicode", + /* 49 = */ "n Class", + /* 50 = */ "Class", + /* 51 = */ "t \51", + /* 52 = */ "n CLOSE", + /* 53 = */ "CLOSE", + /* 54 = */ "t \135", + /* 55 = */ "n CLOSEB", + /* 56 = */ "CLOSEB", + /* 57 = */ "t :", + /* 58 = */ "n COLON", + /* 59 = */ "COLON", + /* 60 = */ "t #", + /* 61 = */ "n COMMENT", + /* 62 = */ "COMMENT", + /* 63 = */ "str ", + /* 64 = */ "n CONTROL", + /* 65 = */ "CONTROL", + /* 66 = */ "t \42", + /* 67 = */ "n DAPOSTROPH", + /* 68 = */ "DAPOSTROPH", + /* 69 = */ "str ", + /* 70 = */ "n DDIGIT", + /* 71 = */ "DDIGIT", + /* 72 = */ "n Definition", + /* 73 = */ "Definition", + /* 74 = */ "str ", + /* 75 = */ "n DIGIT", + /* 76 = */ "DIGIT", + /* 77 = */ "t .", + /* 78 = */ "n DOT", + /* 79 = */ "DOT", + /* 80 = */ "n EOF", + /* 81 = */ "EOF", + /* 82 = */ "cl \n\r", + /* 83 = */ "n EOL", + /* 84 = */ "EOL", + /* 85 = */ "n Expression", + /* 86 = */ "Expression", + /* 87 = */ "str END", + /* 88 = */ "n Final", + /* 89 = */ "Final", + /* 90 = */ "n Grammar", + /* 91 = */ "Grammar", + /* 92 = */ "str ", + /* 93 = */ "n GRAPH", + /* 94 = */ "GRAPH", + /* 95 = */ "n Header", + /* 96 = */ "Header", + /* 97 = */ "cl _:", + /* 98 = */ "n Ident", + /* 99 = */ "Ident", + /* 100 = */ "n Identifier", + /* 101 = */ "Identifier", + /* 102 = */ "str <-", + /* 103 = */ "n IS", + /* 104 = */ "IS", + /* 105 = */ "str leaf", + /* 106 = */ "n LEAF", + /* 107 = */ "LEAF", + /* 108 = */ "n Literal", + /* 109 = */ "Literal", + /* 110 = */ "str ", + /* 111 = */ "n LOWER", + /* 112 = */ "LOWER", + /* 113 = */ "t !", + /* 114 = */ "n NOT", + /* 115 = */ "NOT", + /* 116 = */ "t \50", + /* 117 = */ "n OPEN", + /* 118 = */ "OPEN", + /* 119 = */ "t \133", + /* 120 = */ "n OPENB", + /* 121 = */ "OPENB", + /* 122 = */ "str PEG", + /* 123 = */ "n PEG", + /* 124 = */ "PEG", + /* 125 = */ "t +", + /* 126 = */ "n PLUS", + /* 127 = */ "PLUS", + /* 128 = */ "n Prefix", + /* 129 = */ "Prefix", + /* 130 = */ "n Primary", + /* 131 = */ "Primary", + /* 132 = */ "str ", + /* 133 = */ "n PRINTABLE", + /* 134 = */ "PRINTABLE", + /* 135 = */ "str ", + /* 136 = */ "n PUNCT", + /* 137 = */ "PUNCT", + /* 138 = */ "t ?", + /* 139 = */ "n QUESTION", + /* 140 = */ "QUESTION", + /* 141 = */ "n Range", + /* 142 = */ "Range", + /* 143 = */ "t \73", + /* 144 = */ "n SEMICOLON", + /* 145 = */ "SEMICOLON", + /* 146 = */ "n Sequence", + /* 147 = */ "Sequence", + /* 148 = */ "t /", + /* 149 = */ "n SLASH", + /* 150 = */ "SLASH", + /* 151 = */ "str ", + /* 152 = */ "n SPACE", + /* 153 = */ "SPACE", + /* 154 = */ "t *", + /* 155 = */ "n STAR", + /* 156 = */ "STAR", + /* 157 = */ "n StartExpr", + /* 158 = */ "StartExpr", + /* 159 = */ "n Suffix", + /* 160 = */ "Suffix", + /* 161 = */ "t -", + /* 162 = */ "n TO", + /* 163 = */ "TO", + /* 164 = */ "str ", + /* 165 = */ "n UPPER", + /* 166 = */ "UPPER", + /* 167 = */ "str void", + /* 168 = */ "n VOID", + /* 169 = */ "VOID", + /* 170 = */ "n WHITESPACE", + /* 171 = */ "WHITESPACE", + /* 172 = */ "str ", + /* 173 = */ "n WORDCHAR", + /* 174 = */ "WORDCHAR", + /* 175 = */ "str ", + /* 176 = */ "n XDIGIT", + /* 177 = */ "XDIGIT" + }; + + /* + * Grammar Start Expression + */ + + static void MAIN (RDE_PARAM p) { + sym_Grammar (p); + return; + } + + /* + * leaf Symbol 'ALNUM' + */ + + static void sym_ALNUM (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 16)) return ; + sequence_4 (p); + rde_param_i_symbol_done_leaf (p, 16, 15); + return; + } + + static void sequence_4 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 14); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'ALPHA' + */ + + static void sym_ALPHA (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 19)) return ; + sequence_9 (p); + rde_param_i_symbol_done_leaf (p, 19, 18); + return; + } + + static void sequence_9 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 17); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'AND' + */ + + static void sym_AND (RDE_PARAM p) { + /* + * x + * '&' + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 22)) return ; + sequence_14 (p); + rde_param_i_symbol_done_leaf (p, 22, 21); + return; + } + + static void sequence_14 (RDE_PARAM p) { + /* + * x + * '&' + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "&", 20); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * void Symbol 'APOSTROPH' + */ + + static void sym_APOSTROPH (RDE_PARAM p) { + /* + * ''' + */ + + if (rde_param_i_symbol_void_start (p, 25)) return ; + rde_param_i_next_char (p, "'", 23); + rde_param_i_symbol_done_void (p, 25, 24); + return; + } + + /* + * leaf Symbol 'ASCII' + */ + + static void sym_ASCII (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 28)) return ; + sequence_21 (p); + rde_param_i_symbol_done_leaf (p, 28, 27); + return; + } + + static void sequence_21 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 26); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * value Symbol 'Attribute' + */ + + static void sym_Attribute (RDE_PARAM p) { + /* + * x + * / + * (VOID) + * (LEAF) + * (COLON) + */ + + if (rde_param_i_symbol_start_d (p, 30)) return ; + sequence_29 (p); + rde_param_i_symbol_done_d_reduce (p, 30, 29); + return; + } + + static void sequence_29 (RDE_PARAM p) { + /* + * x + * / + * (VOID) + * (LEAF) + * (COLON) + */ + + rde_param_i_state_push_value (p); + choice_26 (p); + if (rde_param_i_seq_value2value(p)) return; + sym_COLON (p); + rde_param_i_state_merge_value (p); + return; + } + + static void choice_26 (RDE_PARAM p) { + /* + * / + * (VOID) + * (LEAF) + */ + + rde_param_i_state_push_value (p); + sym_VOID (p); + if (rde_param_i_bra_value2value(p)) return; + sym_LEAF (p); + rde_param_i_state_merge_value (p); + return; + } + + /* + * value Symbol 'Char' + */ + + static void sym_Char (RDE_PARAM p) { + /* + * / + * (CharSpecial) + * (CharOctalFull) + * (CharOctalPart) + * (CharUnicode) + * (CharUnescaped) + */ + + if (rde_param_i_symbol_start_d (p, 32)) return ; + choice_37 (p); + rde_param_i_symbol_done_d_reduce (p, 32, 31); + return; + } + + static void choice_37 (RDE_PARAM p) { + /* + * / + * (CharSpecial) + * (CharOctalFull) + * (CharOctalPart) + * (CharUnicode) + * (CharUnescaped) + */ + + rde_param_i_state_push_value (p); + sym_CharSpecial (p); + if (rde_param_i_bra_value2value(p)) return; + sym_CharOctalFull (p); + if (rde_param_i_bra_value2value(p)) return; + sym_CharOctalPart (p); + if (rde_param_i_bra_value2value(p)) return; + sym_CharUnicode (p); + if (rde_param_i_bra_value2value(p)) return; + sym_CharUnescaped (p); + rde_param_i_state_merge_value (p); + return; + } + + /* + * leaf Symbol 'CharOctalFull' + */ + + static void sym_CharOctalFull (RDE_PARAM p) { + /* + * x + * '\' + * range (0 .. 2) + * range (0 .. 7) + * range (0 .. 7) + */ + + if (rde_param_i_symbol_start (p, 37)) return ; + sequence_44 (p); + rde_param_i_symbol_done_leaf (p, 37, 36); + return; + } + + static void sequence_44 (RDE_PARAM p) { + /* + * x + * '\' + * range (0 .. 2) + * range (0 .. 7) + * range (0 .. 7) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "\134", 33); + if (rde_param_i_seq_void2void(p)) return; + rde_param_i_next_range (p, "0", "2", 34); + if (rde_param_i_seq_void2void(p)) return; + rde_param_i_next_range (p, "0", "7", 35); + if (rde_param_i_seq_void2void(p)) return; + rde_param_i_next_range (p, "0", "7", 35); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'CharOctalPart' + */ + + static void sym_CharOctalPart (RDE_PARAM p) { + /* + * x + * '\' + * range (0 .. 7) + * ? + * range (0 .. 7) + */ + + if (rde_param_i_symbol_start (p, 39)) return ; + sequence_52 (p); + rde_param_i_symbol_done_leaf (p, 39, 38); + return; + } + + static void sequence_52 (RDE_PARAM p) { + /* + * x + * '\' + * range (0 .. 7) + * ? + * range (0 .. 7) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "\134", 33); + if (rde_param_i_seq_void2void(p)) return; + rde_param_i_next_range (p, "0", "7", 35); + if (rde_param_i_seq_void2void(p)) return; + optional_50 (p); + rde_param_i_state_merge_void (p); + return; + } + + static void optional_50 (RDE_PARAM p) { + /* + * ? + * range (0 .. 7) + */ + + rde_param_i_state_push_2 (p); + rde_param_i_next_range (p, "0", "7", 35); + rde_param_i_state_merge_ok (p); + return; + } + + /* + * leaf Symbol 'CharSpecial' + */ + + static void sym_CharSpecial (RDE_PARAM p) { + /* + * x + * '\' + * [nrt'\"[]\] + */ + + if (rde_param_i_symbol_start (p, 42)) return ; + sequence_57 (p); + rde_param_i_symbol_done_leaf (p, 42, 41); + return; + } + + static void sequence_57 (RDE_PARAM p) { + /* + * x + * '\' + * [nrt'\"[]\] + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "\134", 33); + if (rde_param_i_seq_void2void(p)) return; + rde_param_i_next_class (p, "nrt'\42\133\135\134", 40); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'CharUnescaped' + */ + + static void sym_CharUnescaped (RDE_PARAM p) { + /* + * x + * ! + * '\' + * + */ + + if (rde_param_i_symbol_start (p, 45)) return ; + sequence_64 (p); + rde_param_i_symbol_done_leaf (p, 45, 44); + return; + } + + static void sequence_64 (RDE_PARAM p) { + /* + * x + * ! + * '\' + * + */ + + rde_param_i_state_push_void (p); + notahead_61 (p); + if (rde_param_i_seq_void2void(p)) return; + rde_param_i_input_next (p, 43); + rde_param_i_state_merge_void (p); + return; + } + + static void notahead_61 (RDE_PARAM p) { + /* + * ! + * '\' + */ + + rde_param_i_loc_push (p); + rde_param_i_next_char (p, "\134", 33); + rde_param_i_notahead_exit (p); + return; + } + + /* + * leaf Symbol 'CharUnicode' + */ + + static void sym_CharUnicode (RDE_PARAM p) { + /* + * x + * "\u" + * + * ? + * x + * + * ? + * x + * + * ? + * + */ + + if (rde_param_i_symbol_start (p, 48)) return ; + sequence_82 (p); + rde_param_i_symbol_done_leaf (p, 48, 47); + return; + } + + static void sequence_82 (RDE_PARAM p) { + /* + * x + * "\u" + * + * ? + * x + * + * ? + * x + * + * ? + * + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "\134u", 46); + if (rde_param_i_seq_void2void(p)) return; + rde_param_i_next_xdigit (p, 13); + if (rde_param_i_seq_void2void(p)) return; + optional_80 (p); + rde_param_i_state_merge_void (p); + return; + } + + static void optional_80 (RDE_PARAM p) { + /* + * ? + * x + * + * ? + * x + * + * ? + * + */ + + rde_param_i_state_push_2 (p); + sequence_78 (p); + rde_param_i_state_merge_ok (p); + return; + } + + static void sequence_78 (RDE_PARAM p) { + /* + * x + * + * ? + * x + * + * ? + * + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_xdigit (p, 13); + if (rde_param_i_seq_void2void(p)) return; + optional_76 (p); + rde_param_i_state_merge_void (p); + return; + } + + static void optional_76 (RDE_PARAM p) { + /* + * ? + * x + * + * ? + * + */ + + rde_param_i_state_push_2 (p); + sequence_74 (p); + rde_param_i_state_merge_ok (p); + return; + } + + static void sequence_74 (RDE_PARAM p) { + /* + * x + * + * ? + * + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_xdigit (p, 13); + if (rde_param_i_seq_void2void(p)) return; + optional_72 (p); + rde_param_i_state_merge_void (p); + return; + } + + static void optional_72 (RDE_PARAM p) { + /* + * ? + * + */ + + rde_param_i_state_push_2 (p); + rde_param_i_next_xdigit (p, 13); + rde_param_i_state_merge_ok (p); + return; + } + + /* + * value Symbol 'Class' + */ + + static void sym_Class (RDE_PARAM p) { + /* + * x + * (OPENB) + * * + * x + * ! + * (CLOSEB) + * (Range) + * (CLOSEB) + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start_d (p, 50)) return ; + sequence_96 (p); + rde_param_i_symbol_done_d_reduce (p, 50, 49); + return; + } + + static void sequence_96 (RDE_PARAM p) { + /* + * x + * (OPENB) + * * + * x + * ! + * (CLOSEB) + * (Range) + * (CLOSEB) + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + sym_OPENB (p); + if (rde_param_i_seq_void2value(p)) return; + kleene_92 (p); + if (rde_param_i_seq_value2value(p)) return; + sym_CLOSEB (p); + if (rde_param_i_seq_value2value(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_value (p); + return; + } + + static void kleene_92 (RDE_PARAM p) { + /* + * * + * x + * ! + * (CLOSEB) + * (Range) + */ + + while (1) { + rde_param_i_state_push_2 (p); + sequence_90 (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + static void sequence_90 (RDE_PARAM p) { + /* + * x + * ! + * (CLOSEB) + * (Range) + */ + + rde_param_i_state_push_void (p); + notahead_87 (p); + if (rde_param_i_seq_void2value(p)) return; + sym_Range (p); + rde_param_i_state_merge_value (p); + return; + } + + static void notahead_87 (RDE_PARAM p) { + /* + * ! + * (CLOSEB) + */ + + rde_param_i_loc_push (p); + sym_CLOSEB (p); + rde_param_i_notahead_exit (p); + return; + } + + /* + * void Symbol 'CLOSE' + */ + + static void sym_CLOSE (RDE_PARAM p) { + /* + * x + * '\)' + * (WHITESPACE) + */ + + if (rde_param_i_symbol_void_start (p, 53)) return ; + sequence_101 (p); + rde_param_i_symbol_done_void (p, 53, 52); + return; + } + + static void sequence_101 (RDE_PARAM p) { + /* + * x + * '\)' + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "\51", 51); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * void Symbol 'CLOSEB' + */ + + static void sym_CLOSEB (RDE_PARAM p) { + /* + * ']' + */ + + if (rde_param_i_symbol_void_start (p, 56)) return ; + rde_param_i_next_char (p, "\135", 54); + rde_param_i_symbol_done_void (p, 56, 55); + return; + } + + /* + * void Symbol 'COLON' + */ + + static void sym_COLON (RDE_PARAM p) { + /* + * x + * ':' + * (WHITESPACE) + */ + + if (rde_param_i_symbol_void_start (p, 59)) return ; + sequence_108 (p); + rde_param_i_symbol_done_void (p, 59, 58); + return; + } + + static void sequence_108 (RDE_PARAM p) { + /* + * x + * ':' + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, ":", 57); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * void Symbol 'COMMENT' + */ + + static void sym_COMMENT (RDE_PARAM p) { + /* + * x + * '#' + * * + * x + * ! + * (EOL) + * + * (EOL) + */ + + if (rde_param_i_symbol_void_start (p, 62)) return ; + sequence_121 (p); + rde_param_i_symbol_done_void (p, 62, 61); + return; + } + + static void sequence_121 (RDE_PARAM p) { + /* + * x + * '#' + * * + * x + * ! + * (EOL) + * + * (EOL) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "#", 60); + if (rde_param_i_seq_void2void(p)) return; + kleene_118 (p); + if (rde_param_i_seq_void2void(p)) return; + sym_EOL (p); + rde_param_i_state_merge_void (p); + return; + } + + static void kleene_118 (RDE_PARAM p) { + /* + * * + * x + * ! + * (EOL) + * + */ + + while (1) { + rde_param_i_state_push_2 (p); + sequence_116 (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + static void sequence_116 (RDE_PARAM p) { + /* + * x + * ! + * (EOL) + * + */ + + rde_param_i_state_push_void (p); + notahead_113 (p); + if (rde_param_i_seq_void2void(p)) return; + rde_param_i_input_next (p, 43); + rde_param_i_state_merge_void (p); + return; + } + + static void notahead_113 (RDE_PARAM p) { + /* + * ! + * (EOL) + */ + + rde_param_i_loc_push (p); + sym_EOL (p); + rde_param_i_notahead_exit (p); + return; + } + + /* + * leaf Symbol 'CONTROL' + */ + + static void sym_CONTROL (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 65)) return ; + sequence_126 (p); + rde_param_i_symbol_done_leaf (p, 65, 64); + return; + } + + static void sequence_126 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 63); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * void Symbol 'DAPOSTROPH' + */ + + static void sym_DAPOSTROPH (RDE_PARAM p) { + /* + * '\"' + */ + + if (rde_param_i_symbol_void_start (p, 68)) return ; + rde_param_i_next_char (p, "\42", 66); + rde_param_i_symbol_done_void (p, 68, 67); + return; + } + + /* + * leaf Symbol 'DDIGIT' + */ + + static void sym_DDIGIT (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 71)) return ; + sequence_133 (p); + rde_param_i_symbol_done_leaf (p, 71, 70); + return; + } + + static void sequence_133 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 69); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * value Symbol 'Definition' + */ + + static void sym_Definition (RDE_PARAM p) { + /* + * x + * ? + * (Attribute) + * (Identifier) + * (IS) + * (Expression) + * (SEMICOLON) + */ + + if (rde_param_i_symbol_start_d (p, 73)) return ; + sequence_143 (p); + rde_param_i_symbol_done_d_reduce (p, 73, 72); + return; + } + + static void sequence_143 (RDE_PARAM p) { + /* + * x + * ? + * (Attribute) + * (Identifier) + * (IS) + * (Expression) + * (SEMICOLON) + */ + + rde_param_i_state_push_value (p); + optional_137 (p); + if (rde_param_i_seq_value2value(p)) return; + sym_Identifier (p); + if (rde_param_i_seq_value2value(p)) return; + sym_IS (p); + if (rde_param_i_seq_value2value(p)) return; + sym_Expression (p); + if (rde_param_i_seq_value2value(p)) return; + sym_SEMICOLON (p); + rde_param_i_state_merge_value (p); + return; + } + + static void optional_137 (RDE_PARAM p) { + /* + * ? + * (Attribute) + */ + + rde_param_i_state_push_2 (p); + sym_Attribute (p); + rde_param_i_state_merge_ok (p); + return; + } + + /* + * leaf Symbol 'DIGIT' + */ + + static void sym_DIGIT (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 76)) return ; + sequence_148 (p); + rde_param_i_symbol_done_leaf (p, 76, 75); + return; + } + + static void sequence_148 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 74); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'DOT' + */ + + static void sym_DOT (RDE_PARAM p) { + /* + * x + * '.' + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 79)) return ; + sequence_153 (p); + rde_param_i_symbol_done_leaf (p, 79, 78); + return; + } + + static void sequence_153 (RDE_PARAM p) { + /* + * x + * '.' + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, ".", 77); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * void Symbol 'EOF' + */ + + static void sym_EOF (RDE_PARAM p) { + /* + * ! + * + */ + + if (rde_param_i_symbol_void_start (p, 81)) return ; + notahead_157 (p); + rde_param_i_symbol_done_void (p, 81, 80); + return; + } + + static void notahead_157 (RDE_PARAM p) { + /* + * ! + * + */ + + rde_param_i_loc_push (p); + rde_param_i_input_next (p, 43); + rde_param_i_notahead_exit (p); + return; + } + + /* + * void Symbol 'EOL' + */ + + static void sym_EOL (RDE_PARAM p) { + /* + * [\n\r] + */ + + if (rde_param_i_symbol_void_start (p, 84)) return ; + rde_param_i_next_class (p, "\n\r", 82); + rde_param_i_symbol_done_void (p, 84, 83); + return; + } + + /* + * value Symbol 'Expression' + */ + + static void sym_Expression (RDE_PARAM p) { + /* + * x + * (Sequence) + * * + * x + * (SLASH) + * (Sequence) + */ + + if (rde_param_i_symbol_start_d (p, 86)) return ; + sequence_169 (p); + rde_param_i_symbol_done_d_reduce (p, 86, 85); + return; + } + + static void sequence_169 (RDE_PARAM p) { + /* + * x + * (Sequence) + * * + * x + * (SLASH) + * (Sequence) + */ + + rde_param_i_state_push_value (p); + sym_Sequence (p); + if (rde_param_i_seq_value2value(p)) return; + kleene_167 (p); + rde_param_i_state_merge_value (p); + return; + } + + static void kleene_167 (RDE_PARAM p) { + /* + * * + * x + * (SLASH) + * (Sequence) + */ + + while (1) { + rde_param_i_state_push_2 (p); + sequence_165 (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + static void sequence_165 (RDE_PARAM p) { + /* + * x + * (SLASH) + * (Sequence) + */ + + rde_param_i_state_push_void (p); + sym_SLASH (p); + if (rde_param_i_seq_void2value(p)) return; + sym_Sequence (p); + rde_param_i_state_merge_value (p); + return; + } + + /* + * void Symbol 'Final' + */ + + static void sym_Final (RDE_PARAM p) { + /* + * x + * "END" + * (WHITESPACE) + * (SEMICOLON) + * (WHITESPACE) + */ + + if (rde_param_i_symbol_void_start (p, 89)) return ; + sequence_176 (p); + rde_param_i_symbol_done_void (p, 89, 88); + return; + } + + static void sequence_176 (RDE_PARAM p) { + /* + * x + * "END" + * (WHITESPACE) + * (SEMICOLON) + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "END", 87); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + if (rde_param_i_seq_void2void(p)) return; + sym_SEMICOLON (p); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * value Symbol 'Grammar' + */ + + static void sym_Grammar (RDE_PARAM p) { + /* + * x + * (WHITESPACE) + * (Header) + * * + * (Definition) + * (Final) + * (EOF) + */ + + if (rde_param_i_symbol_start_d (p, 91)) return ; + sequence_186 (p); + rde_param_i_symbol_done_d_reduce (p, 91, 90); + return; + } + + static void sequence_186 (RDE_PARAM p) { + /* + * x + * (WHITESPACE) + * (Header) + * * + * (Definition) + * (Final) + * (EOF) + */ + + rde_param_i_state_push_void (p); + sym_WHITESPACE (p); + if (rde_param_i_seq_void2value(p)) return; + sym_Header (p); + if (rde_param_i_seq_value2value(p)) return; + kleene_182 (p); + if (rde_param_i_seq_value2value(p)) return; + sym_Final (p); + if (rde_param_i_seq_value2value(p)) return; + sym_EOF (p); + rde_param_i_state_merge_value (p); + return; + } + + static void kleene_182 (RDE_PARAM p) { + /* + * * + * (Definition) + */ + + while (1) { + rde_param_i_state_push_2 (p); + sym_Definition (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + /* + * leaf Symbol 'GRAPH' + */ + + static void sym_GRAPH (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 94)) return ; + sequence_191 (p); + rde_param_i_symbol_done_leaf (p, 94, 93); + return; + } + + static void sequence_191 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 92); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * value Symbol 'Header' + */ + + static void sym_Header (RDE_PARAM p) { + /* + * x + * (PEG) + * (Identifier) + * (StartExpr) + */ + + if (rde_param_i_symbol_start_d (p, 96)) return ; + sequence_197 (p); + rde_param_i_symbol_done_d_reduce (p, 96, 95); + return; + } + + static void sequence_197 (RDE_PARAM p) { + /* + * x + * (PEG) + * (Identifier) + * (StartExpr) + */ + + rde_param_i_state_push_void (p); + sym_PEG (p); + if (rde_param_i_seq_void2value(p)) return; + sym_Identifier (p); + if (rde_param_i_seq_value2value(p)) return; + sym_StartExpr (p); + rde_param_i_state_merge_value (p); + return; + } + + /* + * leaf Symbol 'Ident' + */ + + static void sym_Ident (RDE_PARAM p) { + /* + * x + * / + * [_:] + * + * * + * / + * [_:] + * + */ + + if (rde_param_i_symbol_start (p, 99)) return ; + sequence_210 (p); + rde_param_i_symbol_done_leaf (p, 99, 98); + return; + } + + static void sequence_210 (RDE_PARAM p) { + /* + * x + * / + * [_:] + * + * * + * / + * [_:] + * + */ + + rde_param_i_state_push_void (p); + choice_202 (p); + if (rde_param_i_seq_void2void(p)) return; + kleene_208 (p); + rde_param_i_state_merge_void (p); + return; + } + + static void choice_202 (RDE_PARAM p) { + /* + * / + * [_:] + * + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_class (p, "_:", 97); + if (rde_param_i_bra_void2void(p)) return; + rde_param_i_next_alpha (p, 1); + rde_param_i_state_merge_void (p); + return; + } + + static void kleene_208 (RDE_PARAM p) { + /* + * * + * / + * [_:] + * + */ + + while (1) { + rde_param_i_state_push_2 (p); + choice_206 (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + static void choice_206 (RDE_PARAM p) { + /* + * / + * [_:] + * + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_class (p, "_:", 97); + if (rde_param_i_bra_void2void(p)) return; + rde_param_i_next_alnum (p, 0); + rde_param_i_state_merge_void (p); + return; + } + + /* + * value Symbol 'Identifier' + */ + + static void sym_Identifier (RDE_PARAM p) { + /* + * x + * (Ident) + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start_d (p, 101)) return ; + sequence_215 (p); + rde_param_i_symbol_done_d_reduce (p, 101, 100); + return; + } + + static void sequence_215 (RDE_PARAM p) { + /* + * x + * (Ident) + * (WHITESPACE) + */ + + rde_param_i_state_push_value (p); + sym_Ident (p); + if (rde_param_i_seq_value2value(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_value (p); + return; + } + + /* + * void Symbol 'IS' + */ + + static void sym_IS (RDE_PARAM p) { + /* + * x + * "<-" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_void_start (p, 104)) return ; + sequence_220 (p); + rde_param_i_symbol_done_void (p, 104, 103); + return; + } + + static void sequence_220 (RDE_PARAM p) { + /* + * x + * "<-" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "<-", 102); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'LEAF' + */ + + static void sym_LEAF (RDE_PARAM p) { + /* + * x + * "leaf" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 107)) return ; + sequence_225 (p); + rde_param_i_symbol_done_leaf (p, 107, 106); + return; + } + + static void sequence_225 (RDE_PARAM p) { + /* + * x + * "leaf" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "leaf", 105); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * value Symbol 'Literal' + */ + + static void sym_Literal (RDE_PARAM p) { + /* + * / + * x + * (APOSTROPH) + * * + * x + * ! + * (APOSTROPH) + * (Char) + * (APOSTROPH) + * (WHITESPACE) + * x + * (DAPOSTROPH) + * * + * x + * ! + * (DAPOSTROPH) + * (Char) + * (DAPOSTROPH) + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start_d (p, 109)) return ; + choice_254 (p); + rde_param_i_symbol_done_d_reduce (p, 109, 108); + return; + } + + static void choice_254 (RDE_PARAM p) { + /* + * / + * x + * (APOSTROPH) + * * + * x + * ! + * (APOSTROPH) + * (Char) + * (APOSTROPH) + * (WHITESPACE) + * x + * (DAPOSTROPH) + * * + * x + * ! + * (DAPOSTROPH) + * (Char) + * (DAPOSTROPH) + * (WHITESPACE) + */ + + rde_param_i_state_push_value (p); + sequence_239 (p); + if (rde_param_i_bra_value2value(p)) return; + sequence_252 (p); + rde_param_i_state_merge_value (p); + return; + } + + static void sequence_239 (RDE_PARAM p) { + /* + * x + * (APOSTROPH) + * * + * x + * ! + * (APOSTROPH) + * (Char) + * (APOSTROPH) + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + sym_APOSTROPH (p); + if (rde_param_i_seq_void2value(p)) return; + kleene_235 (p); + if (rde_param_i_seq_value2value(p)) return; + sym_APOSTROPH (p); + if (rde_param_i_seq_value2value(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_value (p); + return; + } + + static void kleene_235 (RDE_PARAM p) { + /* + * * + * x + * ! + * (APOSTROPH) + * (Char) + */ + + while (1) { + rde_param_i_state_push_2 (p); + sequence_233 (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + static void sequence_233 (RDE_PARAM p) { + /* + * x + * ! + * (APOSTROPH) + * (Char) + */ + + rde_param_i_state_push_void (p); + notahead_230 (p); + if (rde_param_i_seq_void2value(p)) return; + sym_Char (p); + rde_param_i_state_merge_value (p); + return; + } + + static void notahead_230 (RDE_PARAM p) { + /* + * ! + * (APOSTROPH) + */ + + rde_param_i_loc_push (p); + sym_APOSTROPH (p); + rde_param_i_notahead_exit (p); + return; + } + + static void sequence_252 (RDE_PARAM p) { + /* + * x + * (DAPOSTROPH) + * * + * x + * ! + * (DAPOSTROPH) + * (Char) + * (DAPOSTROPH) + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + sym_DAPOSTROPH (p); + if (rde_param_i_seq_void2value(p)) return; + kleene_248 (p); + if (rde_param_i_seq_value2value(p)) return; + sym_DAPOSTROPH (p); + if (rde_param_i_seq_value2value(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_value (p); + return; + } + + static void kleene_248 (RDE_PARAM p) { + /* + * * + * x + * ! + * (DAPOSTROPH) + * (Char) + */ + + while (1) { + rde_param_i_state_push_2 (p); + sequence_246 (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + static void sequence_246 (RDE_PARAM p) { + /* + * x + * ! + * (DAPOSTROPH) + * (Char) + */ + + rde_param_i_state_push_void (p); + notahead_243 (p); + if (rde_param_i_seq_void2value(p)) return; + sym_Char (p); + rde_param_i_state_merge_value (p); + return; + } + + static void notahead_243 (RDE_PARAM p) { + /* + * ! + * (DAPOSTROPH) + */ + + rde_param_i_loc_push (p); + sym_DAPOSTROPH (p); + rde_param_i_notahead_exit (p); + return; + } + + /* + * leaf Symbol 'LOWER' + */ + + static void sym_LOWER (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 112)) return ; + sequence_259 (p); + rde_param_i_symbol_done_leaf (p, 112, 111); + return; + } + + static void sequence_259 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 110); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'NOT' + */ + + static void sym_NOT (RDE_PARAM p) { + /* + * x + * '!' + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 115)) return ; + sequence_264 (p); + rde_param_i_symbol_done_leaf (p, 115, 114); + return; + } + + static void sequence_264 (RDE_PARAM p) { + /* + * x + * '!' + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "!", 113); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * void Symbol 'OPEN' + */ + + static void sym_OPEN (RDE_PARAM p) { + /* + * x + * '\(' + * (WHITESPACE) + */ + + if (rde_param_i_symbol_void_start (p, 118)) return ; + sequence_269 (p); + rde_param_i_symbol_done_void (p, 118, 117); + return; + } + + static void sequence_269 (RDE_PARAM p) { + /* + * x + * '\(' + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "\50", 116); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * void Symbol 'OPENB' + */ + + static void sym_OPENB (RDE_PARAM p) { + /* + * '[' + */ + + if (rde_param_i_symbol_void_start (p, 121)) return ; + rde_param_i_next_char (p, "\133", 119); + rde_param_i_symbol_done_void (p, 121, 120); + return; + } + + /* + * void Symbol 'PEG' + */ + + static void sym_PEG (RDE_PARAM p) { + /* + * x + * "PEG" + * ! + * / + * [_:] + * + * (WHITESPACE) + */ + + if (rde_param_i_symbol_void_start (p, 124)) return ; + sequence_281 (p); + rde_param_i_symbol_done_void (p, 124, 123); + return; + } + + static void sequence_281 (RDE_PARAM p) { + /* + * x + * "PEG" + * ! + * / + * [_:] + * + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "PEG", 122); + if (rde_param_i_seq_void2void(p)) return; + notahead_278 (p); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + static void notahead_278 (RDE_PARAM p) { + /* + * ! + * / + * [_:] + * + */ + + rde_param_i_loc_push (p); + choice_206 (p); + rde_param_i_notahead_exit (p); + return; + } + + /* + * leaf Symbol 'PLUS' + */ + + static void sym_PLUS (RDE_PARAM p) { + /* + * x + * '+' + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 127)) return ; + sequence_286 (p); + rde_param_i_symbol_done_leaf (p, 127, 126); + return; + } + + static void sequence_286 (RDE_PARAM p) { + /* + * x + * '+' + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "+", 125); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * value Symbol 'Prefix' + */ + + static void sym_Prefix (RDE_PARAM p) { + /* + * x + * ? + * / + * (AND) + * (NOT) + * (Suffix) + */ + + if (rde_param_i_symbol_start_d (p, 129)) return ; + sequence_296 (p); + rde_param_i_symbol_done_d_reduce (p, 129, 128); + return; + } + + static void sequence_296 (RDE_PARAM p) { + /* + * x + * ? + * / + * (AND) + * (NOT) + * (Suffix) + */ + + rde_param_i_state_push_value (p); + optional_293 (p); + if (rde_param_i_seq_value2value(p)) return; + sym_Suffix (p); + rde_param_i_state_merge_value (p); + return; + } + + static void optional_293 (RDE_PARAM p) { + /* + * ? + * / + * (AND) + * (NOT) + */ + + rde_param_i_state_push_2 (p); + choice_291 (p); + rde_param_i_state_merge_ok (p); + return; + } + + static void choice_291 (RDE_PARAM p) { + /* + * / + * (AND) + * (NOT) + */ + + rde_param_i_state_push_value (p); + sym_AND (p); + if (rde_param_i_bra_value2value(p)) return; + sym_NOT (p); + rde_param_i_state_merge_value (p); + return; + } + + /* + * value Symbol 'Primary' + */ + + static void sym_Primary (RDE_PARAM p) { + /* + * / + * (ALNUM) + * (ALPHA) + * (ASCII) + * (CONTROL) + * (DDIGIT) + * (DIGIT) + * (GRAPH) + * (LOWER) + * (PRINTABLE) + * (PUNCT) + * (SPACE) + * (UPPER) + * (WORDCHAR) + * (XDIGIT) + * (Identifier) + * x + * (OPEN) + * (Expression) + * (CLOSE) + * (Literal) + * (Class) + * (DOT) + */ + + if (rde_param_i_symbol_start_d (p, 131)) return ; + choice_322 (p); + rde_param_i_symbol_done_d_reduce (p, 131, 130); + return; + } + + static void choice_322 (RDE_PARAM p) { + /* + * / + * (ALNUM) + * (ALPHA) + * (ASCII) + * (CONTROL) + * (DDIGIT) + * (DIGIT) + * (GRAPH) + * (LOWER) + * (PRINTABLE) + * (PUNCT) + * (SPACE) + * (UPPER) + * (WORDCHAR) + * (XDIGIT) + * (Identifier) + * x + * (OPEN) + * (Expression) + * (CLOSE) + * (Literal) + * (Class) + * (DOT) + */ + + rde_param_i_state_push_value (p); + sym_ALNUM (p); + if (rde_param_i_bra_value2value(p)) return; + sym_ALPHA (p); + if (rde_param_i_bra_value2value(p)) return; + sym_ASCII (p); + if (rde_param_i_bra_value2value(p)) return; + sym_CONTROL (p); + if (rde_param_i_bra_value2value(p)) return; + sym_DDIGIT (p); + if (rde_param_i_bra_value2value(p)) return; + sym_DIGIT (p); + if (rde_param_i_bra_value2value(p)) return; + sym_GRAPH (p); + if (rde_param_i_bra_value2value(p)) return; + sym_LOWER (p); + if (rde_param_i_bra_value2value(p)) return; + sym_PRINTABLE (p); + if (rde_param_i_bra_value2value(p)) return; + sym_PUNCT (p); + if (rde_param_i_bra_value2value(p)) return; + sym_SPACE (p); + if (rde_param_i_bra_value2value(p)) return; + sym_UPPER (p); + if (rde_param_i_bra_value2value(p)) return; + sym_WORDCHAR (p); + if (rde_param_i_bra_value2value(p)) return; + sym_XDIGIT (p); + if (rde_param_i_bra_value2value(p)) return; + sym_Identifier (p); + if (rde_param_i_bra_value2value(p)) return; + sequence_317 (p); + if (rde_param_i_bra_value2value(p)) return; + sym_Literal (p); + if (rde_param_i_bra_value2value(p)) return; + sym_Class (p); + if (rde_param_i_bra_value2value(p)) return; + sym_DOT (p); + rde_param_i_state_merge_value (p); + return; + } + + static void sequence_317 (RDE_PARAM p) { + /* + * x + * (OPEN) + * (Expression) + * (CLOSE) + */ + + rde_param_i_state_push_void (p); + sym_OPEN (p); + if (rde_param_i_seq_void2value(p)) return; + sym_Expression (p); + if (rde_param_i_seq_value2value(p)) return; + sym_CLOSE (p); + rde_param_i_state_merge_value (p); + return; + } + + /* + * leaf Symbol 'PRINTABLE' + */ + + static void sym_PRINTABLE (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 134)) return ; + sequence_327 (p); + rde_param_i_symbol_done_leaf (p, 134, 133); + return; + } + + static void sequence_327 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 132); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'PUNCT' + */ + + static void sym_PUNCT (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 137)) return ; + sequence_332 (p); + rde_param_i_symbol_done_leaf (p, 137, 136); + return; + } + + static void sequence_332 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 135); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'QUESTION' + */ + + static void sym_QUESTION (RDE_PARAM p) { + /* + * x + * '?' + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 140)) return ; + sequence_337 (p); + rde_param_i_symbol_done_leaf (p, 140, 139); + return; + } + + static void sequence_337 (RDE_PARAM p) { + /* + * x + * '?' + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "?", 138); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * value Symbol 'Range' + */ + + static void sym_Range (RDE_PARAM p) { + /* + * / + * x + * (Char) + * (TO) + * (Char) + * (Char) + */ + + if (rde_param_i_symbol_start_d (p, 142)) return ; + choice_346 (p); + rde_param_i_symbol_done_d_reduce (p, 142, 141); + return; + } + + static void choice_346 (RDE_PARAM p) { + /* + * / + * x + * (Char) + * (TO) + * (Char) + * (Char) + */ + + rde_param_i_state_push_value (p); + sequence_343 (p); + if (rde_param_i_bra_value2value(p)) return; + sym_Char (p); + rde_param_i_state_merge_value (p); + return; + } + + static void sequence_343 (RDE_PARAM p) { + /* + * x + * (Char) + * (TO) + * (Char) + */ + + rde_param_i_state_push_value (p); + sym_Char (p); + if (rde_param_i_seq_value2value(p)) return; + sym_TO (p); + if (rde_param_i_seq_value2value(p)) return; + sym_Char (p); + rde_param_i_state_merge_value (p); + return; + } + + /* + * void Symbol 'SEMICOLON' + */ + + static void sym_SEMICOLON (RDE_PARAM p) { + /* + * x + * ';' + * (WHITESPACE) + */ + + if (rde_param_i_symbol_void_start (p, 145)) return ; + sequence_351 (p); + rde_param_i_symbol_done_void (p, 145, 144); + return; + } + + static void sequence_351 (RDE_PARAM p) { + /* + * x + * ';' + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "\73", 143); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * value Symbol 'Sequence' + */ + + static void sym_Sequence (RDE_PARAM p) { + /* + * + + * (Prefix) + */ + + if (rde_param_i_symbol_start_d (p, 147)) return ; + poskleene_355 (p); + rde_param_i_symbol_done_d_reduce (p, 147, 146); + return; + } + + static void poskleene_355 (RDE_PARAM p) { + /* + * + + * (Prefix) + */ + + rde_param_i_loc_push (p); + sym_Prefix (p); + if (rde_param_i_kleene_abort(p)) return; + while (1) { + rde_param_i_state_push_2 (p); + sym_Prefix (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + /* + * void Symbol 'SLASH' + */ + + static void sym_SLASH (RDE_PARAM p) { + /* + * x + * '/' + * (WHITESPACE) + */ + + if (rde_param_i_symbol_void_start (p, 150)) return ; + sequence_360 (p); + rde_param_i_symbol_done_void (p, 150, 149); + return; + } + + static void sequence_360 (RDE_PARAM p) { + /* + * x + * '/' + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "/", 148); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'SPACE' + */ + + static void sym_SPACE (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 153)) return ; + sequence_365 (p); + rde_param_i_symbol_done_leaf (p, 153, 152); + return; + } + + static void sequence_365 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 151); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'STAR' + */ + + static void sym_STAR (RDE_PARAM p) { + /* + * x + * '*' + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 156)) return ; + sequence_370 (p); + rde_param_i_symbol_done_leaf (p, 156, 155); + return; + } + + static void sequence_370 (RDE_PARAM p) { + /* + * x + * '*' + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_char (p, "*", 154); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * value Symbol 'StartExpr' + */ + + static void sym_StartExpr (RDE_PARAM p) { + /* + * x + * (OPEN) + * (Expression) + * (CLOSE) + */ + + if (rde_param_i_symbol_start_d (p, 158)) return ; + sequence_317 (p); + rde_param_i_symbol_done_d_reduce (p, 158, 157); + return; + } + + /* + * value Symbol 'Suffix' + */ + + static void sym_Suffix (RDE_PARAM p) { + /* + * x + * (Primary) + * ? + * / + * (QUESTION) + * (STAR) + * (PLUS) + */ + + if (rde_param_i_symbol_start_d (p, 160)) return ; + sequence_386 (p); + rde_param_i_symbol_done_d_reduce (p, 160, 159); + return; + } + + static void sequence_386 (RDE_PARAM p) { + /* + * x + * (Primary) + * ? + * / + * (QUESTION) + * (STAR) + * (PLUS) + */ + + rde_param_i_state_push_value (p); + sym_Primary (p); + if (rde_param_i_seq_value2value(p)) return; + optional_384 (p); + rde_param_i_state_merge_value (p); + return; + } + + static void optional_384 (RDE_PARAM p) { + /* + * ? + * / + * (QUESTION) + * (STAR) + * (PLUS) + */ + + rde_param_i_state_push_2 (p); + choice_382 (p); + rde_param_i_state_merge_ok (p); + return; + } + + static void choice_382 (RDE_PARAM p) { + /* + * / + * (QUESTION) + * (STAR) + * (PLUS) + */ + + rde_param_i_state_push_value (p); + sym_QUESTION (p); + if (rde_param_i_bra_value2value(p)) return; + sym_STAR (p); + if (rde_param_i_bra_value2value(p)) return; + sym_PLUS (p); + rde_param_i_state_merge_value (p); + return; + } + + /* + * void Symbol 'TO' + */ + + static void sym_TO (RDE_PARAM p) { + /* + * '-' + */ + + if (rde_param_i_symbol_void_start (p, 163)) return ; + rde_param_i_next_char (p, "-", 161); + rde_param_i_symbol_done_void (p, 163, 162); + return; + } + + /* + * leaf Symbol 'UPPER' + */ + + static void sym_UPPER (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 166)) return ; + sequence_393 (p); + rde_param_i_symbol_done_leaf (p, 166, 165); + return; + } + + static void sequence_393 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 164); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'VOID' + */ + + static void sym_VOID (RDE_PARAM p) { + /* + * x + * "void" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 169)) return ; + sequence_398 (p); + rde_param_i_symbol_done_leaf (p, 169, 168); + return; + } + + static void sequence_398 (RDE_PARAM p) { + /* + * x + * "void" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "void", 167); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * void Symbol 'WHITESPACE' + */ + + static void sym_WHITESPACE (RDE_PARAM p) { + /* + * * + * / + * + * (COMMENT) + */ + + if (rde_param_i_symbol_void_start (p, 171)) return ; + kleene_405 (p); + rde_param_i_symbol_done_void (p, 171, 170); + return; + } + + static void kleene_405 (RDE_PARAM p) { + /* + * * + * / + * + * (COMMENT) + */ + + while (1) { + rde_param_i_state_push_2 (p); + choice_403 (p); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + static void choice_403 (RDE_PARAM p) { + /* + * / + * + * (COMMENT) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_space (p, 10); + if (rde_param_i_bra_void2void(p)) return; + sym_COMMENT (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'WORDCHAR' + */ + + static void sym_WORDCHAR (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 174)) return ; + sequence_410 (p); + rde_param_i_symbol_done_leaf (p, 174, 173); + return; + } + + static void sequence_410 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 172); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* + * leaf Symbol 'XDIGIT' + */ + + static void sym_XDIGIT (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + if (rde_param_i_symbol_start (p, 177)) return ; + sequence_415 (p); + rde_param_i_symbol_done_leaf (p, 177, 176); + return; + } + + static void sequence_415 (RDE_PARAM p) { + /* + * x + * "" + * (WHITESPACE) + */ + + rde_param_i_state_push_void (p); + rde_param_i_next_str (p, "", 175); + if (rde_param_i_seq_void2void(p)) return; + sym_WHITESPACE (p); + rde_param_i_state_merge_void (p); + return; + } + + /* -*- c -*- */ + + typedef struct PARSERg { + long int counter; + char buf [50]; + } PARSERg; + + static void + PARSERgRelease (ClientData cd, Tcl_Interp* interp) + { + ckfree((char*) cd); + } + + static const char* + PARSERnewName (Tcl_Interp* interp) + { +#define KEY "tcllib/parser/PACKAGE/TEA" + + Tcl_InterpDeleteProc* proc = PARSERgRelease; + PARSERg* parserg; + + parserg = Tcl_GetAssocData (interp, KEY, &proc); + if (parserg == NULL) { + parserg = (PARSERg*) ckalloc (sizeof (PARSERg)); + parserg->counter = 0; + + Tcl_SetAssocData (interp, KEY, proc, + (ClientData) parserg); + } + + parserg->counter ++; + sprintf (parserg->buf, "PARSER%d", parserg->counter); + return parserg->buf; +#undef KEY + } + + static void + PARSERdeleteCmd (ClientData clientData) + { + /* + * Release the whole PARSER + * (Low-level engine only actually). + */ + rde_param_del ((RDE_PARAM) clientData); + } + + + /* * ** *** ***** ******** ************* + ** Functions implementing the object methods, and helper. + */ + + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp); + + static int parser_PARSE (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + int mode; + Tcl_Channel chan; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "chan"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, + Tcl_GetString (objv[2]), + &mode); + + if (!chan) { + return TCL_ERROR; + } + + rde_param_reset (p, chan); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + static int parser_PARSET (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + char* buf; + int len; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "text"); + return TCL_ERROR; + } + + buf = Tcl_GetStringFromObj (objv[2], &len); + + rde_param_reset (p, NULL); + rde_param_data (p, buf, len); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + /* See also rde_critcl/m.c, param_COMPLETE() */ + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp) + { + if (rde_param_query_st (p)) { + long int ac; + Tcl_Obj** av; + + rde_param_query_ast (p, &ac, &av); + + if (ac > 1) { + Tcl_Obj** lv = NALLOC (3+ac, Tcl_Obj*); + + memcpy(lv + 3, av, ac * sizeof (Tcl_Obj*)); + lv [0] = Tcl_NewObj (); + lv [1] = Tcl_NewIntObj (1 + rde_param_query_lstop (p)); + lv [2] = Tcl_NewIntObj (rde_param_query_cl (p)); + + Tcl_SetObjResult (interp, Tcl_NewListObj (3, lv)); + ckfree ((char*) lv); + + } else if (ac == 0) { + /* + * Match, but no AST. This is possible if the grammar + * consists of only the start expression. + */ + Tcl_SetObjResult (interp, Tcl_NewStringObj ("",-1)); + } else { + Tcl_SetObjResult (interp, av [0]); + } + + return TCL_OK; + } else { + Tcl_Obj* xv [1]; + const ERROR_STATE* er = rde_param_query_er (p); + Tcl_Obj* res = rde_param_query_er_tcl (p, er); + /* res = list (location, list(msg)) */ + + /* Stick the exception type-tag before the existing elements */ + xv [0] = Tcl_NewStringObj ("pt::rde",-1); + Tcl_ListObjReplace(interp, res, 0, 0, 1, xv); + + Tcl_SetErrorCode (interp, "PT", "RDE", "SYNTAX", NULL); + Tcl_SetObjResult (interp, res); + return TCL_ERROR; + } + } + + + /* * ** *** ***** ******** ************* + ** Object command, method dispatch. + */ + static int parser_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + RDE_PARAM p = (RDE_PARAM) cd; + int m, res; + + static CONST char* methods [] = { + "destroy", "parse", "parset", NULL + }; + enum methods { + M_DESTROY, M_PARSE, M_PARSET + }; + + if (objc < 2) { + Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option", + 0, &m) != TCL_OK) { + return TCL_ERROR; + } + + /* Dispatch to methods. They check the #args in + * detail before performing the requested + * functionality + */ + + switch (m) { + case M_DESTROY: + if (objc != 2) { + Tcl_WrongNumArgs (interp, 2, objv, NULL); + return TCL_ERROR; + } + + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) rde_param_query_clientdata (p)); + return TCL_OK; + + case M_PARSE: res = parser_PARSE (p, interp, objc, objv); break; + case M_PARSET: res = parser_PARSET (p, interp, objc, objv); break; + default: + /* Not coming to this place */ + ASSERT (0,"Reached unreachable location"); + } + + return res; + } + + /** * ** *** ***** ******** ************* + * Class command, i.e. object construction. + */ + static int ParserClassCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const*objv) { + /* + * Syntax: No arguments beyond the name + */ + + RDE_PARAM parser; + CONST char* name; + Tcl_Obj* fqn; + Tcl_CmdInfo ci; + Tcl_Command c; + +#define USAGE "?name?" + + if ((objc != 2) && (objc != 1)) { + Tcl_WrongNumArgs (interp, 1, objv, USAGE); + return TCL_ERROR; + } + + if (objc < 2) { + name = PARSERnewName (interp); + } else { + name = Tcl_GetString (objv [1]); + } + + if (!Tcl_StringMatch (name, "::*")) { + /* Relative name. Prefix with current namespace */ + + Tcl_Eval (interp, "namespace current"); + fqn = Tcl_GetObjResult (interp); + fqn = Tcl_DuplicateObj (fqn); + Tcl_IncrRefCount (fqn); + + if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { + Tcl_AppendToObj (fqn, "::", -1); + } + Tcl_AppendToObj (fqn, name, -1); + } else { + fqn = Tcl_NewStringObj (name, -1); + Tcl_IncrRefCount (fqn); + } + Tcl_ResetResult (interp); + + if (Tcl_GetCommandInfo (interp, + Tcl_GetString (fqn), + &ci)) { + Tcl_Obj* err; + + err = Tcl_NewObj (); + Tcl_AppendToObj (err, "command \"", -1); + Tcl_AppendObjToObj (err, fqn); + Tcl_AppendToObj (err, "\" already exists", -1); + + Tcl_DecrRefCount (fqn); + Tcl_SetObjResult (interp, err); + return TCL_ERROR; + } + + parser = rde_param_new (sizeof(p_string)/sizeof(char*), (char**) p_string); + c = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), + parser_objcmd, (ClientData) parser, + PARSERdeleteCmd); + rde_param_clientdata (parser, (ClientData) c); + Tcl_SetObjResult (interp, fqn); + Tcl_DecrRefCount (fqn); + return TCL_OK; + } + +int Package_Init(Tcl_Interp* interp) { + if (interp == 0) return TCL_ERROR; + + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + + if (Tcl_CreateObjCommand(interp, "PARSER", ParserClassCmd , NULL, NULL) == NULL) { + Tcl_SetResult(interp, "Can't create constructor", NULL); + return TCL_ERROR; + } + + + Tcl_PkgProvide(interp, "PACKAGE", "0.1"); + + return TCL_OK; +} ADDED modules/pt/tests/data/ok/peg_cparam-tea/4_choice Index: modules/pt/tests/data/ok/peg_cparam-tea/4_choice ================================================================== --- /dev/null +++ modules/pt/tests/data/ok/peg_cparam-tea/4_choice @@ -0,0 +1,1982 @@ +/************************************************************ +** +** TEA-based C/PARAM implementation of the parsing +** expression grammar +** +** TEMPLATE +** +** Generated from file TEST +** for user unknown +** +* * ** *** ***** ******** ************* *********************/ + #include + #include + #include + #include + #define SCOPE static + +#line 1 "rde_critcl/util.h" + + #ifndef _RDE_UTIL_H + #define _RDE_UTIL_H 1 + #ifndef SCOPE + #define SCOPE + #endif + #define ALLOC(type) (type *) ckalloc (sizeof (type)) + #define NALLOC(n,type) (type *) ckalloc ((n) * sizeof (type)) + #undef RDE_DEBUG + #define RDE_DEBUG 1 + #undef RDE_TRACE + #ifdef RDE_DEBUG + #define STOPAFTER(x) { static int count = (x); count --; if (!count) { Tcl_Panic ("stop"); } } + #define XSTR(x) #x + #define STR(x) XSTR(x) + #define RANGEOK(i,n) ((0 <= (i)) && (i < (n))) + #define ASSERT(x,msg) if (!(x)) { Tcl_Panic (msg " (" #x "), in file " __FILE__ " @line " STR(__LINE__));} + #define ASSERT_BOUNDS(i,n) ASSERT (RANGEOK(i,n),"array index out of bounds: " STR(i) " >= " STR(n)) + #else + #define STOPAFTER(x) + #define ASSERT(x,msg) + #define ASSERT_BOUNDS(i,n) + #endif + #ifdef RDE_TRACE + SCOPE void trace_enter (const char* fun); + SCOPE void trace_return (const char *pat, ...); + SCOPE void trace_printf (const char *pat, ...); + #define ENTER(fun) trace_enter (fun) + #define RETURN(format,x) trace_return (format,x) ; return x + #define RETURNVOID trace_return ("%s","(void)") ; return + #define TRACE0(x) trace_printf0 x + #define TRACE(x) trace_printf x + #else + #define ENTER(fun) + #define RETURN(f,x) return x + #define RETURNVOID return + #define TRACE0(x) + #define TRACE(x) + #endif + #endif + + +#line 1 "rde_critcl/stack.h" + + #ifndef _RDE_DS_STACK_H + #define _RDE_DS_STACK_H 1 + typedef void (*RDE_STACK_CELL_FREE) (void* cell); + typedef struct RDE_STACK_* RDE_STACK; + static const int RDE_STACK_INITIAL_SIZE = 256; + #endif + + +#line 1 "rde_critcl/tc.h" + + #ifndef _RDE_DS_TC_H + #define _RDE_DS_TC_H 1 + typedef struct RDE_TC_* RDE_TC; + #endif + + +#line 1 "rde_critcl/param.h" + + #ifndef _RDE_DS_PARAM_H + #define _RDE_DS_PARAM_H 1 + typedef struct RDE_PARAM_* RDE_PARAM; + typedef struct ERROR_STATE { + int refCount; + long int loc; + RDE_STACK msg; + } ERROR_STATE; + typedef struct NC_STATE { + long int CL; + long int ST; + Tcl_Obj* SV; + ERROR_STATE* ER; + } NC_STATE; + #endif + + +#line 1 "rde_critcl/util.c" + + #ifdef RDE_TRACE + typedef struct F_STACK { + const char* str; + struct F_STACK* down; + } F_STACK; + static F_STACK* top = 0; + static int level = 0; + static void + push (const char* str) + { + F_STACK* new = ALLOC (F_STACK); + new->str = str; + new->down = top; + top = new; + level += 4; + } + static void + pop (void) + { + F_STACK* next = top->down; + level -= 4; + ckfree ((char*)top); + top = next; + } + static void + indent (void) + { + int i; + for (i = 0; i < level; i++) { + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + if (top) { + fwrite(top->str, 1, strlen(top->str), stdout); + fflush (stdout); + } + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + SCOPE void + trace_enter (const char* fun) + { + push (fun); + indent(); + fwrite("ENTER\n", 1, 6, stdout); + fflush (stdout); + } + static char msg [1024*1024]; + SCOPE void + trace_return (const char *pat, ...) + { + int len; + va_list args; + indent(); + fwrite("RETURN = ", 1, 9, stdout); + fflush (stdout); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + pop(); + } + SCOPE void + trace_printf (const char *pat, ...) + { + int len; + va_list args; + indent(); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + SCOPE void + trace_printf0 (const char *pat, ...) + { + int len; + va_list args; + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + #endif + + +#line 1 "rde_critcl/stack.c" + + typedef struct RDE_STACK_ { + long int max; + long int top; + RDE_STACK_CELL_FREE freeCellProc; + void** cell; + } RDE_STACK_; + + SCOPE RDE_STACK + rde_stack_new (RDE_STACK_CELL_FREE freeCellProc) + { + RDE_STACK s = ALLOC (RDE_STACK_); + s->cell = NALLOC (RDE_STACK_INITIAL_SIZE, void*); + s->max = RDE_STACK_INITIAL_SIZE; + s->top = 0; + s->freeCellProc = freeCellProc; + return s; + } + SCOPE void + rde_stack_del (RDE_STACK s) + { + if (s->freeCellProc && s->top) { + long int i; + for (i=0; i < s->top; i++) { + ASSERT_BOUNDS(i,s->max); + s->freeCellProc ( s->cell [i] ); + } + } + ckfree ((char*) s->cell); + ckfree ((char*) s); + } + SCOPE void + rde_stack_push (RDE_STACK s, void* item) + { + if (s->top >= s->max) { + long int new = s->max ? (2 * s->max) : RDE_STACK_INITIAL_SIZE; + void** cell = (void**) ckrealloc ((char*) s->cell, new * sizeof(void*)); + ASSERT (cell,"Memory allocation failure for RDE stack"); + s->max = new; + s->cell = cell; + } + ASSERT_BOUNDS(s->top,s->max); + s->cell [s->top] = item; + s->top ++; + } + SCOPE void* + rde_stack_top (RDE_STACK s) + { + ASSERT_BOUNDS(s->top-1,s->max); + return s->cell [s->top - 1]; + } + SCOPE void + rde_stack_pop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + if (s->freeCellProc) { + while (n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + n --; + } + } else { + s->top -= n; + } + } + SCOPE void + rde_stack_trim (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad trimsize"); + if (s->freeCellProc) { + while (s->top > n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + } + } else { + s->top = n; + } + } + SCOPE void + rde_stack_drop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + s->top -= n; + } + SCOPE void + rde_stack_move (RDE_STACK dst, RDE_STACK src) + { + ASSERT (dst->freeCellProc == src->freeCellProc, "Ownership mismatch"); + + while (src->top > 0) { + src->top --; + ASSERT_BOUNDS(src->top,src->max); + rde_stack_push (dst, src->cell [src->top] ); + } + } + SCOPE void + rde_stack_get (RDE_STACK s, long int* cn, void*** cc) + { + *cn = s->top; + *cc = s->cell; + } + SCOPE long int + rde_stack_size (RDE_STACK s) + { + return s->top; + } + + +#line 1 "rde_critcl/tc.c" + + typedef struct RDE_TC_ { + int max; + int num; + char* str; + RDE_STACK off; + } RDE_TC_; + + SCOPE RDE_TC + rde_tc_new (void) + { + RDE_TC tc = ALLOC (RDE_TC_); + tc->max = RDE_STACK_INITIAL_SIZE; + tc->num = 0; + tc->str = NALLOC (RDE_STACK_INITIAL_SIZE, char); + tc->off = rde_stack_new (NULL); + return tc; + } + SCOPE void + rde_tc_del (RDE_TC tc) + { + rde_stack_del (tc->off); + ckfree (tc->str); + ckfree ((char*) tc); + } + SCOPE long int + rde_tc_size (RDE_TC tc) + { + return rde_stack_size (tc->off); + } + SCOPE void + rde_tc_clear (RDE_TC tc) + { + tc->num = 0; + rde_stack_trim (tc->off, 0); + } + SCOPE char* + rde_tc_append (RDE_TC tc, char* string, long int len) + { + long int base = tc->num; + long int off = tc->num; + char* ch; + int clen; + Tcl_UniChar uni; + if (len < 0) { + len = strlen (string); + } + + if (!len) { + return tc->str + base; + } + + if ((tc->num + len) >= tc->max) { + int new = len + (tc->max ? (2 * tc->max) : RDE_STACK_INITIAL_SIZE); + char* str = ckrealloc (tc->str, new * sizeof(char)); + ASSERT (str,"Memory allocation failure for token character array"); + tc->max = new; + tc->str = str; + } + tc->num += len; + ASSERT_BOUNDS(tc->num,tc->max); + ASSERT_BOUNDS(off,tc->max); + ASSERT_BOUNDS(off+len-1,tc->max); + ASSERT_BOUNDS(off+len-1,tc->num); + memcpy (tc->str + off, string, len); + + ch = string; + while (ch < (string + len)) { + ASSERT_BOUNDS(off,tc->num); + rde_stack_push (tc->off, (void*) off); + clen = Tcl_UtfToUniChar (ch, &uni); + off += clen; + ch += clen; + } + return tc->str + base; + } + SCOPE void + rde_tc_get (RDE_TC tc, int at, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + off = ov [at]; + if ((at+1) == oc) { + end = tc->num; + } else { + end = ov [at+1]; + } + TRACE (("rde_tc_get (RDE_TC %p, @ %d) => %d.[%d ... %d]/%d",tc,at,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + SCOPE void + rde_tc_get_s (RDE_TC tc, int at, int last, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + ASSERT_BOUNDS(last,oc); + off = ov [at]; + if ((last+1) == oc) { + end = tc->num; + } else { + end = ov [last+1]; + } + TRACE (("rde_tc_get_s (RDE_TC %p, @ %d .. %d) => %d.[%d ... %d]/%d",tc,at,last,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + + +#line 1 "rde_critcl/param.c" + + typedef struct RDE_PARAM_ { + Tcl_Channel IN; + Tcl_Obj* readbuf; + char* CC; + long int CC_len; + RDE_TC TC; + long int CL; + RDE_STACK LS; + ERROR_STATE* ER; + RDE_STACK ES; + long int ST; + Tcl_Obj* SV; + Tcl_HashTable NC; + + RDE_STACK ast ; + RDE_STACK mark ; + + long int numstr; + char** string; + + ClientData clientData; + } RDE_PARAM_; + typedef int (*UniCharClass) (int); + typedef enum test_class_id { + tc_alnum, + tc_alpha, + tc_ascii, + tc_control, + tc_ddigit, + tc_digit, + tc_graph, + tc_lower, + tc_printable, + tc_punct, + tc_space, + tc_upper, + tc_wordchar, + tc_xdigit + } test_class_id; + static void ast_node_free (void* n); + static void error_state_free (void* es); + static void error_set (RDE_PARAM p, int s); + static void nc_clear (RDE_PARAM p); + static int UniCharIsAscii (int character); + static int UniCharIsHexDigit (int character); + static int UniCharIsDecDigit (int character); + static void test_class (RDE_PARAM p, UniCharClass class, test_class_id id); + static int er_int_compare (const void* a, const void* b); + #define SV_INIT(p) \ + p->SV = NULL; \ + TRACE (("SV_INIT (%p => %p)", (p), (p)->SV)) + #define SV_SET(p,newsv) \ + if (((p)->SV) != (newsv)) { \ + TRACE (("SV_CLEAR/set (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = (newsv); \ + TRACE (("SV_SET (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_IncrRefCount ((p)->SV); \ + } \ + } + #define SV_CLEAR(p) \ + TRACE (("SV_CLEAR (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = NULL + #define ER_INIT(p) \ + p->ER = NULL; \ + TRACE (("ER_INIT (%p => %p)", (p), (p)->ER)) + #define ER_CLEAR(p) \ + error_state_free ((p)->ER); \ + (p)->ER = NULL + SCOPE RDE_PARAM + rde_param_new (long int nstr, char** strings) + { + RDE_PARAM p; + ENTER ("rde_param_new"); + TRACE (("\tINT %d strings @ %p", nstr, strings)); + p = ALLOC (RDE_PARAM_); + p->numstr = nstr; + p->string = strings; + p->readbuf = Tcl_NewObj (); + Tcl_IncrRefCount (p->readbuf); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_InitHashTable (&p->NC, TCL_ONE_WORD_KEYS); + p->IN = NULL; + p->CL = -1; + p->ST = 0; + ER_INIT (p); + SV_INIT (p); + p->CC = NULL; + p->CC_len = 0; + p->TC = rde_tc_new (); + p->ES = rde_stack_new (error_state_free); + p->LS = rde_stack_new (NULL); + p->ast = rde_stack_new (ast_node_free); + p->mark = rde_stack_new (NULL); + RETURN ("%p", p); + } + SCOPE void + rde_param_del (RDE_PARAM p) + { + ENTER ("rde_param_del"); + TRACE (("RDE_PARAM %p",p)); + ER_CLEAR (p); TRACE (("\ter_clear")); + SV_CLEAR (p); TRACE (("\tsv_clear")); + nc_clear (p); TRACE (("\tnc_clear")); + Tcl_DeleteHashTable (&p->NC); TRACE (("\tnc hashtable delete")); + rde_tc_del (p->TC); TRACE (("\ttc clear")); + rde_stack_del (p->ES); TRACE (("\tes clear")); + rde_stack_del (p->LS); TRACE (("\tls clear")); + rde_stack_del (p->ast); TRACE (("\tast clear")); + rde_stack_del (p->mark); TRACE (("\tmark clear")); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_DecrRefCount (p->readbuf); + ckfree ((char*) p); + RETURNVOID; + } + SCOPE void + rde_param_reset (RDE_PARAM p, Tcl_Channel chan) + { + ENTER ("rde_param_reset"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("Tcl_Channel %p",chan)); + p->IN = chan; + p->CL = -1; + p->ST = 0; + p->CC = NULL; + p->CC_len = 0; + ER_CLEAR (p); + SV_CLEAR (p); + nc_clear (p); + rde_tc_clear (p->TC); + rde_stack_trim (p->ES, 0); + rde_stack_trim (p->LS, 0); + rde_stack_trim (p->ast, 0); + rde_stack_trim (p->mark, 0); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + RETURNVOID; + } + SCOPE void + rde_param_update_strings (RDE_PARAM p, long int nstr, char** strings) + { + ENTER ("rde_param_update_strings"); + TRACE (("RDE_PARAM %p", p)); + TRACE (("INT %d strings", nstr)); + p->numstr = nstr; + p->string = strings; + RETURNVOID; + } + SCOPE void + rde_param_data (RDE_PARAM p, char* buf, long int len) + { + (void) rde_tc_append (p->TC, buf, len); + } + SCOPE void + rde_param_clientdata (RDE_PARAM p, ClientData clientData) + { + p->clientData = clientData; + } + static void + nc_clear (RDE_PARAM p) + { + Tcl_HashSearch hs; + Tcl_HashEntry* he; + Tcl_HashTable* tablePtr; + for(he = Tcl_FirstHashEntry(&p->NC, &hs); + he != NULL; + he = Tcl_FirstHashEntry(&p->NC, &hs)) { + Tcl_HashSearch hsc; + Tcl_HashEntry* hec; + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (he); + for(hec = Tcl_FirstHashEntry(tablePtr, &hsc); + hec != NULL; + hec = Tcl_NextHashEntry(&hsc)) { + NC_STATE* scs = Tcl_GetHashValue (hec); + error_state_free (scs->ER); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + ckfree ((char*) scs); + } + Tcl_DeleteHashTable (tablePtr); + ckfree ((char*) tablePtr); + Tcl_DeleteHashEntry (he); + } + } + SCOPE ClientData + rde_param_query_clientdata (RDE_PARAM p) + { + return p->clientData; + } + SCOPE void + rde_param_query_amark (RDE_PARAM p, long int* mc, long int** mv) + { + rde_stack_get (p->mark, mc, (void***) mv); + } + SCOPE void + rde_param_query_ast (RDE_PARAM p, long int* ac, Tcl_Obj*** av) + { + rde_stack_get (p->ast, ac, (void***) av); + } + SCOPE const char* + rde_param_query_in (RDE_PARAM p) + { + return p->IN + ? Tcl_GetChannelName (p->IN) + : ""; + } + SCOPE const char* + rde_param_query_cc (RDE_PARAM p, long int* len) + { + *len = p->CC_len; + return p->CC; + } + SCOPE int + rde_param_query_cl (RDE_PARAM p) + { + return p->CL; + } + SCOPE const ERROR_STATE* + rde_param_query_er (RDE_PARAM p) + { + return p->ER; + } + SCOPE Tcl_Obj* + rde_param_query_er_tcl (RDE_PARAM p, const ERROR_STATE* er) + { + Tcl_Obj* res; + if (!er) { + + res = Tcl_NewStringObj ("", 0); + } else { + Tcl_Obj* ov [2]; + Tcl_Obj** mov; + long int mc, i, j; + long int* mv; + int lastid; + const char* msg; + rde_stack_get (er->msg, &mc, (void***) &mv); + + qsort (mv, mc, sizeof (long int), er_int_compare); + + mov = NALLOC (mc, Tcl_Obj*); + lastid = -1; + for (i=0, j=0; i < mc; i++) { + ASSERT_BOUNDS (i,mc); + if (mv [i] == lastid) continue; + lastid = mv [i]; + ASSERT_BOUNDS(mv[i],p->numstr); + msg = p->string [mv[i]]; + ASSERT_BOUNDS (j,mc); + mov [j] = Tcl_NewStringObj (msg, -1); + j++; + } + + ov [0] = Tcl_NewIntObj (er->loc); + ov [1] = Tcl_NewListObj (j, mov); + res = Tcl_NewListObj (2, ov); + ckfree ((char*) mov); + } + return res; + } + SCOPE void + rde_param_query_es (RDE_PARAM p, long int* ec, ERROR_STATE*** ev) + { + rde_stack_get (p->ES, ec, (void***) ev); + } + SCOPE void + rde_param_query_ls (RDE_PARAM p, long int* lc, void*** lv) + { + rde_stack_get (p->LS, lc, lv); + } + SCOPE long int + rde_param_query_lstop (RDE_PARAM p) + { + (long int) rde_stack_top (p->LS); + } + SCOPE Tcl_HashTable* + rde_param_query_nc (RDE_PARAM p) + { + return &p->NC; + } + SCOPE int + rde_param_query_st (RDE_PARAM p) + { + return p->ST; + } + SCOPE Tcl_Obj* + rde_param_query_sv (RDE_PARAM p) + { + TRACE (("SV_QUERY %p => (%p)", (p), (p)->SV)); \ + return p->SV; + } + SCOPE long int + rde_param_query_tc_size (RDE_PARAM p) + { + return rde_tc_size (p->TC); + } + SCOPE void + rde_param_query_tc_get_s (RDE_PARAM p, long int at, long int last, char** ch, long int* len) + { + rde_tc_get_s (p->TC, at, last, ch, len); + } + SCOPE const char* + rde_param_query_string (RDE_PARAM p, long int id) + { + TRACE (("rde_param_query_string (RDE_PARAM %p, %d/%d)", p, id, p->numstr)); + ASSERT_BOUNDS(id,p->numstr); + return p->string [id]; + } + SCOPE void + rde_param_i_ast_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->mark, 1); + } + SCOPE void + rde_param_i_ast_pop_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_pop_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_push (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_ast_value_push (RDE_PARAM p) + { + ENTER ("rde_param_i_ast_value_push"); + TRACE (("RDE_PARAM %p",p)); + ASSERT(p->SV,"Unable to push undefined semantic value"); + TRACE (("rde_param_i_ast_value_push %p => (%p)", p, p->SV)); + TRACE (("SV = (%p rc%d '%s')", p->SV, p->SV->refCount, Tcl_GetString (p->SV))); + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + RETURNVOID; + } + static void + ast_node_free (void* n) + { + Tcl_DecrRefCount ((Tcl_Obj*) n); + } + SCOPE void + rde_param_i_error_clear (RDE_PARAM p) + { + ER_CLEAR (p); + } + SCOPE void + rde_param_i_error_nonterminal (RDE_PARAM p, int s) + { + + return; + long int pos; + if (!p->ER) return; + pos = 1 + (long int) rde_stack_top (p->LS); + if (p->ER->loc != pos) return; + error_set (p, s); + p->ER->loc = pos; + } + SCOPE void + rde_param_i_error_pop_merge (RDE_PARAM p) + { + ERROR_STATE* top = (ERROR_STATE*) rde_stack_top (p->ES); + + if (top == p->ER) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!top) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!p->ER) { + rde_stack_drop (p->ES, 1); + p->ER = top; + + return; + } + + if (top->loc < p->ER->loc) { + rde_stack_pop (p->ES, 1); + return; + } + + if (top->loc > p->ER->loc) { + rde_stack_drop (p->ES, 1); + error_state_free (p->ER); + p->ER = top; + + return; + } + + rde_stack_move (p->ER->msg, top->msg); + rde_stack_pop (p->ES, 1); + } + SCOPE void + rde_param_i_error_push (RDE_PARAM p) + { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + static void + error_set (RDE_PARAM p, int s) + { + error_state_free (p->ER); + p->ER = ALLOC (ERROR_STATE); + p->ER->refCount = 1; + p->ER->loc = p->CL; + p->ER->msg = rde_stack_new (NULL); + ASSERT_BOUNDS(s,p->numstr); + rde_stack_push (p->ER->msg, (void*) s); + } + static void + error_state_free (void* esx) + { + ERROR_STATE* es = esx; + if (!es) return; + es->refCount --; + if (es->refCount > 0) return; + rde_stack_del (es->msg); + ckfree ((char*) es); + } + SCOPE void + rde_param_i_loc_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_pop_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_push (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + } + SCOPE void + rde_param_i_loc_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + } + SCOPE void + rde_param_i_input_next (RDE_PARAM p, int m) + { + int leni; + char* ch; + ASSERT_BOUNDS(m,p->numstr); + p->CL ++; + if (p->CL < rde_tc_size (p->TC)) { + + rde_tc_get (p->TC, p->CL, &p->CC, &p->CC_len); + ASSERT_BOUNDS (p->CC_len, TCL_UTF_MAX); + p->ST = 1; + ER_CLEAR (p); + return; + } + if (!p->IN || + Tcl_Eof (p->IN) || + (Tcl_ReadChars (p->IN, p->readbuf, 1, 0) <= 0)) { + + p->ST = 0; + error_set (p, m); + return; + } + + ch = Tcl_GetStringFromObj (p->readbuf, &leni); + ASSERT_BOUNDS (leni, TCL_UTF_MAX); + p->CC = rde_tc_append (p->TC, ch, leni); + p->CC_len = leni; + p->ST = 1; + ER_CLEAR (p); + } + SCOPE void + rde_param_i_status_fail (RDE_PARAM p) + { + p->ST = 0; + } + SCOPE void + rde_param_i_status_ok (RDE_PARAM p) + { + p->ST = 1; + } + SCOPE void + rde_param_i_status_negate (RDE_PARAM p) + { + p->ST = !p->ST; + } + SCOPE int + rde_param_i_symbol_restore (RDE_PARAM p, int s) + { + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + + hPtr = Tcl_FindHashEntry (&p->NC, (char*) p->CL); + if (!hPtr) { return 0; } + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + hPtr = Tcl_FindHashEntry (tablePtr, (char*) s); + if (!hPtr) { return 0; } + + scs = Tcl_GetHashValue (hPtr); + p->CL = scs->CL; + p->ST = scs->ST; + error_state_free (p->ER); + p->ER = scs->ER; + if (p->ER) { p->ER->refCount ++; } + TRACE (("SV_RESTORE (%p) '%s'",scs->SV, scs->SV ? Tcl_GetString (scs->SV):"")); + SV_SET (p, scs->SV); + return 1; + } + SCOPE void + rde_param_i_symbol_save (RDE_PARAM p, int s) + { + long int at = (long int) rde_stack_top (p->LS); + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + int isnew; + ENTER ("rde_param_i_symbol_save"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("INT %d",s)); + + hPtr = Tcl_CreateHashEntry (&p->NC, (char*) at, &isnew); + if (isnew) { + tablePtr = ALLOC (Tcl_HashTable); + Tcl_InitHashTable (tablePtr, TCL_ONE_WORD_KEYS); + Tcl_SetHashValue (hPtr, tablePtr); + } else { + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + } + hPtr = Tcl_CreateHashEntry (tablePtr, (char*) s, &isnew); + if (isnew) { + + scs = ALLOC (NC_STATE); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "")); + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + Tcl_SetHashValue (hPtr, scs); + } else { + + scs = (NC_STATE*) Tcl_GetHashValue (hPtr); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE/over (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "" )); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + error_state_free (scs->ER); + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + } + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_test_alnum (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlnum, tc_alnum); + } + SCOPE void + rde_param_i_test_alpha (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlpha, tc_alpha); + } + SCOPE void + rde_param_i_test_ascii (RDE_PARAM p) + { + test_class (p, UniCharIsAscii, tc_ascii); + } + SCOPE void + rde_param_i_test_control (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsControl, tc_control); + } + SCOPE void + rde_param_i_test_char (RDE_PARAM p, const char* c, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = Tcl_UtfNcmp (p->CC, c, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_ddigit (RDE_PARAM p) + { + test_class (p, UniCharIsDecDigit, tc_ddigit); + } + SCOPE void + rde_param_i_test_digit (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsDigit, tc_digit); + } + SCOPE void + rde_param_i_test_graph (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsGraph, tc_graph); + } + SCOPE void + rde_param_i_test_lower (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsLower, tc_lower); + } + SCOPE void + rde_param_i_test_print (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPrint, tc_printable); + } + SCOPE void + rde_param_i_test_punct (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPunct, tc_punct); + } + SCOPE void + rde_param_i_test_range (RDE_PARAM p, char* s, char* e, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = + (Tcl_UtfNcmp (s, p->CC, 1) <= 0) && + (Tcl_UtfNcmp (p->CC, e, 1) <= 0); + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_space (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsSpace, tc_space); + } + SCOPE void + rde_param_i_test_upper (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsUpper, tc_upper); + } + SCOPE void + rde_param_i_test_wordchar (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsWordChar, tc_wordchar); + } + SCOPE void + rde_param_i_test_xdigit (RDE_PARAM p) + { + test_class (p, UniCharIsHexDigit, tc_xdigit); + } + static void + test_class (RDE_PARAM p, UniCharClass class, test_class_id id) + { + Tcl_UniChar ch; + Tcl_UtfToUniChar(p->CC, &ch); + ASSERT_BOUNDS(id,p->numstr); + p->ST = !!class (ch); + + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, id); + p->CL --; + } + } + static int + UniCharIsAscii (int character) + { + return (character >= 0) && (character < 0x80); + } + static int + UniCharIsHexDigit (int character) + { + return (character >= 0) && (character < 0x80) && isxdigit(character); + } + static int + UniCharIsDecDigit (int character) + { + return (character >= 0) && (character < 0x80) && isdigit(character); + } + SCOPE void + rde_param_i_value_clear (RDE_PARAM p) + { + SV_CLEAR (p); + } + SCOPE void + rde_param_i_value_leaf (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + Tcl_Obj* ov [3]; + long int pos = 1 + (long int) rde_stack_top (p->LS); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + newsv = Tcl_NewListObj (3, ov); + TRACE (("rde_param_i_value_leaf => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + } + SCOPE void + rde_param_i_value_reduce (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + int oc, i, j; + Tcl_Obj** ov; + long int ac; + Tcl_Obj** av; + long int pos = 1 + (long int) rde_stack_top (p->LS); + long int mark = (long int) rde_stack_top (p->mark); + long int asize = rde_stack_size (p->ast); + long int new = asize - mark; + ASSERT (new >= 0, "Bad number of elements to reduce"); + ov = NALLOC (3+new, Tcl_Obj*); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + rde_stack_get (p->ast, &ac, (void***) &av); + for (i = 3, j = mark; j < asize; i++, j++) { + ASSERT_BOUNDS (i, 3+new); + ASSERT_BOUNDS (j, ac); + ov [i] = av [j]; + } + ASSERT (i == 3+new, "Reduction result incomplete"); + newsv = Tcl_NewListObj (3+new, ov); + TRACE (("rde_param_i_value_reduce => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + ckfree ((char*) ov); + } + static int + er_int_compare (const void* a, const void* b) + { + long int ai = *((long int*) a); + long int bi = *((long int*) b); + if (ai < bi) { return -1; } + if (ai > bi) { return 1; } + return 0; + } + SCOPE int + rde_param_i_symbol_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE void + rde_param_i_symbol_done_d_reduce (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_reduce (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_d_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_symbol_done_d_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_next_char (RDE_PARAM p, char* c, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_char (p, c, m); + } + SCOPE void + rde_param_i_next_range (RDE_PARAM p, char* s, char* e, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_range (p, s, e, m); + } + SCOPE void + rde_param_i_next_alnum (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alnum (p); + } + SCOPE void + rde_param_i_next_alpha (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alpha (p); + } + SCOPE void + rde_param_i_next_ascii (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ascii (p); + } + SCOPE void + rde_param_i_next_control (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_control (p); + } + SCOPE void + rde_param_i_next_ddigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ddigit (p); + } + SCOPE void + rde_param_i_next_digit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_digit (p); + } + SCOPE void + rde_param_i_next_graph (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_graph (p); + } + SCOPE void + rde_param_i_next_lower (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_lower (p); + } + SCOPE void + rde_param_i_next_print (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_print (p); + } + SCOPE void + rde_param_i_next_punct (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_punct (p); + } + SCOPE void + rde_param_i_next_space (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_space (p); + } + SCOPE void + rde_param_i_next_upper (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_upper (p); + } + SCOPE void + rde_param_i_next_wordchar (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_wordchar (p); + } + SCOPE void + rde_param_i_next_xdigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_xdigit (p); + } + SCOPE void + rde_param_i_notahead_start_d (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_notahead_exit_d (RDE_PARAM p) + { + if (p->ST) { + rde_param_i_ast_pop_rewind (p); + } else { + rde_stack_pop (p->mark, 1); + } + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_notahead_exit (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_state_push_2 (RDE_PARAM p) + { + + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + SCOPE void + rde_param_i_state_push_void (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_push_value (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_merge_ok (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } + SCOPE int + rde_param_i_kleene_close (RDE_PARAM p) + { + int stop = !p->ST; + rde_param_i_error_pop_merge (p); + if (stop) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_kleene_abort (RDE_PARAM p) + { + int stop = !p->ST; + if (stop) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_seq_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_bra_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE void + rde_param_i_next_str (RDE_PARAM p, const char* str, int m) + { + int at = p->CL; + + while (*str) { + rde_param_i_input_next (p, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + rde_param_i_test_char (p, str, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + str = Tcl_UtfNext (str); + } + } + SCOPE void + rde_param_i_next_class (RDE_PARAM p, const char* class, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + while (*class) { + p->ST = Tcl_UtfNcmp (p->CC, class, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + return; + } + class = Tcl_UtfNext (class); + } + error_set (p, m); + p->CL --; + } + + + /* + * Declaring the parse functions + */ + + + /* + * Precomputed table of strings (symbols, error messages, etc.). + */ + + static char const* p_string [15] = { + /* 0 = */ "alnum", + /* 1 = */ "alpha", + /* 2 = */ "ascii", + /* 3 = */ "control", + /* 4 = */ "ddigit", + /* 5 = */ "digit", + /* 6 = */ "graph", + /* 7 = */ "lower", + /* 8 = */ "print", + /* 9 = */ "punct", + /* 10 = */ "space", + /* 11 = */ "upper", + /* 12 = */ "wordchar", + /* 13 = */ "xdigit", + /* 14 = */ "cl abc" + }; + + /* + * Grammar Start Expression + */ + + static void MAIN (RDE_PARAM p) { + rde_param_i_next_class (p, "abc", 14); + return; + } + + /* -*- c -*- */ + + typedef struct PARSERg { + long int counter; + char buf [50]; + } PARSERg; + + static void + PARSERgRelease (ClientData cd, Tcl_Interp* interp) + { + ckfree((char*) cd); + } + + static const char* + PARSERnewName (Tcl_Interp* interp) + { +#define KEY "tcllib/parser/PACKAGE/TEA" + + Tcl_InterpDeleteProc* proc = PARSERgRelease; + PARSERg* parserg; + + parserg = Tcl_GetAssocData (interp, KEY, &proc); + if (parserg == NULL) { + parserg = (PARSERg*) ckalloc (sizeof (PARSERg)); + parserg->counter = 0; + + Tcl_SetAssocData (interp, KEY, proc, + (ClientData) parserg); + } + + parserg->counter ++; + sprintf (parserg->buf, "PARSER%d", parserg->counter); + return parserg->buf; +#undef KEY + } + + static void + PARSERdeleteCmd (ClientData clientData) + { + /* + * Release the whole PARSER + * (Low-level engine only actually). + */ + rde_param_del ((RDE_PARAM) clientData); + } + + + /* * ** *** ***** ******** ************* + ** Functions implementing the object methods, and helper. + */ + + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp); + + static int parser_PARSE (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + int mode; + Tcl_Channel chan; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "chan"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, + Tcl_GetString (objv[2]), + &mode); + + if (!chan) { + return TCL_ERROR; + } + + rde_param_reset (p, chan); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + static int parser_PARSET (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + char* buf; + int len; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "text"); + return TCL_ERROR; + } + + buf = Tcl_GetStringFromObj (objv[2], &len); + + rde_param_reset (p, NULL); + rde_param_data (p, buf, len); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + /* See also rde_critcl/m.c, param_COMPLETE() */ + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp) + { + if (rde_param_query_st (p)) { + long int ac; + Tcl_Obj** av; + + rde_param_query_ast (p, &ac, &av); + + if (ac > 1) { + Tcl_Obj** lv = NALLOC (3+ac, Tcl_Obj*); + + memcpy(lv + 3, av, ac * sizeof (Tcl_Obj*)); + lv [0] = Tcl_NewObj (); + lv [1] = Tcl_NewIntObj (1 + rde_param_query_lstop (p)); + lv [2] = Tcl_NewIntObj (rde_param_query_cl (p)); + + Tcl_SetObjResult (interp, Tcl_NewListObj (3, lv)); + ckfree ((char*) lv); + + } else if (ac == 0) { + /* + * Match, but no AST. This is possible if the grammar + * consists of only the start expression. + */ + Tcl_SetObjResult (interp, Tcl_NewStringObj ("",-1)); + } else { + Tcl_SetObjResult (interp, av [0]); + } + + return TCL_OK; + } else { + Tcl_Obj* xv [1]; + const ERROR_STATE* er = rde_param_query_er (p); + Tcl_Obj* res = rde_param_query_er_tcl (p, er); + /* res = list (location, list(msg)) */ + + /* Stick the exception type-tag before the existing elements */ + xv [0] = Tcl_NewStringObj ("pt::rde",-1); + Tcl_ListObjReplace(interp, res, 0, 0, 1, xv); + + Tcl_SetErrorCode (interp, "PT", "RDE", "SYNTAX", NULL); + Tcl_SetObjResult (interp, res); + return TCL_ERROR; + } + } + + + /* * ** *** ***** ******** ************* + ** Object command, method dispatch. + */ + static int parser_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + RDE_PARAM p = (RDE_PARAM) cd; + int m, res; + + static CONST char* methods [] = { + "destroy", "parse", "parset", NULL + }; + enum methods { + M_DESTROY, M_PARSE, M_PARSET + }; + + if (objc < 2) { + Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option", + 0, &m) != TCL_OK) { + return TCL_ERROR; + } + + /* Dispatch to methods. They check the #args in + * detail before performing the requested + * functionality + */ + + switch (m) { + case M_DESTROY: + if (objc != 2) { + Tcl_WrongNumArgs (interp, 2, objv, NULL); + return TCL_ERROR; + } + + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) rde_param_query_clientdata (p)); + return TCL_OK; + + case M_PARSE: res = parser_PARSE (p, interp, objc, objv); break; + case M_PARSET: res = parser_PARSET (p, interp, objc, objv); break; + default: + /* Not coming to this place */ + ASSERT (0,"Reached unreachable location"); + } + + return res; + } + + /** * ** *** ***** ******** ************* + * Class command, i.e. object construction. + */ + static int ParserClassCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const*objv) { + /* + * Syntax: No arguments beyond the name + */ + + RDE_PARAM parser; + CONST char* name; + Tcl_Obj* fqn; + Tcl_CmdInfo ci; + Tcl_Command c; + +#define USAGE "?name?" + + if ((objc != 2) && (objc != 1)) { + Tcl_WrongNumArgs (interp, 1, objv, USAGE); + return TCL_ERROR; + } + + if (objc < 2) { + name = PARSERnewName (interp); + } else { + name = Tcl_GetString (objv [1]); + } + + if (!Tcl_StringMatch (name, "::*")) { + /* Relative name. Prefix with current namespace */ + + Tcl_Eval (interp, "namespace current"); + fqn = Tcl_GetObjResult (interp); + fqn = Tcl_DuplicateObj (fqn); + Tcl_IncrRefCount (fqn); + + if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { + Tcl_AppendToObj (fqn, "::", -1); + } + Tcl_AppendToObj (fqn, name, -1); + } else { + fqn = Tcl_NewStringObj (name, -1); + Tcl_IncrRefCount (fqn); + } + Tcl_ResetResult (interp); + + if (Tcl_GetCommandInfo (interp, + Tcl_GetString (fqn), + &ci)) { + Tcl_Obj* err; + + err = Tcl_NewObj (); + Tcl_AppendToObj (err, "command \"", -1); + Tcl_AppendObjToObj (err, fqn); + Tcl_AppendToObj (err, "\" already exists", -1); + + Tcl_DecrRefCount (fqn); + Tcl_SetObjResult (interp, err); + return TCL_ERROR; + } + + parser = rde_param_new (sizeof(p_string)/sizeof(char*), (char**) p_string); + c = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), + parser_objcmd, (ClientData) parser, + PARSERdeleteCmd); + rde_param_clientdata (parser, (ClientData) c); + Tcl_SetObjResult (interp, fqn); + Tcl_DecrRefCount (fqn); + return TCL_OK; + } + +int Package_Init(Tcl_Interp* interp) { + if (interp == 0) return TCL_ERROR; + + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + + if (Tcl_CreateObjCommand(interp, "PARSER", ParserClassCmd , NULL, NULL) == NULL) { + Tcl_SetResult(interp, "Can't create constructor", NULL); + return TCL_ERROR; + } + + + Tcl_PkgProvide(interp, "PACKAGE", "0.1"); + + return TCL_OK; +} ADDED modules/pt/tests/data/ok/peg_cparam-tea/5_sequence Index: modules/pt/tests/data/ok/peg_cparam-tea/5_sequence ================================================================== --- /dev/null +++ modules/pt/tests/data/ok/peg_cparam-tea/5_sequence @@ -0,0 +1,1982 @@ +/************************************************************ +** +** TEA-based C/PARAM implementation of the parsing +** expression grammar +** +** TEMPLATE +** +** Generated from file TEST +** for user unknown +** +* * ** *** ***** ******** ************* *********************/ + #include + #include + #include + #include + #define SCOPE static + +#line 1 "rde_critcl/util.h" + + #ifndef _RDE_UTIL_H + #define _RDE_UTIL_H 1 + #ifndef SCOPE + #define SCOPE + #endif + #define ALLOC(type) (type *) ckalloc (sizeof (type)) + #define NALLOC(n,type) (type *) ckalloc ((n) * sizeof (type)) + #undef RDE_DEBUG + #define RDE_DEBUG 1 + #undef RDE_TRACE + #ifdef RDE_DEBUG + #define STOPAFTER(x) { static int count = (x); count --; if (!count) { Tcl_Panic ("stop"); } } + #define XSTR(x) #x + #define STR(x) XSTR(x) + #define RANGEOK(i,n) ((0 <= (i)) && (i < (n))) + #define ASSERT(x,msg) if (!(x)) { Tcl_Panic (msg " (" #x "), in file " __FILE__ " @line " STR(__LINE__));} + #define ASSERT_BOUNDS(i,n) ASSERT (RANGEOK(i,n),"array index out of bounds: " STR(i) " >= " STR(n)) + #else + #define STOPAFTER(x) + #define ASSERT(x,msg) + #define ASSERT_BOUNDS(i,n) + #endif + #ifdef RDE_TRACE + SCOPE void trace_enter (const char* fun); + SCOPE void trace_return (const char *pat, ...); + SCOPE void trace_printf (const char *pat, ...); + #define ENTER(fun) trace_enter (fun) + #define RETURN(format,x) trace_return (format,x) ; return x + #define RETURNVOID trace_return ("%s","(void)") ; return + #define TRACE0(x) trace_printf0 x + #define TRACE(x) trace_printf x + #else + #define ENTER(fun) + #define RETURN(f,x) return x + #define RETURNVOID return + #define TRACE0(x) + #define TRACE(x) + #endif + #endif + + +#line 1 "rde_critcl/stack.h" + + #ifndef _RDE_DS_STACK_H + #define _RDE_DS_STACK_H 1 + typedef void (*RDE_STACK_CELL_FREE) (void* cell); + typedef struct RDE_STACK_* RDE_STACK; + static const int RDE_STACK_INITIAL_SIZE = 256; + #endif + + +#line 1 "rde_critcl/tc.h" + + #ifndef _RDE_DS_TC_H + #define _RDE_DS_TC_H 1 + typedef struct RDE_TC_* RDE_TC; + #endif + + +#line 1 "rde_critcl/param.h" + + #ifndef _RDE_DS_PARAM_H + #define _RDE_DS_PARAM_H 1 + typedef struct RDE_PARAM_* RDE_PARAM; + typedef struct ERROR_STATE { + int refCount; + long int loc; + RDE_STACK msg; + } ERROR_STATE; + typedef struct NC_STATE { + long int CL; + long int ST; + Tcl_Obj* SV; + ERROR_STATE* ER; + } NC_STATE; + #endif + + +#line 1 "rde_critcl/util.c" + + #ifdef RDE_TRACE + typedef struct F_STACK { + const char* str; + struct F_STACK* down; + } F_STACK; + static F_STACK* top = 0; + static int level = 0; + static void + push (const char* str) + { + F_STACK* new = ALLOC (F_STACK); + new->str = str; + new->down = top; + top = new; + level += 4; + } + static void + pop (void) + { + F_STACK* next = top->down; + level -= 4; + ckfree ((char*)top); + top = next; + } + static void + indent (void) + { + int i; + for (i = 0; i < level; i++) { + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + if (top) { + fwrite(top->str, 1, strlen(top->str), stdout); + fflush (stdout); + } + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + SCOPE void + trace_enter (const char* fun) + { + push (fun); + indent(); + fwrite("ENTER\n", 1, 6, stdout); + fflush (stdout); + } + static char msg [1024*1024]; + SCOPE void + trace_return (const char *pat, ...) + { + int len; + va_list args; + indent(); + fwrite("RETURN = ", 1, 9, stdout); + fflush (stdout); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + pop(); + } + SCOPE void + trace_printf (const char *pat, ...) + { + int len; + va_list args; + indent(); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + SCOPE void + trace_printf0 (const char *pat, ...) + { + int len; + va_list args; + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + #endif + + +#line 1 "rde_critcl/stack.c" + + typedef struct RDE_STACK_ { + long int max; + long int top; + RDE_STACK_CELL_FREE freeCellProc; + void** cell; + } RDE_STACK_; + + SCOPE RDE_STACK + rde_stack_new (RDE_STACK_CELL_FREE freeCellProc) + { + RDE_STACK s = ALLOC (RDE_STACK_); + s->cell = NALLOC (RDE_STACK_INITIAL_SIZE, void*); + s->max = RDE_STACK_INITIAL_SIZE; + s->top = 0; + s->freeCellProc = freeCellProc; + return s; + } + SCOPE void + rde_stack_del (RDE_STACK s) + { + if (s->freeCellProc && s->top) { + long int i; + for (i=0; i < s->top; i++) { + ASSERT_BOUNDS(i,s->max); + s->freeCellProc ( s->cell [i] ); + } + } + ckfree ((char*) s->cell); + ckfree ((char*) s); + } + SCOPE void + rde_stack_push (RDE_STACK s, void* item) + { + if (s->top >= s->max) { + long int new = s->max ? (2 * s->max) : RDE_STACK_INITIAL_SIZE; + void** cell = (void**) ckrealloc ((char*) s->cell, new * sizeof(void*)); + ASSERT (cell,"Memory allocation failure for RDE stack"); + s->max = new; + s->cell = cell; + } + ASSERT_BOUNDS(s->top,s->max); + s->cell [s->top] = item; + s->top ++; + } + SCOPE void* + rde_stack_top (RDE_STACK s) + { + ASSERT_BOUNDS(s->top-1,s->max); + return s->cell [s->top - 1]; + } + SCOPE void + rde_stack_pop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + if (s->freeCellProc) { + while (n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + n --; + } + } else { + s->top -= n; + } + } + SCOPE void + rde_stack_trim (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad trimsize"); + if (s->freeCellProc) { + while (s->top > n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + } + } else { + s->top = n; + } + } + SCOPE void + rde_stack_drop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + s->top -= n; + } + SCOPE void + rde_stack_move (RDE_STACK dst, RDE_STACK src) + { + ASSERT (dst->freeCellProc == src->freeCellProc, "Ownership mismatch"); + + while (src->top > 0) { + src->top --; + ASSERT_BOUNDS(src->top,src->max); + rde_stack_push (dst, src->cell [src->top] ); + } + } + SCOPE void + rde_stack_get (RDE_STACK s, long int* cn, void*** cc) + { + *cn = s->top; + *cc = s->cell; + } + SCOPE long int + rde_stack_size (RDE_STACK s) + { + return s->top; + } + + +#line 1 "rde_critcl/tc.c" + + typedef struct RDE_TC_ { + int max; + int num; + char* str; + RDE_STACK off; + } RDE_TC_; + + SCOPE RDE_TC + rde_tc_new (void) + { + RDE_TC tc = ALLOC (RDE_TC_); + tc->max = RDE_STACK_INITIAL_SIZE; + tc->num = 0; + tc->str = NALLOC (RDE_STACK_INITIAL_SIZE, char); + tc->off = rde_stack_new (NULL); + return tc; + } + SCOPE void + rde_tc_del (RDE_TC tc) + { + rde_stack_del (tc->off); + ckfree (tc->str); + ckfree ((char*) tc); + } + SCOPE long int + rde_tc_size (RDE_TC tc) + { + return rde_stack_size (tc->off); + } + SCOPE void + rde_tc_clear (RDE_TC tc) + { + tc->num = 0; + rde_stack_trim (tc->off, 0); + } + SCOPE char* + rde_tc_append (RDE_TC tc, char* string, long int len) + { + long int base = tc->num; + long int off = tc->num; + char* ch; + int clen; + Tcl_UniChar uni; + if (len < 0) { + len = strlen (string); + } + + if (!len) { + return tc->str + base; + } + + if ((tc->num + len) >= tc->max) { + int new = len + (tc->max ? (2 * tc->max) : RDE_STACK_INITIAL_SIZE); + char* str = ckrealloc (tc->str, new * sizeof(char)); + ASSERT (str,"Memory allocation failure for token character array"); + tc->max = new; + tc->str = str; + } + tc->num += len; + ASSERT_BOUNDS(tc->num,tc->max); + ASSERT_BOUNDS(off,tc->max); + ASSERT_BOUNDS(off+len-1,tc->max); + ASSERT_BOUNDS(off+len-1,tc->num); + memcpy (tc->str + off, string, len); + + ch = string; + while (ch < (string + len)) { + ASSERT_BOUNDS(off,tc->num); + rde_stack_push (tc->off, (void*) off); + clen = Tcl_UtfToUniChar (ch, &uni); + off += clen; + ch += clen; + } + return tc->str + base; + } + SCOPE void + rde_tc_get (RDE_TC tc, int at, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + off = ov [at]; + if ((at+1) == oc) { + end = tc->num; + } else { + end = ov [at+1]; + } + TRACE (("rde_tc_get (RDE_TC %p, @ %d) => %d.[%d ... %d]/%d",tc,at,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + SCOPE void + rde_tc_get_s (RDE_TC tc, int at, int last, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + ASSERT_BOUNDS(last,oc); + off = ov [at]; + if ((last+1) == oc) { + end = tc->num; + } else { + end = ov [last+1]; + } + TRACE (("rde_tc_get_s (RDE_TC %p, @ %d .. %d) => %d.[%d ... %d]/%d",tc,at,last,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + + +#line 1 "rde_critcl/param.c" + + typedef struct RDE_PARAM_ { + Tcl_Channel IN; + Tcl_Obj* readbuf; + char* CC; + long int CC_len; + RDE_TC TC; + long int CL; + RDE_STACK LS; + ERROR_STATE* ER; + RDE_STACK ES; + long int ST; + Tcl_Obj* SV; + Tcl_HashTable NC; + + RDE_STACK ast ; + RDE_STACK mark ; + + long int numstr; + char** string; + + ClientData clientData; + } RDE_PARAM_; + typedef int (*UniCharClass) (int); + typedef enum test_class_id { + tc_alnum, + tc_alpha, + tc_ascii, + tc_control, + tc_ddigit, + tc_digit, + tc_graph, + tc_lower, + tc_printable, + tc_punct, + tc_space, + tc_upper, + tc_wordchar, + tc_xdigit + } test_class_id; + static void ast_node_free (void* n); + static void error_state_free (void* es); + static void error_set (RDE_PARAM p, int s); + static void nc_clear (RDE_PARAM p); + static int UniCharIsAscii (int character); + static int UniCharIsHexDigit (int character); + static int UniCharIsDecDigit (int character); + static void test_class (RDE_PARAM p, UniCharClass class, test_class_id id); + static int er_int_compare (const void* a, const void* b); + #define SV_INIT(p) \ + p->SV = NULL; \ + TRACE (("SV_INIT (%p => %p)", (p), (p)->SV)) + #define SV_SET(p,newsv) \ + if (((p)->SV) != (newsv)) { \ + TRACE (("SV_CLEAR/set (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = (newsv); \ + TRACE (("SV_SET (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_IncrRefCount ((p)->SV); \ + } \ + } + #define SV_CLEAR(p) \ + TRACE (("SV_CLEAR (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = NULL + #define ER_INIT(p) \ + p->ER = NULL; \ + TRACE (("ER_INIT (%p => %p)", (p), (p)->ER)) + #define ER_CLEAR(p) \ + error_state_free ((p)->ER); \ + (p)->ER = NULL + SCOPE RDE_PARAM + rde_param_new (long int nstr, char** strings) + { + RDE_PARAM p; + ENTER ("rde_param_new"); + TRACE (("\tINT %d strings @ %p", nstr, strings)); + p = ALLOC (RDE_PARAM_); + p->numstr = nstr; + p->string = strings; + p->readbuf = Tcl_NewObj (); + Tcl_IncrRefCount (p->readbuf); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_InitHashTable (&p->NC, TCL_ONE_WORD_KEYS); + p->IN = NULL; + p->CL = -1; + p->ST = 0; + ER_INIT (p); + SV_INIT (p); + p->CC = NULL; + p->CC_len = 0; + p->TC = rde_tc_new (); + p->ES = rde_stack_new (error_state_free); + p->LS = rde_stack_new (NULL); + p->ast = rde_stack_new (ast_node_free); + p->mark = rde_stack_new (NULL); + RETURN ("%p", p); + } + SCOPE void + rde_param_del (RDE_PARAM p) + { + ENTER ("rde_param_del"); + TRACE (("RDE_PARAM %p",p)); + ER_CLEAR (p); TRACE (("\ter_clear")); + SV_CLEAR (p); TRACE (("\tsv_clear")); + nc_clear (p); TRACE (("\tnc_clear")); + Tcl_DeleteHashTable (&p->NC); TRACE (("\tnc hashtable delete")); + rde_tc_del (p->TC); TRACE (("\ttc clear")); + rde_stack_del (p->ES); TRACE (("\tes clear")); + rde_stack_del (p->LS); TRACE (("\tls clear")); + rde_stack_del (p->ast); TRACE (("\tast clear")); + rde_stack_del (p->mark); TRACE (("\tmark clear")); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_DecrRefCount (p->readbuf); + ckfree ((char*) p); + RETURNVOID; + } + SCOPE void + rde_param_reset (RDE_PARAM p, Tcl_Channel chan) + { + ENTER ("rde_param_reset"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("Tcl_Channel %p",chan)); + p->IN = chan; + p->CL = -1; + p->ST = 0; + p->CC = NULL; + p->CC_len = 0; + ER_CLEAR (p); + SV_CLEAR (p); + nc_clear (p); + rde_tc_clear (p->TC); + rde_stack_trim (p->ES, 0); + rde_stack_trim (p->LS, 0); + rde_stack_trim (p->ast, 0); + rde_stack_trim (p->mark, 0); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + RETURNVOID; + } + SCOPE void + rde_param_update_strings (RDE_PARAM p, long int nstr, char** strings) + { + ENTER ("rde_param_update_strings"); + TRACE (("RDE_PARAM %p", p)); + TRACE (("INT %d strings", nstr)); + p->numstr = nstr; + p->string = strings; + RETURNVOID; + } + SCOPE void + rde_param_data (RDE_PARAM p, char* buf, long int len) + { + (void) rde_tc_append (p->TC, buf, len); + } + SCOPE void + rde_param_clientdata (RDE_PARAM p, ClientData clientData) + { + p->clientData = clientData; + } + static void + nc_clear (RDE_PARAM p) + { + Tcl_HashSearch hs; + Tcl_HashEntry* he; + Tcl_HashTable* tablePtr; + for(he = Tcl_FirstHashEntry(&p->NC, &hs); + he != NULL; + he = Tcl_FirstHashEntry(&p->NC, &hs)) { + Tcl_HashSearch hsc; + Tcl_HashEntry* hec; + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (he); + for(hec = Tcl_FirstHashEntry(tablePtr, &hsc); + hec != NULL; + hec = Tcl_NextHashEntry(&hsc)) { + NC_STATE* scs = Tcl_GetHashValue (hec); + error_state_free (scs->ER); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + ckfree ((char*) scs); + } + Tcl_DeleteHashTable (tablePtr); + ckfree ((char*) tablePtr); + Tcl_DeleteHashEntry (he); + } + } + SCOPE ClientData + rde_param_query_clientdata (RDE_PARAM p) + { + return p->clientData; + } + SCOPE void + rde_param_query_amark (RDE_PARAM p, long int* mc, long int** mv) + { + rde_stack_get (p->mark, mc, (void***) mv); + } + SCOPE void + rde_param_query_ast (RDE_PARAM p, long int* ac, Tcl_Obj*** av) + { + rde_stack_get (p->ast, ac, (void***) av); + } + SCOPE const char* + rde_param_query_in (RDE_PARAM p) + { + return p->IN + ? Tcl_GetChannelName (p->IN) + : ""; + } + SCOPE const char* + rde_param_query_cc (RDE_PARAM p, long int* len) + { + *len = p->CC_len; + return p->CC; + } + SCOPE int + rde_param_query_cl (RDE_PARAM p) + { + return p->CL; + } + SCOPE const ERROR_STATE* + rde_param_query_er (RDE_PARAM p) + { + return p->ER; + } + SCOPE Tcl_Obj* + rde_param_query_er_tcl (RDE_PARAM p, const ERROR_STATE* er) + { + Tcl_Obj* res; + if (!er) { + + res = Tcl_NewStringObj ("", 0); + } else { + Tcl_Obj* ov [2]; + Tcl_Obj** mov; + long int mc, i, j; + long int* mv; + int lastid; + const char* msg; + rde_stack_get (er->msg, &mc, (void***) &mv); + + qsort (mv, mc, sizeof (long int), er_int_compare); + + mov = NALLOC (mc, Tcl_Obj*); + lastid = -1; + for (i=0, j=0; i < mc; i++) { + ASSERT_BOUNDS (i,mc); + if (mv [i] == lastid) continue; + lastid = mv [i]; + ASSERT_BOUNDS(mv[i],p->numstr); + msg = p->string [mv[i]]; + ASSERT_BOUNDS (j,mc); + mov [j] = Tcl_NewStringObj (msg, -1); + j++; + } + + ov [0] = Tcl_NewIntObj (er->loc); + ov [1] = Tcl_NewListObj (j, mov); + res = Tcl_NewListObj (2, ov); + ckfree ((char*) mov); + } + return res; + } + SCOPE void + rde_param_query_es (RDE_PARAM p, long int* ec, ERROR_STATE*** ev) + { + rde_stack_get (p->ES, ec, (void***) ev); + } + SCOPE void + rde_param_query_ls (RDE_PARAM p, long int* lc, void*** lv) + { + rde_stack_get (p->LS, lc, lv); + } + SCOPE long int + rde_param_query_lstop (RDE_PARAM p) + { + (long int) rde_stack_top (p->LS); + } + SCOPE Tcl_HashTable* + rde_param_query_nc (RDE_PARAM p) + { + return &p->NC; + } + SCOPE int + rde_param_query_st (RDE_PARAM p) + { + return p->ST; + } + SCOPE Tcl_Obj* + rde_param_query_sv (RDE_PARAM p) + { + TRACE (("SV_QUERY %p => (%p)", (p), (p)->SV)); \ + return p->SV; + } + SCOPE long int + rde_param_query_tc_size (RDE_PARAM p) + { + return rde_tc_size (p->TC); + } + SCOPE void + rde_param_query_tc_get_s (RDE_PARAM p, long int at, long int last, char** ch, long int* len) + { + rde_tc_get_s (p->TC, at, last, ch, len); + } + SCOPE const char* + rde_param_query_string (RDE_PARAM p, long int id) + { + TRACE (("rde_param_query_string (RDE_PARAM %p, %d/%d)", p, id, p->numstr)); + ASSERT_BOUNDS(id,p->numstr); + return p->string [id]; + } + SCOPE void + rde_param_i_ast_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->mark, 1); + } + SCOPE void + rde_param_i_ast_pop_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_pop_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_push (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_ast_value_push (RDE_PARAM p) + { + ENTER ("rde_param_i_ast_value_push"); + TRACE (("RDE_PARAM %p",p)); + ASSERT(p->SV,"Unable to push undefined semantic value"); + TRACE (("rde_param_i_ast_value_push %p => (%p)", p, p->SV)); + TRACE (("SV = (%p rc%d '%s')", p->SV, p->SV->refCount, Tcl_GetString (p->SV))); + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + RETURNVOID; + } + static void + ast_node_free (void* n) + { + Tcl_DecrRefCount ((Tcl_Obj*) n); + } + SCOPE void + rde_param_i_error_clear (RDE_PARAM p) + { + ER_CLEAR (p); + } + SCOPE void + rde_param_i_error_nonterminal (RDE_PARAM p, int s) + { + + return; + long int pos; + if (!p->ER) return; + pos = 1 + (long int) rde_stack_top (p->LS); + if (p->ER->loc != pos) return; + error_set (p, s); + p->ER->loc = pos; + } + SCOPE void + rde_param_i_error_pop_merge (RDE_PARAM p) + { + ERROR_STATE* top = (ERROR_STATE*) rde_stack_top (p->ES); + + if (top == p->ER) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!top) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!p->ER) { + rde_stack_drop (p->ES, 1); + p->ER = top; + + return; + } + + if (top->loc < p->ER->loc) { + rde_stack_pop (p->ES, 1); + return; + } + + if (top->loc > p->ER->loc) { + rde_stack_drop (p->ES, 1); + error_state_free (p->ER); + p->ER = top; + + return; + } + + rde_stack_move (p->ER->msg, top->msg); + rde_stack_pop (p->ES, 1); + } + SCOPE void + rde_param_i_error_push (RDE_PARAM p) + { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + static void + error_set (RDE_PARAM p, int s) + { + error_state_free (p->ER); + p->ER = ALLOC (ERROR_STATE); + p->ER->refCount = 1; + p->ER->loc = p->CL; + p->ER->msg = rde_stack_new (NULL); + ASSERT_BOUNDS(s,p->numstr); + rde_stack_push (p->ER->msg, (void*) s); + } + static void + error_state_free (void* esx) + { + ERROR_STATE* es = esx; + if (!es) return; + es->refCount --; + if (es->refCount > 0) return; + rde_stack_del (es->msg); + ckfree ((char*) es); + } + SCOPE void + rde_param_i_loc_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_pop_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_push (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + } + SCOPE void + rde_param_i_loc_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + } + SCOPE void + rde_param_i_input_next (RDE_PARAM p, int m) + { + int leni; + char* ch; + ASSERT_BOUNDS(m,p->numstr); + p->CL ++; + if (p->CL < rde_tc_size (p->TC)) { + + rde_tc_get (p->TC, p->CL, &p->CC, &p->CC_len); + ASSERT_BOUNDS (p->CC_len, TCL_UTF_MAX); + p->ST = 1; + ER_CLEAR (p); + return; + } + if (!p->IN || + Tcl_Eof (p->IN) || + (Tcl_ReadChars (p->IN, p->readbuf, 1, 0) <= 0)) { + + p->ST = 0; + error_set (p, m); + return; + } + + ch = Tcl_GetStringFromObj (p->readbuf, &leni); + ASSERT_BOUNDS (leni, TCL_UTF_MAX); + p->CC = rde_tc_append (p->TC, ch, leni); + p->CC_len = leni; + p->ST = 1; + ER_CLEAR (p); + } + SCOPE void + rde_param_i_status_fail (RDE_PARAM p) + { + p->ST = 0; + } + SCOPE void + rde_param_i_status_ok (RDE_PARAM p) + { + p->ST = 1; + } + SCOPE void + rde_param_i_status_negate (RDE_PARAM p) + { + p->ST = !p->ST; + } + SCOPE int + rde_param_i_symbol_restore (RDE_PARAM p, int s) + { + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + + hPtr = Tcl_FindHashEntry (&p->NC, (char*) p->CL); + if (!hPtr) { return 0; } + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + hPtr = Tcl_FindHashEntry (tablePtr, (char*) s); + if (!hPtr) { return 0; } + + scs = Tcl_GetHashValue (hPtr); + p->CL = scs->CL; + p->ST = scs->ST; + error_state_free (p->ER); + p->ER = scs->ER; + if (p->ER) { p->ER->refCount ++; } + TRACE (("SV_RESTORE (%p) '%s'",scs->SV, scs->SV ? Tcl_GetString (scs->SV):"")); + SV_SET (p, scs->SV); + return 1; + } + SCOPE void + rde_param_i_symbol_save (RDE_PARAM p, int s) + { + long int at = (long int) rde_stack_top (p->LS); + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + int isnew; + ENTER ("rde_param_i_symbol_save"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("INT %d",s)); + + hPtr = Tcl_CreateHashEntry (&p->NC, (char*) at, &isnew); + if (isnew) { + tablePtr = ALLOC (Tcl_HashTable); + Tcl_InitHashTable (tablePtr, TCL_ONE_WORD_KEYS); + Tcl_SetHashValue (hPtr, tablePtr); + } else { + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + } + hPtr = Tcl_CreateHashEntry (tablePtr, (char*) s, &isnew); + if (isnew) { + + scs = ALLOC (NC_STATE); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "")); + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + Tcl_SetHashValue (hPtr, scs); + } else { + + scs = (NC_STATE*) Tcl_GetHashValue (hPtr); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE/over (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "" )); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + error_state_free (scs->ER); + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + } + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_test_alnum (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlnum, tc_alnum); + } + SCOPE void + rde_param_i_test_alpha (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlpha, tc_alpha); + } + SCOPE void + rde_param_i_test_ascii (RDE_PARAM p) + { + test_class (p, UniCharIsAscii, tc_ascii); + } + SCOPE void + rde_param_i_test_control (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsControl, tc_control); + } + SCOPE void + rde_param_i_test_char (RDE_PARAM p, const char* c, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = Tcl_UtfNcmp (p->CC, c, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_ddigit (RDE_PARAM p) + { + test_class (p, UniCharIsDecDigit, tc_ddigit); + } + SCOPE void + rde_param_i_test_digit (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsDigit, tc_digit); + } + SCOPE void + rde_param_i_test_graph (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsGraph, tc_graph); + } + SCOPE void + rde_param_i_test_lower (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsLower, tc_lower); + } + SCOPE void + rde_param_i_test_print (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPrint, tc_printable); + } + SCOPE void + rde_param_i_test_punct (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPunct, tc_punct); + } + SCOPE void + rde_param_i_test_range (RDE_PARAM p, char* s, char* e, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = + (Tcl_UtfNcmp (s, p->CC, 1) <= 0) && + (Tcl_UtfNcmp (p->CC, e, 1) <= 0); + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_space (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsSpace, tc_space); + } + SCOPE void + rde_param_i_test_upper (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsUpper, tc_upper); + } + SCOPE void + rde_param_i_test_wordchar (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsWordChar, tc_wordchar); + } + SCOPE void + rde_param_i_test_xdigit (RDE_PARAM p) + { + test_class (p, UniCharIsHexDigit, tc_xdigit); + } + static void + test_class (RDE_PARAM p, UniCharClass class, test_class_id id) + { + Tcl_UniChar ch; + Tcl_UtfToUniChar(p->CC, &ch); + ASSERT_BOUNDS(id,p->numstr); + p->ST = !!class (ch); + + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, id); + p->CL --; + } + } + static int + UniCharIsAscii (int character) + { + return (character >= 0) && (character < 0x80); + } + static int + UniCharIsHexDigit (int character) + { + return (character >= 0) && (character < 0x80) && isxdigit(character); + } + static int + UniCharIsDecDigit (int character) + { + return (character >= 0) && (character < 0x80) && isdigit(character); + } + SCOPE void + rde_param_i_value_clear (RDE_PARAM p) + { + SV_CLEAR (p); + } + SCOPE void + rde_param_i_value_leaf (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + Tcl_Obj* ov [3]; + long int pos = 1 + (long int) rde_stack_top (p->LS); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + newsv = Tcl_NewListObj (3, ov); + TRACE (("rde_param_i_value_leaf => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + } + SCOPE void + rde_param_i_value_reduce (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + int oc, i, j; + Tcl_Obj** ov; + long int ac; + Tcl_Obj** av; + long int pos = 1 + (long int) rde_stack_top (p->LS); + long int mark = (long int) rde_stack_top (p->mark); + long int asize = rde_stack_size (p->ast); + long int new = asize - mark; + ASSERT (new >= 0, "Bad number of elements to reduce"); + ov = NALLOC (3+new, Tcl_Obj*); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + rde_stack_get (p->ast, &ac, (void***) &av); + for (i = 3, j = mark; j < asize; i++, j++) { + ASSERT_BOUNDS (i, 3+new); + ASSERT_BOUNDS (j, ac); + ov [i] = av [j]; + } + ASSERT (i == 3+new, "Reduction result incomplete"); + newsv = Tcl_NewListObj (3+new, ov); + TRACE (("rde_param_i_value_reduce => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + ckfree ((char*) ov); + } + static int + er_int_compare (const void* a, const void* b) + { + long int ai = *((long int*) a); + long int bi = *((long int*) b); + if (ai < bi) { return -1; } + if (ai > bi) { return 1; } + return 0; + } + SCOPE int + rde_param_i_symbol_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE void + rde_param_i_symbol_done_d_reduce (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_reduce (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_d_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_symbol_done_d_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_next_char (RDE_PARAM p, char* c, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_char (p, c, m); + } + SCOPE void + rde_param_i_next_range (RDE_PARAM p, char* s, char* e, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_range (p, s, e, m); + } + SCOPE void + rde_param_i_next_alnum (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alnum (p); + } + SCOPE void + rde_param_i_next_alpha (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alpha (p); + } + SCOPE void + rde_param_i_next_ascii (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ascii (p); + } + SCOPE void + rde_param_i_next_control (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_control (p); + } + SCOPE void + rde_param_i_next_ddigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ddigit (p); + } + SCOPE void + rde_param_i_next_digit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_digit (p); + } + SCOPE void + rde_param_i_next_graph (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_graph (p); + } + SCOPE void + rde_param_i_next_lower (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_lower (p); + } + SCOPE void + rde_param_i_next_print (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_print (p); + } + SCOPE void + rde_param_i_next_punct (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_punct (p); + } + SCOPE void + rde_param_i_next_space (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_space (p); + } + SCOPE void + rde_param_i_next_upper (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_upper (p); + } + SCOPE void + rde_param_i_next_wordchar (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_wordchar (p); + } + SCOPE void + rde_param_i_next_xdigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_xdigit (p); + } + SCOPE void + rde_param_i_notahead_start_d (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_notahead_exit_d (RDE_PARAM p) + { + if (p->ST) { + rde_param_i_ast_pop_rewind (p); + } else { + rde_stack_pop (p->mark, 1); + } + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_notahead_exit (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_state_push_2 (RDE_PARAM p) + { + + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + SCOPE void + rde_param_i_state_push_void (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_push_value (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_merge_ok (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } + SCOPE int + rde_param_i_kleene_close (RDE_PARAM p) + { + int stop = !p->ST; + rde_param_i_error_pop_merge (p); + if (stop) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_kleene_abort (RDE_PARAM p) + { + int stop = !p->ST; + if (stop) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_seq_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_bra_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE void + rde_param_i_next_str (RDE_PARAM p, const char* str, int m) + { + int at = p->CL; + + while (*str) { + rde_param_i_input_next (p, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + rde_param_i_test_char (p, str, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + str = Tcl_UtfNext (str); + } + } + SCOPE void + rde_param_i_next_class (RDE_PARAM p, const char* class, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + while (*class) { + p->ST = Tcl_UtfNcmp (p->CC, class, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + return; + } + class = Tcl_UtfNext (class); + } + error_set (p, m); + p->CL --; + } + + + /* + * Declaring the parse functions + */ + + + /* + * Precomputed table of strings (symbols, error messages, etc.). + */ + + static char const* p_string [15] = { + /* 0 = */ "alnum", + /* 1 = */ "alpha", + /* 2 = */ "ascii", + /* 3 = */ "control", + /* 4 = */ "ddigit", + /* 5 = */ "digit", + /* 6 = */ "graph", + /* 7 = */ "lower", + /* 8 = */ "print", + /* 9 = */ "punct", + /* 10 = */ "space", + /* 11 = */ "upper", + /* 12 = */ "wordchar", + /* 13 = */ "xdigit", + /* 14 = */ "str abc" + }; + + /* + * Grammar Start Expression + */ + + static void MAIN (RDE_PARAM p) { + rde_param_i_next_str (p, "abc", 14); + return; + } + + /* -*- c -*- */ + + typedef struct PARSERg { + long int counter; + char buf [50]; + } PARSERg; + + static void + PARSERgRelease (ClientData cd, Tcl_Interp* interp) + { + ckfree((char*) cd); + } + + static const char* + PARSERnewName (Tcl_Interp* interp) + { +#define KEY "tcllib/parser/PACKAGE/TEA" + + Tcl_InterpDeleteProc* proc = PARSERgRelease; + PARSERg* parserg; + + parserg = Tcl_GetAssocData (interp, KEY, &proc); + if (parserg == NULL) { + parserg = (PARSERg*) ckalloc (sizeof (PARSERg)); + parserg->counter = 0; + + Tcl_SetAssocData (interp, KEY, proc, + (ClientData) parserg); + } + + parserg->counter ++; + sprintf (parserg->buf, "PARSER%d", parserg->counter); + return parserg->buf; +#undef KEY + } + + static void + PARSERdeleteCmd (ClientData clientData) + { + /* + * Release the whole PARSER + * (Low-level engine only actually). + */ + rde_param_del ((RDE_PARAM) clientData); + } + + + /* * ** *** ***** ******** ************* + ** Functions implementing the object methods, and helper. + */ + + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp); + + static int parser_PARSE (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + int mode; + Tcl_Channel chan; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "chan"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, + Tcl_GetString (objv[2]), + &mode); + + if (!chan) { + return TCL_ERROR; + } + + rde_param_reset (p, chan); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + static int parser_PARSET (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + char* buf; + int len; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "text"); + return TCL_ERROR; + } + + buf = Tcl_GetStringFromObj (objv[2], &len); + + rde_param_reset (p, NULL); + rde_param_data (p, buf, len); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + /* See also rde_critcl/m.c, param_COMPLETE() */ + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp) + { + if (rde_param_query_st (p)) { + long int ac; + Tcl_Obj** av; + + rde_param_query_ast (p, &ac, &av); + + if (ac > 1) { + Tcl_Obj** lv = NALLOC (3+ac, Tcl_Obj*); + + memcpy(lv + 3, av, ac * sizeof (Tcl_Obj*)); + lv [0] = Tcl_NewObj (); + lv [1] = Tcl_NewIntObj (1 + rde_param_query_lstop (p)); + lv [2] = Tcl_NewIntObj (rde_param_query_cl (p)); + + Tcl_SetObjResult (interp, Tcl_NewListObj (3, lv)); + ckfree ((char*) lv); + + } else if (ac == 0) { + /* + * Match, but no AST. This is possible if the grammar + * consists of only the start expression. + */ + Tcl_SetObjResult (interp, Tcl_NewStringObj ("",-1)); + } else { + Tcl_SetObjResult (interp, av [0]); + } + + return TCL_OK; + } else { + Tcl_Obj* xv [1]; + const ERROR_STATE* er = rde_param_query_er (p); + Tcl_Obj* res = rde_param_query_er_tcl (p, er); + /* res = list (location, list(msg)) */ + + /* Stick the exception type-tag before the existing elements */ + xv [0] = Tcl_NewStringObj ("pt::rde",-1); + Tcl_ListObjReplace(interp, res, 0, 0, 1, xv); + + Tcl_SetErrorCode (interp, "PT", "RDE", "SYNTAX", NULL); + Tcl_SetObjResult (interp, res); + return TCL_ERROR; + } + } + + + /* * ** *** ***** ******** ************* + ** Object command, method dispatch. + */ + static int parser_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + RDE_PARAM p = (RDE_PARAM) cd; + int m, res; + + static CONST char* methods [] = { + "destroy", "parse", "parset", NULL + }; + enum methods { + M_DESTROY, M_PARSE, M_PARSET + }; + + if (objc < 2) { + Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option", + 0, &m) != TCL_OK) { + return TCL_ERROR; + } + + /* Dispatch to methods. They check the #args in + * detail before performing the requested + * functionality + */ + + switch (m) { + case M_DESTROY: + if (objc != 2) { + Tcl_WrongNumArgs (interp, 2, objv, NULL); + return TCL_ERROR; + } + + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) rde_param_query_clientdata (p)); + return TCL_OK; + + case M_PARSE: res = parser_PARSE (p, interp, objc, objv); break; + case M_PARSET: res = parser_PARSET (p, interp, objc, objv); break; + default: + /* Not coming to this place */ + ASSERT (0,"Reached unreachable location"); + } + + return res; + } + + /** * ** *** ***** ******** ************* + * Class command, i.e. object construction. + */ + static int ParserClassCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const*objv) { + /* + * Syntax: No arguments beyond the name + */ + + RDE_PARAM parser; + CONST char* name; + Tcl_Obj* fqn; + Tcl_CmdInfo ci; + Tcl_Command c; + +#define USAGE "?name?" + + if ((objc != 2) && (objc != 1)) { + Tcl_WrongNumArgs (interp, 1, objv, USAGE); + return TCL_ERROR; + } + + if (objc < 2) { + name = PARSERnewName (interp); + } else { + name = Tcl_GetString (objv [1]); + } + + if (!Tcl_StringMatch (name, "::*")) { + /* Relative name. Prefix with current namespace */ + + Tcl_Eval (interp, "namespace current"); + fqn = Tcl_GetObjResult (interp); + fqn = Tcl_DuplicateObj (fqn); + Tcl_IncrRefCount (fqn); + + if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { + Tcl_AppendToObj (fqn, "::", -1); + } + Tcl_AppendToObj (fqn, name, -1); + } else { + fqn = Tcl_NewStringObj (name, -1); + Tcl_IncrRefCount (fqn); + } + Tcl_ResetResult (interp); + + if (Tcl_GetCommandInfo (interp, + Tcl_GetString (fqn), + &ci)) { + Tcl_Obj* err; + + err = Tcl_NewObj (); + Tcl_AppendToObj (err, "command \"", -1); + Tcl_AppendObjToObj (err, fqn); + Tcl_AppendToObj (err, "\" already exists", -1); + + Tcl_DecrRefCount (fqn); + Tcl_SetObjResult (interp, err); + return TCL_ERROR; + } + + parser = rde_param_new (sizeof(p_string)/sizeof(char*), (char**) p_string); + c = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), + parser_objcmd, (ClientData) parser, + PARSERdeleteCmd); + rde_param_clientdata (parser, (ClientData) c); + Tcl_SetObjResult (interp, fqn); + Tcl_DecrRefCount (fqn); + return TCL_OK; + } + +int Package_Init(Tcl_Interp* interp) { + if (interp == 0) return TCL_ERROR; + + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + + if (Tcl_CreateObjCommand(interp, "PARSER", ParserClassCmd , NULL, NULL) == NULL) { + Tcl_SetResult(interp, "Can't create constructor", NULL); + return TCL_ERROR; + } + + + Tcl_PkgProvide(interp, "PACKAGE", "0.1"); + + return TCL_OK; +} ADDED modules/pt/tests/data/ok/peg_cparam-tea/6_optional Index: modules/pt/tests/data/ok/peg_cparam-tea/6_optional ================================================================== --- /dev/null +++ modules/pt/tests/data/ok/peg_cparam-tea/6_optional @@ -0,0 +1,1995 @@ +/************************************************************ +** +** TEA-based C/PARAM implementation of the parsing +** expression grammar +** +** TEMPLATE +** +** Generated from file TEST +** for user unknown +** +* * ** *** ***** ******** ************* *********************/ + #include + #include + #include + #include + #define SCOPE static + +#line 1 "rde_critcl/util.h" + + #ifndef _RDE_UTIL_H + #define _RDE_UTIL_H 1 + #ifndef SCOPE + #define SCOPE + #endif + #define ALLOC(type) (type *) ckalloc (sizeof (type)) + #define NALLOC(n,type) (type *) ckalloc ((n) * sizeof (type)) + #undef RDE_DEBUG + #define RDE_DEBUG 1 + #undef RDE_TRACE + #ifdef RDE_DEBUG + #define STOPAFTER(x) { static int count = (x); count --; if (!count) { Tcl_Panic ("stop"); } } + #define XSTR(x) #x + #define STR(x) XSTR(x) + #define RANGEOK(i,n) ((0 <= (i)) && (i < (n))) + #define ASSERT(x,msg) if (!(x)) { Tcl_Panic (msg " (" #x "), in file " __FILE__ " @line " STR(__LINE__));} + #define ASSERT_BOUNDS(i,n) ASSERT (RANGEOK(i,n),"array index out of bounds: " STR(i) " >= " STR(n)) + #else + #define STOPAFTER(x) + #define ASSERT(x,msg) + #define ASSERT_BOUNDS(i,n) + #endif + #ifdef RDE_TRACE + SCOPE void trace_enter (const char* fun); + SCOPE void trace_return (const char *pat, ...); + SCOPE void trace_printf (const char *pat, ...); + #define ENTER(fun) trace_enter (fun) + #define RETURN(format,x) trace_return (format,x) ; return x + #define RETURNVOID trace_return ("%s","(void)") ; return + #define TRACE0(x) trace_printf0 x + #define TRACE(x) trace_printf x + #else + #define ENTER(fun) + #define RETURN(f,x) return x + #define RETURNVOID return + #define TRACE0(x) + #define TRACE(x) + #endif + #endif + + +#line 1 "rde_critcl/stack.h" + + #ifndef _RDE_DS_STACK_H + #define _RDE_DS_STACK_H 1 + typedef void (*RDE_STACK_CELL_FREE) (void* cell); + typedef struct RDE_STACK_* RDE_STACK; + static const int RDE_STACK_INITIAL_SIZE = 256; + #endif + + +#line 1 "rde_critcl/tc.h" + + #ifndef _RDE_DS_TC_H + #define _RDE_DS_TC_H 1 + typedef struct RDE_TC_* RDE_TC; + #endif + + +#line 1 "rde_critcl/param.h" + + #ifndef _RDE_DS_PARAM_H + #define _RDE_DS_PARAM_H 1 + typedef struct RDE_PARAM_* RDE_PARAM; + typedef struct ERROR_STATE { + int refCount; + long int loc; + RDE_STACK msg; + } ERROR_STATE; + typedef struct NC_STATE { + long int CL; + long int ST; + Tcl_Obj* SV; + ERROR_STATE* ER; + } NC_STATE; + #endif + + +#line 1 "rde_critcl/util.c" + + #ifdef RDE_TRACE + typedef struct F_STACK { + const char* str; + struct F_STACK* down; + } F_STACK; + static F_STACK* top = 0; + static int level = 0; + static void + push (const char* str) + { + F_STACK* new = ALLOC (F_STACK); + new->str = str; + new->down = top; + top = new; + level += 4; + } + static void + pop (void) + { + F_STACK* next = top->down; + level -= 4; + ckfree ((char*)top); + top = next; + } + static void + indent (void) + { + int i; + for (i = 0; i < level; i++) { + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + if (top) { + fwrite(top->str, 1, strlen(top->str), stdout); + fflush (stdout); + } + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + SCOPE void + trace_enter (const char* fun) + { + push (fun); + indent(); + fwrite("ENTER\n", 1, 6, stdout); + fflush (stdout); + } + static char msg [1024*1024]; + SCOPE void + trace_return (const char *pat, ...) + { + int len; + va_list args; + indent(); + fwrite("RETURN = ", 1, 9, stdout); + fflush (stdout); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + pop(); + } + SCOPE void + trace_printf (const char *pat, ...) + { + int len; + va_list args; + indent(); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + SCOPE void + trace_printf0 (const char *pat, ...) + { + int len; + va_list args; + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + #endif + + +#line 1 "rde_critcl/stack.c" + + typedef struct RDE_STACK_ { + long int max; + long int top; + RDE_STACK_CELL_FREE freeCellProc; + void** cell; + } RDE_STACK_; + + SCOPE RDE_STACK + rde_stack_new (RDE_STACK_CELL_FREE freeCellProc) + { + RDE_STACK s = ALLOC (RDE_STACK_); + s->cell = NALLOC (RDE_STACK_INITIAL_SIZE, void*); + s->max = RDE_STACK_INITIAL_SIZE; + s->top = 0; + s->freeCellProc = freeCellProc; + return s; + } + SCOPE void + rde_stack_del (RDE_STACK s) + { + if (s->freeCellProc && s->top) { + long int i; + for (i=0; i < s->top; i++) { + ASSERT_BOUNDS(i,s->max); + s->freeCellProc ( s->cell [i] ); + } + } + ckfree ((char*) s->cell); + ckfree ((char*) s); + } + SCOPE void + rde_stack_push (RDE_STACK s, void* item) + { + if (s->top >= s->max) { + long int new = s->max ? (2 * s->max) : RDE_STACK_INITIAL_SIZE; + void** cell = (void**) ckrealloc ((char*) s->cell, new * sizeof(void*)); + ASSERT (cell,"Memory allocation failure for RDE stack"); + s->max = new; + s->cell = cell; + } + ASSERT_BOUNDS(s->top,s->max); + s->cell [s->top] = item; + s->top ++; + } + SCOPE void* + rde_stack_top (RDE_STACK s) + { + ASSERT_BOUNDS(s->top-1,s->max); + return s->cell [s->top - 1]; + } + SCOPE void + rde_stack_pop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + if (s->freeCellProc) { + while (n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + n --; + } + } else { + s->top -= n; + } + } + SCOPE void + rde_stack_trim (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad trimsize"); + if (s->freeCellProc) { + while (s->top > n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + } + } else { + s->top = n; + } + } + SCOPE void + rde_stack_drop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + s->top -= n; + } + SCOPE void + rde_stack_move (RDE_STACK dst, RDE_STACK src) + { + ASSERT (dst->freeCellProc == src->freeCellProc, "Ownership mismatch"); + + while (src->top > 0) { + src->top --; + ASSERT_BOUNDS(src->top,src->max); + rde_stack_push (dst, src->cell [src->top] ); + } + } + SCOPE void + rde_stack_get (RDE_STACK s, long int* cn, void*** cc) + { + *cn = s->top; + *cc = s->cell; + } + SCOPE long int + rde_stack_size (RDE_STACK s) + { + return s->top; + } + + +#line 1 "rde_critcl/tc.c" + + typedef struct RDE_TC_ { + int max; + int num; + char* str; + RDE_STACK off; + } RDE_TC_; + + SCOPE RDE_TC + rde_tc_new (void) + { + RDE_TC tc = ALLOC (RDE_TC_); + tc->max = RDE_STACK_INITIAL_SIZE; + tc->num = 0; + tc->str = NALLOC (RDE_STACK_INITIAL_SIZE, char); + tc->off = rde_stack_new (NULL); + return tc; + } + SCOPE void + rde_tc_del (RDE_TC tc) + { + rde_stack_del (tc->off); + ckfree (tc->str); + ckfree ((char*) tc); + } + SCOPE long int + rde_tc_size (RDE_TC tc) + { + return rde_stack_size (tc->off); + } + SCOPE void + rde_tc_clear (RDE_TC tc) + { + tc->num = 0; + rde_stack_trim (tc->off, 0); + } + SCOPE char* + rde_tc_append (RDE_TC tc, char* string, long int len) + { + long int base = tc->num; + long int off = tc->num; + char* ch; + int clen; + Tcl_UniChar uni; + if (len < 0) { + len = strlen (string); + } + + if (!len) { + return tc->str + base; + } + + if ((tc->num + len) >= tc->max) { + int new = len + (tc->max ? (2 * tc->max) : RDE_STACK_INITIAL_SIZE); + char* str = ckrealloc (tc->str, new * sizeof(char)); + ASSERT (str,"Memory allocation failure for token character array"); + tc->max = new; + tc->str = str; + } + tc->num += len; + ASSERT_BOUNDS(tc->num,tc->max); + ASSERT_BOUNDS(off,tc->max); + ASSERT_BOUNDS(off+len-1,tc->max); + ASSERT_BOUNDS(off+len-1,tc->num); + memcpy (tc->str + off, string, len); + + ch = string; + while (ch < (string + len)) { + ASSERT_BOUNDS(off,tc->num); + rde_stack_push (tc->off, (void*) off); + clen = Tcl_UtfToUniChar (ch, &uni); + off += clen; + ch += clen; + } + return tc->str + base; + } + SCOPE void + rde_tc_get (RDE_TC tc, int at, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + off = ov [at]; + if ((at+1) == oc) { + end = tc->num; + } else { + end = ov [at+1]; + } + TRACE (("rde_tc_get (RDE_TC %p, @ %d) => %d.[%d ... %d]/%d",tc,at,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + SCOPE void + rde_tc_get_s (RDE_TC tc, int at, int last, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + ASSERT_BOUNDS(last,oc); + off = ov [at]; + if ((last+1) == oc) { + end = tc->num; + } else { + end = ov [last+1]; + } + TRACE (("rde_tc_get_s (RDE_TC %p, @ %d .. %d) => %d.[%d ... %d]/%d",tc,at,last,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + + +#line 1 "rde_critcl/param.c" + + typedef struct RDE_PARAM_ { + Tcl_Channel IN; + Tcl_Obj* readbuf; + char* CC; + long int CC_len; + RDE_TC TC; + long int CL; + RDE_STACK LS; + ERROR_STATE* ER; + RDE_STACK ES; + long int ST; + Tcl_Obj* SV; + Tcl_HashTable NC; + + RDE_STACK ast ; + RDE_STACK mark ; + + long int numstr; + char** string; + + ClientData clientData; + } RDE_PARAM_; + typedef int (*UniCharClass) (int); + typedef enum test_class_id { + tc_alnum, + tc_alpha, + tc_ascii, + tc_control, + tc_ddigit, + tc_digit, + tc_graph, + tc_lower, + tc_printable, + tc_punct, + tc_space, + tc_upper, + tc_wordchar, + tc_xdigit + } test_class_id; + static void ast_node_free (void* n); + static void error_state_free (void* es); + static void error_set (RDE_PARAM p, int s); + static void nc_clear (RDE_PARAM p); + static int UniCharIsAscii (int character); + static int UniCharIsHexDigit (int character); + static int UniCharIsDecDigit (int character); + static void test_class (RDE_PARAM p, UniCharClass class, test_class_id id); + static int er_int_compare (const void* a, const void* b); + #define SV_INIT(p) \ + p->SV = NULL; \ + TRACE (("SV_INIT (%p => %p)", (p), (p)->SV)) + #define SV_SET(p,newsv) \ + if (((p)->SV) != (newsv)) { \ + TRACE (("SV_CLEAR/set (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = (newsv); \ + TRACE (("SV_SET (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_IncrRefCount ((p)->SV); \ + } \ + } + #define SV_CLEAR(p) \ + TRACE (("SV_CLEAR (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = NULL + #define ER_INIT(p) \ + p->ER = NULL; \ + TRACE (("ER_INIT (%p => %p)", (p), (p)->ER)) + #define ER_CLEAR(p) \ + error_state_free ((p)->ER); \ + (p)->ER = NULL + SCOPE RDE_PARAM + rde_param_new (long int nstr, char** strings) + { + RDE_PARAM p; + ENTER ("rde_param_new"); + TRACE (("\tINT %d strings @ %p", nstr, strings)); + p = ALLOC (RDE_PARAM_); + p->numstr = nstr; + p->string = strings; + p->readbuf = Tcl_NewObj (); + Tcl_IncrRefCount (p->readbuf); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_InitHashTable (&p->NC, TCL_ONE_WORD_KEYS); + p->IN = NULL; + p->CL = -1; + p->ST = 0; + ER_INIT (p); + SV_INIT (p); + p->CC = NULL; + p->CC_len = 0; + p->TC = rde_tc_new (); + p->ES = rde_stack_new (error_state_free); + p->LS = rde_stack_new (NULL); + p->ast = rde_stack_new (ast_node_free); + p->mark = rde_stack_new (NULL); + RETURN ("%p", p); + } + SCOPE void + rde_param_del (RDE_PARAM p) + { + ENTER ("rde_param_del"); + TRACE (("RDE_PARAM %p",p)); + ER_CLEAR (p); TRACE (("\ter_clear")); + SV_CLEAR (p); TRACE (("\tsv_clear")); + nc_clear (p); TRACE (("\tnc_clear")); + Tcl_DeleteHashTable (&p->NC); TRACE (("\tnc hashtable delete")); + rde_tc_del (p->TC); TRACE (("\ttc clear")); + rde_stack_del (p->ES); TRACE (("\tes clear")); + rde_stack_del (p->LS); TRACE (("\tls clear")); + rde_stack_del (p->ast); TRACE (("\tast clear")); + rde_stack_del (p->mark); TRACE (("\tmark clear")); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_DecrRefCount (p->readbuf); + ckfree ((char*) p); + RETURNVOID; + } + SCOPE void + rde_param_reset (RDE_PARAM p, Tcl_Channel chan) + { + ENTER ("rde_param_reset"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("Tcl_Channel %p",chan)); + p->IN = chan; + p->CL = -1; + p->ST = 0; + p->CC = NULL; + p->CC_len = 0; + ER_CLEAR (p); + SV_CLEAR (p); + nc_clear (p); + rde_tc_clear (p->TC); + rde_stack_trim (p->ES, 0); + rde_stack_trim (p->LS, 0); + rde_stack_trim (p->ast, 0); + rde_stack_trim (p->mark, 0); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + RETURNVOID; + } + SCOPE void + rde_param_update_strings (RDE_PARAM p, long int nstr, char** strings) + { + ENTER ("rde_param_update_strings"); + TRACE (("RDE_PARAM %p", p)); + TRACE (("INT %d strings", nstr)); + p->numstr = nstr; + p->string = strings; + RETURNVOID; + } + SCOPE void + rde_param_data (RDE_PARAM p, char* buf, long int len) + { + (void) rde_tc_append (p->TC, buf, len); + } + SCOPE void + rde_param_clientdata (RDE_PARAM p, ClientData clientData) + { + p->clientData = clientData; + } + static void + nc_clear (RDE_PARAM p) + { + Tcl_HashSearch hs; + Tcl_HashEntry* he; + Tcl_HashTable* tablePtr; + for(he = Tcl_FirstHashEntry(&p->NC, &hs); + he != NULL; + he = Tcl_FirstHashEntry(&p->NC, &hs)) { + Tcl_HashSearch hsc; + Tcl_HashEntry* hec; + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (he); + for(hec = Tcl_FirstHashEntry(tablePtr, &hsc); + hec != NULL; + hec = Tcl_NextHashEntry(&hsc)) { + NC_STATE* scs = Tcl_GetHashValue (hec); + error_state_free (scs->ER); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + ckfree ((char*) scs); + } + Tcl_DeleteHashTable (tablePtr); + ckfree ((char*) tablePtr); + Tcl_DeleteHashEntry (he); + } + } + SCOPE ClientData + rde_param_query_clientdata (RDE_PARAM p) + { + return p->clientData; + } + SCOPE void + rde_param_query_amark (RDE_PARAM p, long int* mc, long int** mv) + { + rde_stack_get (p->mark, mc, (void***) mv); + } + SCOPE void + rde_param_query_ast (RDE_PARAM p, long int* ac, Tcl_Obj*** av) + { + rde_stack_get (p->ast, ac, (void***) av); + } + SCOPE const char* + rde_param_query_in (RDE_PARAM p) + { + return p->IN + ? Tcl_GetChannelName (p->IN) + : ""; + } + SCOPE const char* + rde_param_query_cc (RDE_PARAM p, long int* len) + { + *len = p->CC_len; + return p->CC; + } + SCOPE int + rde_param_query_cl (RDE_PARAM p) + { + return p->CL; + } + SCOPE const ERROR_STATE* + rde_param_query_er (RDE_PARAM p) + { + return p->ER; + } + SCOPE Tcl_Obj* + rde_param_query_er_tcl (RDE_PARAM p, const ERROR_STATE* er) + { + Tcl_Obj* res; + if (!er) { + + res = Tcl_NewStringObj ("", 0); + } else { + Tcl_Obj* ov [2]; + Tcl_Obj** mov; + long int mc, i, j; + long int* mv; + int lastid; + const char* msg; + rde_stack_get (er->msg, &mc, (void***) &mv); + + qsort (mv, mc, sizeof (long int), er_int_compare); + + mov = NALLOC (mc, Tcl_Obj*); + lastid = -1; + for (i=0, j=0; i < mc; i++) { + ASSERT_BOUNDS (i,mc); + if (mv [i] == lastid) continue; + lastid = mv [i]; + ASSERT_BOUNDS(mv[i],p->numstr); + msg = p->string [mv[i]]; + ASSERT_BOUNDS (j,mc); + mov [j] = Tcl_NewStringObj (msg, -1); + j++; + } + + ov [0] = Tcl_NewIntObj (er->loc); + ov [1] = Tcl_NewListObj (j, mov); + res = Tcl_NewListObj (2, ov); + ckfree ((char*) mov); + } + return res; + } + SCOPE void + rde_param_query_es (RDE_PARAM p, long int* ec, ERROR_STATE*** ev) + { + rde_stack_get (p->ES, ec, (void***) ev); + } + SCOPE void + rde_param_query_ls (RDE_PARAM p, long int* lc, void*** lv) + { + rde_stack_get (p->LS, lc, lv); + } + SCOPE long int + rde_param_query_lstop (RDE_PARAM p) + { + (long int) rde_stack_top (p->LS); + } + SCOPE Tcl_HashTable* + rde_param_query_nc (RDE_PARAM p) + { + return &p->NC; + } + SCOPE int + rde_param_query_st (RDE_PARAM p) + { + return p->ST; + } + SCOPE Tcl_Obj* + rde_param_query_sv (RDE_PARAM p) + { + TRACE (("SV_QUERY %p => (%p)", (p), (p)->SV)); \ + return p->SV; + } + SCOPE long int + rde_param_query_tc_size (RDE_PARAM p) + { + return rde_tc_size (p->TC); + } + SCOPE void + rde_param_query_tc_get_s (RDE_PARAM p, long int at, long int last, char** ch, long int* len) + { + rde_tc_get_s (p->TC, at, last, ch, len); + } + SCOPE const char* + rde_param_query_string (RDE_PARAM p, long int id) + { + TRACE (("rde_param_query_string (RDE_PARAM %p, %d/%d)", p, id, p->numstr)); + ASSERT_BOUNDS(id,p->numstr); + return p->string [id]; + } + SCOPE void + rde_param_i_ast_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->mark, 1); + } + SCOPE void + rde_param_i_ast_pop_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_pop_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_push (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_ast_value_push (RDE_PARAM p) + { + ENTER ("rde_param_i_ast_value_push"); + TRACE (("RDE_PARAM %p",p)); + ASSERT(p->SV,"Unable to push undefined semantic value"); + TRACE (("rde_param_i_ast_value_push %p => (%p)", p, p->SV)); + TRACE (("SV = (%p rc%d '%s')", p->SV, p->SV->refCount, Tcl_GetString (p->SV))); + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + RETURNVOID; + } + static void + ast_node_free (void* n) + { + Tcl_DecrRefCount ((Tcl_Obj*) n); + } + SCOPE void + rde_param_i_error_clear (RDE_PARAM p) + { + ER_CLEAR (p); + } + SCOPE void + rde_param_i_error_nonterminal (RDE_PARAM p, int s) + { + + return; + long int pos; + if (!p->ER) return; + pos = 1 + (long int) rde_stack_top (p->LS); + if (p->ER->loc != pos) return; + error_set (p, s); + p->ER->loc = pos; + } + SCOPE void + rde_param_i_error_pop_merge (RDE_PARAM p) + { + ERROR_STATE* top = (ERROR_STATE*) rde_stack_top (p->ES); + + if (top == p->ER) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!top) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!p->ER) { + rde_stack_drop (p->ES, 1); + p->ER = top; + + return; + } + + if (top->loc < p->ER->loc) { + rde_stack_pop (p->ES, 1); + return; + } + + if (top->loc > p->ER->loc) { + rde_stack_drop (p->ES, 1); + error_state_free (p->ER); + p->ER = top; + + return; + } + + rde_stack_move (p->ER->msg, top->msg); + rde_stack_pop (p->ES, 1); + } + SCOPE void + rde_param_i_error_push (RDE_PARAM p) + { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + static void + error_set (RDE_PARAM p, int s) + { + error_state_free (p->ER); + p->ER = ALLOC (ERROR_STATE); + p->ER->refCount = 1; + p->ER->loc = p->CL; + p->ER->msg = rde_stack_new (NULL); + ASSERT_BOUNDS(s,p->numstr); + rde_stack_push (p->ER->msg, (void*) s); + } + static void + error_state_free (void* esx) + { + ERROR_STATE* es = esx; + if (!es) return; + es->refCount --; + if (es->refCount > 0) return; + rde_stack_del (es->msg); + ckfree ((char*) es); + } + SCOPE void + rde_param_i_loc_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_pop_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_push (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + } + SCOPE void + rde_param_i_loc_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + } + SCOPE void + rde_param_i_input_next (RDE_PARAM p, int m) + { + int leni; + char* ch; + ASSERT_BOUNDS(m,p->numstr); + p->CL ++; + if (p->CL < rde_tc_size (p->TC)) { + + rde_tc_get (p->TC, p->CL, &p->CC, &p->CC_len); + ASSERT_BOUNDS (p->CC_len, TCL_UTF_MAX); + p->ST = 1; + ER_CLEAR (p); + return; + } + if (!p->IN || + Tcl_Eof (p->IN) || + (Tcl_ReadChars (p->IN, p->readbuf, 1, 0) <= 0)) { + + p->ST = 0; + error_set (p, m); + return; + } + + ch = Tcl_GetStringFromObj (p->readbuf, &leni); + ASSERT_BOUNDS (leni, TCL_UTF_MAX); + p->CC = rde_tc_append (p->TC, ch, leni); + p->CC_len = leni; + p->ST = 1; + ER_CLEAR (p); + } + SCOPE void + rde_param_i_status_fail (RDE_PARAM p) + { + p->ST = 0; + } + SCOPE void + rde_param_i_status_ok (RDE_PARAM p) + { + p->ST = 1; + } + SCOPE void + rde_param_i_status_negate (RDE_PARAM p) + { + p->ST = !p->ST; + } + SCOPE int + rde_param_i_symbol_restore (RDE_PARAM p, int s) + { + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + + hPtr = Tcl_FindHashEntry (&p->NC, (char*) p->CL); + if (!hPtr) { return 0; } + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + hPtr = Tcl_FindHashEntry (tablePtr, (char*) s); + if (!hPtr) { return 0; } + + scs = Tcl_GetHashValue (hPtr); + p->CL = scs->CL; + p->ST = scs->ST; + error_state_free (p->ER); + p->ER = scs->ER; + if (p->ER) { p->ER->refCount ++; } + TRACE (("SV_RESTORE (%p) '%s'",scs->SV, scs->SV ? Tcl_GetString (scs->SV):"")); + SV_SET (p, scs->SV); + return 1; + } + SCOPE void + rde_param_i_symbol_save (RDE_PARAM p, int s) + { + long int at = (long int) rde_stack_top (p->LS); + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + int isnew; + ENTER ("rde_param_i_symbol_save"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("INT %d",s)); + + hPtr = Tcl_CreateHashEntry (&p->NC, (char*) at, &isnew); + if (isnew) { + tablePtr = ALLOC (Tcl_HashTable); + Tcl_InitHashTable (tablePtr, TCL_ONE_WORD_KEYS); + Tcl_SetHashValue (hPtr, tablePtr); + } else { + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + } + hPtr = Tcl_CreateHashEntry (tablePtr, (char*) s, &isnew); + if (isnew) { + + scs = ALLOC (NC_STATE); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "")); + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + Tcl_SetHashValue (hPtr, scs); + } else { + + scs = (NC_STATE*) Tcl_GetHashValue (hPtr); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE/over (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "" )); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + error_state_free (scs->ER); + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + } + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_test_alnum (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlnum, tc_alnum); + } + SCOPE void + rde_param_i_test_alpha (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlpha, tc_alpha); + } + SCOPE void + rde_param_i_test_ascii (RDE_PARAM p) + { + test_class (p, UniCharIsAscii, tc_ascii); + } + SCOPE void + rde_param_i_test_control (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsControl, tc_control); + } + SCOPE void + rde_param_i_test_char (RDE_PARAM p, const char* c, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = Tcl_UtfNcmp (p->CC, c, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_ddigit (RDE_PARAM p) + { + test_class (p, UniCharIsDecDigit, tc_ddigit); + } + SCOPE void + rde_param_i_test_digit (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsDigit, tc_digit); + } + SCOPE void + rde_param_i_test_graph (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsGraph, tc_graph); + } + SCOPE void + rde_param_i_test_lower (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsLower, tc_lower); + } + SCOPE void + rde_param_i_test_print (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPrint, tc_printable); + } + SCOPE void + rde_param_i_test_punct (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPunct, tc_punct); + } + SCOPE void + rde_param_i_test_range (RDE_PARAM p, char* s, char* e, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = + (Tcl_UtfNcmp (s, p->CC, 1) <= 0) && + (Tcl_UtfNcmp (p->CC, e, 1) <= 0); + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_space (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsSpace, tc_space); + } + SCOPE void + rde_param_i_test_upper (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsUpper, tc_upper); + } + SCOPE void + rde_param_i_test_wordchar (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsWordChar, tc_wordchar); + } + SCOPE void + rde_param_i_test_xdigit (RDE_PARAM p) + { + test_class (p, UniCharIsHexDigit, tc_xdigit); + } + static void + test_class (RDE_PARAM p, UniCharClass class, test_class_id id) + { + Tcl_UniChar ch; + Tcl_UtfToUniChar(p->CC, &ch); + ASSERT_BOUNDS(id,p->numstr); + p->ST = !!class (ch); + + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, id); + p->CL --; + } + } + static int + UniCharIsAscii (int character) + { + return (character >= 0) && (character < 0x80); + } + static int + UniCharIsHexDigit (int character) + { + return (character >= 0) && (character < 0x80) && isxdigit(character); + } + static int + UniCharIsDecDigit (int character) + { + return (character >= 0) && (character < 0x80) && isdigit(character); + } + SCOPE void + rde_param_i_value_clear (RDE_PARAM p) + { + SV_CLEAR (p); + } + SCOPE void + rde_param_i_value_leaf (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + Tcl_Obj* ov [3]; + long int pos = 1 + (long int) rde_stack_top (p->LS); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + newsv = Tcl_NewListObj (3, ov); + TRACE (("rde_param_i_value_leaf => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + } + SCOPE void + rde_param_i_value_reduce (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + int oc, i, j; + Tcl_Obj** ov; + long int ac; + Tcl_Obj** av; + long int pos = 1 + (long int) rde_stack_top (p->LS); + long int mark = (long int) rde_stack_top (p->mark); + long int asize = rde_stack_size (p->ast); + long int new = asize - mark; + ASSERT (new >= 0, "Bad number of elements to reduce"); + ov = NALLOC (3+new, Tcl_Obj*); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + rde_stack_get (p->ast, &ac, (void***) &av); + for (i = 3, j = mark; j < asize; i++, j++) { + ASSERT_BOUNDS (i, 3+new); + ASSERT_BOUNDS (j, ac); + ov [i] = av [j]; + } + ASSERT (i == 3+new, "Reduction result incomplete"); + newsv = Tcl_NewListObj (3+new, ov); + TRACE (("rde_param_i_value_reduce => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + ckfree ((char*) ov); + } + static int + er_int_compare (const void* a, const void* b) + { + long int ai = *((long int*) a); + long int bi = *((long int*) b); + if (ai < bi) { return -1; } + if (ai > bi) { return 1; } + return 0; + } + SCOPE int + rde_param_i_symbol_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE void + rde_param_i_symbol_done_d_reduce (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_reduce (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_d_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_symbol_done_d_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_next_char (RDE_PARAM p, char* c, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_char (p, c, m); + } + SCOPE void + rde_param_i_next_range (RDE_PARAM p, char* s, char* e, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_range (p, s, e, m); + } + SCOPE void + rde_param_i_next_alnum (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alnum (p); + } + SCOPE void + rde_param_i_next_alpha (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alpha (p); + } + SCOPE void + rde_param_i_next_ascii (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ascii (p); + } + SCOPE void + rde_param_i_next_control (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_control (p); + } + SCOPE void + rde_param_i_next_ddigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ddigit (p); + } + SCOPE void + rde_param_i_next_digit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_digit (p); + } + SCOPE void + rde_param_i_next_graph (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_graph (p); + } + SCOPE void + rde_param_i_next_lower (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_lower (p); + } + SCOPE void + rde_param_i_next_print (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_print (p); + } + SCOPE void + rde_param_i_next_punct (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_punct (p); + } + SCOPE void + rde_param_i_next_space (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_space (p); + } + SCOPE void + rde_param_i_next_upper (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_upper (p); + } + SCOPE void + rde_param_i_next_wordchar (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_wordchar (p); + } + SCOPE void + rde_param_i_next_xdigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_xdigit (p); + } + SCOPE void + rde_param_i_notahead_start_d (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_notahead_exit_d (RDE_PARAM p) + { + if (p->ST) { + rde_param_i_ast_pop_rewind (p); + } else { + rde_stack_pop (p->mark, 1); + } + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_notahead_exit (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_state_push_2 (RDE_PARAM p) + { + + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + SCOPE void + rde_param_i_state_push_void (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_push_value (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_merge_ok (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } + SCOPE int + rde_param_i_kleene_close (RDE_PARAM p) + { + int stop = !p->ST; + rde_param_i_error_pop_merge (p); + if (stop) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_kleene_abort (RDE_PARAM p) + { + int stop = !p->ST; + if (stop) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_seq_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_bra_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE void + rde_param_i_next_str (RDE_PARAM p, const char* str, int m) + { + int at = p->CL; + + while (*str) { + rde_param_i_input_next (p, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + rde_param_i_test_char (p, str, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + str = Tcl_UtfNext (str); + } + } + SCOPE void + rde_param_i_next_class (RDE_PARAM p, const char* class, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + while (*class) { + p->ST = Tcl_UtfNcmp (p->CC, class, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + return; + } + class = Tcl_UtfNext (class); + } + error_set (p, m); + p->CL --; + } + + + /* + * Declaring the parse functions + */ + + static void optional_2 (RDE_PARAM p); + + /* + * Precomputed table of strings (symbols, error messages, etc.). + */ + + static char const* p_string [15] = { + /* 0 = */ "alnum", + /* 1 = */ "alpha", + /* 2 = */ "ascii", + /* 3 = */ "control", + /* 4 = */ "ddigit", + /* 5 = */ "digit", + /* 6 = */ "graph", + /* 7 = */ "lower", + /* 8 = */ "print", + /* 9 = */ "punct", + /* 10 = */ "space", + /* 11 = */ "upper", + /* 12 = */ "wordchar", + /* 13 = */ "xdigit", + /* 14 = */ "t a" + }; + + /* + * Grammar Start Expression + */ + + static void MAIN (RDE_PARAM p) { + optional_2 (p); + return; + } + + static void optional_2 (RDE_PARAM p) { + /* + * ? + * 'a' + */ + + rde_param_i_state_push_2 (p); + rde_param_i_next_char (p, "a", 14); + rde_param_i_state_merge_ok (p); + return; + } + + /* -*- c -*- */ + + typedef struct PARSERg { + long int counter; + char buf [50]; + } PARSERg; + + static void + PARSERgRelease (ClientData cd, Tcl_Interp* interp) + { + ckfree((char*) cd); + } + + static const char* + PARSERnewName (Tcl_Interp* interp) + { +#define KEY "tcllib/parser/PACKAGE/TEA" + + Tcl_InterpDeleteProc* proc = PARSERgRelease; + PARSERg* parserg; + + parserg = Tcl_GetAssocData (interp, KEY, &proc); + if (parserg == NULL) { + parserg = (PARSERg*) ckalloc (sizeof (PARSERg)); + parserg->counter = 0; + + Tcl_SetAssocData (interp, KEY, proc, + (ClientData) parserg); + } + + parserg->counter ++; + sprintf (parserg->buf, "PARSER%d", parserg->counter); + return parserg->buf; +#undef KEY + } + + static void + PARSERdeleteCmd (ClientData clientData) + { + /* + * Release the whole PARSER + * (Low-level engine only actually). + */ + rde_param_del ((RDE_PARAM) clientData); + } + + + /* * ** *** ***** ******** ************* + ** Functions implementing the object methods, and helper. + */ + + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp); + + static int parser_PARSE (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + int mode; + Tcl_Channel chan; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "chan"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, + Tcl_GetString (objv[2]), + &mode); + + if (!chan) { + return TCL_ERROR; + } + + rde_param_reset (p, chan); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + static int parser_PARSET (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + char* buf; + int len; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "text"); + return TCL_ERROR; + } + + buf = Tcl_GetStringFromObj (objv[2], &len); + + rde_param_reset (p, NULL); + rde_param_data (p, buf, len); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + /* See also rde_critcl/m.c, param_COMPLETE() */ + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp) + { + if (rde_param_query_st (p)) { + long int ac; + Tcl_Obj** av; + + rde_param_query_ast (p, &ac, &av); + + if (ac > 1) { + Tcl_Obj** lv = NALLOC (3+ac, Tcl_Obj*); + + memcpy(lv + 3, av, ac * sizeof (Tcl_Obj*)); + lv [0] = Tcl_NewObj (); + lv [1] = Tcl_NewIntObj (1 + rde_param_query_lstop (p)); + lv [2] = Tcl_NewIntObj (rde_param_query_cl (p)); + + Tcl_SetObjResult (interp, Tcl_NewListObj (3, lv)); + ckfree ((char*) lv); + + } else if (ac == 0) { + /* + * Match, but no AST. This is possible if the grammar + * consists of only the start expression. + */ + Tcl_SetObjResult (interp, Tcl_NewStringObj ("",-1)); + } else { + Tcl_SetObjResult (interp, av [0]); + } + + return TCL_OK; + } else { + Tcl_Obj* xv [1]; + const ERROR_STATE* er = rde_param_query_er (p); + Tcl_Obj* res = rde_param_query_er_tcl (p, er); + /* res = list (location, list(msg)) */ + + /* Stick the exception type-tag before the existing elements */ + xv [0] = Tcl_NewStringObj ("pt::rde",-1); + Tcl_ListObjReplace(interp, res, 0, 0, 1, xv); + + Tcl_SetErrorCode (interp, "PT", "RDE", "SYNTAX", NULL); + Tcl_SetObjResult (interp, res); + return TCL_ERROR; + } + } + + + /* * ** *** ***** ******** ************* + ** Object command, method dispatch. + */ + static int parser_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + RDE_PARAM p = (RDE_PARAM) cd; + int m, res; + + static CONST char* methods [] = { + "destroy", "parse", "parset", NULL + }; + enum methods { + M_DESTROY, M_PARSE, M_PARSET + }; + + if (objc < 2) { + Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option", + 0, &m) != TCL_OK) { + return TCL_ERROR; + } + + /* Dispatch to methods. They check the #args in + * detail before performing the requested + * functionality + */ + + switch (m) { + case M_DESTROY: + if (objc != 2) { + Tcl_WrongNumArgs (interp, 2, objv, NULL); + return TCL_ERROR; + } + + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) rde_param_query_clientdata (p)); + return TCL_OK; + + case M_PARSE: res = parser_PARSE (p, interp, objc, objv); break; + case M_PARSET: res = parser_PARSET (p, interp, objc, objv); break; + default: + /* Not coming to this place */ + ASSERT (0,"Reached unreachable location"); + } + + return res; + } + + /** * ** *** ***** ******** ************* + * Class command, i.e. object construction. + */ + static int ParserClassCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const*objv) { + /* + * Syntax: No arguments beyond the name + */ + + RDE_PARAM parser; + CONST char* name; + Tcl_Obj* fqn; + Tcl_CmdInfo ci; + Tcl_Command c; + +#define USAGE "?name?" + + if ((objc != 2) && (objc != 1)) { + Tcl_WrongNumArgs (interp, 1, objv, USAGE); + return TCL_ERROR; + } + + if (objc < 2) { + name = PARSERnewName (interp); + } else { + name = Tcl_GetString (objv [1]); + } + + if (!Tcl_StringMatch (name, "::*")) { + /* Relative name. Prefix with current namespace */ + + Tcl_Eval (interp, "namespace current"); + fqn = Tcl_GetObjResult (interp); + fqn = Tcl_DuplicateObj (fqn); + Tcl_IncrRefCount (fqn); + + if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { + Tcl_AppendToObj (fqn, "::", -1); + } + Tcl_AppendToObj (fqn, name, -1); + } else { + fqn = Tcl_NewStringObj (name, -1); + Tcl_IncrRefCount (fqn); + } + Tcl_ResetResult (interp); + + if (Tcl_GetCommandInfo (interp, + Tcl_GetString (fqn), + &ci)) { + Tcl_Obj* err; + + err = Tcl_NewObj (); + Tcl_AppendToObj (err, "command \"", -1); + Tcl_AppendObjToObj (err, fqn); + Tcl_AppendToObj (err, "\" already exists", -1); + + Tcl_DecrRefCount (fqn); + Tcl_SetObjResult (interp, err); + return TCL_ERROR; + } + + parser = rde_param_new (sizeof(p_string)/sizeof(char*), (char**) p_string); + c = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), + parser_objcmd, (ClientData) parser, + PARSERdeleteCmd); + rde_param_clientdata (parser, (ClientData) c); + Tcl_SetObjResult (interp, fqn); + Tcl_DecrRefCount (fqn); + return TCL_OK; + } + +int Package_Init(Tcl_Interp* interp) { + if (interp == 0) return TCL_ERROR; + + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + + if (Tcl_CreateObjCommand(interp, "PARSER", ParserClassCmd , NULL, NULL) == NULL) { + Tcl_SetResult(interp, "Can't create constructor", NULL); + return TCL_ERROR; + } + + + Tcl_PkgProvide(interp, "PACKAGE", "0.1"); + + return TCL_OK; +} ADDED modules/pt/tests/data/ok/peg_cparam-tea/7_kleene Index: modules/pt/tests/data/ok/peg_cparam-tea/7_kleene ================================================================== --- /dev/null +++ modules/pt/tests/data/ok/peg_cparam-tea/7_kleene @@ -0,0 +1,1997 @@ +/************************************************************ +** +** TEA-based C/PARAM implementation of the parsing +** expression grammar +** +** TEMPLATE +** +** Generated from file TEST +** for user unknown +** +* * ** *** ***** ******** ************* *********************/ + #include + #include + #include + #include + #define SCOPE static + +#line 1 "rde_critcl/util.h" + + #ifndef _RDE_UTIL_H + #define _RDE_UTIL_H 1 + #ifndef SCOPE + #define SCOPE + #endif + #define ALLOC(type) (type *) ckalloc (sizeof (type)) + #define NALLOC(n,type) (type *) ckalloc ((n) * sizeof (type)) + #undef RDE_DEBUG + #define RDE_DEBUG 1 + #undef RDE_TRACE + #ifdef RDE_DEBUG + #define STOPAFTER(x) { static int count = (x); count --; if (!count) { Tcl_Panic ("stop"); } } + #define XSTR(x) #x + #define STR(x) XSTR(x) + #define RANGEOK(i,n) ((0 <= (i)) && (i < (n))) + #define ASSERT(x,msg) if (!(x)) { Tcl_Panic (msg " (" #x "), in file " __FILE__ " @line " STR(__LINE__));} + #define ASSERT_BOUNDS(i,n) ASSERT (RANGEOK(i,n),"array index out of bounds: " STR(i) " >= " STR(n)) + #else + #define STOPAFTER(x) + #define ASSERT(x,msg) + #define ASSERT_BOUNDS(i,n) + #endif + #ifdef RDE_TRACE + SCOPE void trace_enter (const char* fun); + SCOPE void trace_return (const char *pat, ...); + SCOPE void trace_printf (const char *pat, ...); + #define ENTER(fun) trace_enter (fun) + #define RETURN(format,x) trace_return (format,x) ; return x + #define RETURNVOID trace_return ("%s","(void)") ; return + #define TRACE0(x) trace_printf0 x + #define TRACE(x) trace_printf x + #else + #define ENTER(fun) + #define RETURN(f,x) return x + #define RETURNVOID return + #define TRACE0(x) + #define TRACE(x) + #endif + #endif + + +#line 1 "rde_critcl/stack.h" + + #ifndef _RDE_DS_STACK_H + #define _RDE_DS_STACK_H 1 + typedef void (*RDE_STACK_CELL_FREE) (void* cell); + typedef struct RDE_STACK_* RDE_STACK; + static const int RDE_STACK_INITIAL_SIZE = 256; + #endif + + +#line 1 "rde_critcl/tc.h" + + #ifndef _RDE_DS_TC_H + #define _RDE_DS_TC_H 1 + typedef struct RDE_TC_* RDE_TC; + #endif + + +#line 1 "rde_critcl/param.h" + + #ifndef _RDE_DS_PARAM_H + #define _RDE_DS_PARAM_H 1 + typedef struct RDE_PARAM_* RDE_PARAM; + typedef struct ERROR_STATE { + int refCount; + long int loc; + RDE_STACK msg; + } ERROR_STATE; + typedef struct NC_STATE { + long int CL; + long int ST; + Tcl_Obj* SV; + ERROR_STATE* ER; + } NC_STATE; + #endif + + +#line 1 "rde_critcl/util.c" + + #ifdef RDE_TRACE + typedef struct F_STACK { + const char* str; + struct F_STACK* down; + } F_STACK; + static F_STACK* top = 0; + static int level = 0; + static void + push (const char* str) + { + F_STACK* new = ALLOC (F_STACK); + new->str = str; + new->down = top; + top = new; + level += 4; + } + static void + pop (void) + { + F_STACK* next = top->down; + level -= 4; + ckfree ((char*)top); + top = next; + } + static void + indent (void) + { + int i; + for (i = 0; i < level; i++) { + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + if (top) { + fwrite(top->str, 1, strlen(top->str), stdout); + fflush (stdout); + } + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + SCOPE void + trace_enter (const char* fun) + { + push (fun); + indent(); + fwrite("ENTER\n", 1, 6, stdout); + fflush (stdout); + } + static char msg [1024*1024]; + SCOPE void + trace_return (const char *pat, ...) + { + int len; + va_list args; + indent(); + fwrite("RETURN = ", 1, 9, stdout); + fflush (stdout); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + pop(); + } + SCOPE void + trace_printf (const char *pat, ...) + { + int len; + va_list args; + indent(); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + SCOPE void + trace_printf0 (const char *pat, ...) + { + int len; + va_list args; + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + #endif + + +#line 1 "rde_critcl/stack.c" + + typedef struct RDE_STACK_ { + long int max; + long int top; + RDE_STACK_CELL_FREE freeCellProc; + void** cell; + } RDE_STACK_; + + SCOPE RDE_STACK + rde_stack_new (RDE_STACK_CELL_FREE freeCellProc) + { + RDE_STACK s = ALLOC (RDE_STACK_); + s->cell = NALLOC (RDE_STACK_INITIAL_SIZE, void*); + s->max = RDE_STACK_INITIAL_SIZE; + s->top = 0; + s->freeCellProc = freeCellProc; + return s; + } + SCOPE void + rde_stack_del (RDE_STACK s) + { + if (s->freeCellProc && s->top) { + long int i; + for (i=0; i < s->top; i++) { + ASSERT_BOUNDS(i,s->max); + s->freeCellProc ( s->cell [i] ); + } + } + ckfree ((char*) s->cell); + ckfree ((char*) s); + } + SCOPE void + rde_stack_push (RDE_STACK s, void* item) + { + if (s->top >= s->max) { + long int new = s->max ? (2 * s->max) : RDE_STACK_INITIAL_SIZE; + void** cell = (void**) ckrealloc ((char*) s->cell, new * sizeof(void*)); + ASSERT (cell,"Memory allocation failure for RDE stack"); + s->max = new; + s->cell = cell; + } + ASSERT_BOUNDS(s->top,s->max); + s->cell [s->top] = item; + s->top ++; + } + SCOPE void* + rde_stack_top (RDE_STACK s) + { + ASSERT_BOUNDS(s->top-1,s->max); + return s->cell [s->top - 1]; + } + SCOPE void + rde_stack_pop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + if (s->freeCellProc) { + while (n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + n --; + } + } else { + s->top -= n; + } + } + SCOPE void + rde_stack_trim (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad trimsize"); + if (s->freeCellProc) { + while (s->top > n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + } + } else { + s->top = n; + } + } + SCOPE void + rde_stack_drop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + s->top -= n; + } + SCOPE void + rde_stack_move (RDE_STACK dst, RDE_STACK src) + { + ASSERT (dst->freeCellProc == src->freeCellProc, "Ownership mismatch"); + + while (src->top > 0) { + src->top --; + ASSERT_BOUNDS(src->top,src->max); + rde_stack_push (dst, src->cell [src->top] ); + } + } + SCOPE void + rde_stack_get (RDE_STACK s, long int* cn, void*** cc) + { + *cn = s->top; + *cc = s->cell; + } + SCOPE long int + rde_stack_size (RDE_STACK s) + { + return s->top; + } + + +#line 1 "rde_critcl/tc.c" + + typedef struct RDE_TC_ { + int max; + int num; + char* str; + RDE_STACK off; + } RDE_TC_; + + SCOPE RDE_TC + rde_tc_new (void) + { + RDE_TC tc = ALLOC (RDE_TC_); + tc->max = RDE_STACK_INITIAL_SIZE; + tc->num = 0; + tc->str = NALLOC (RDE_STACK_INITIAL_SIZE, char); + tc->off = rde_stack_new (NULL); + return tc; + } + SCOPE void + rde_tc_del (RDE_TC tc) + { + rde_stack_del (tc->off); + ckfree (tc->str); + ckfree ((char*) tc); + } + SCOPE long int + rde_tc_size (RDE_TC tc) + { + return rde_stack_size (tc->off); + } + SCOPE void + rde_tc_clear (RDE_TC tc) + { + tc->num = 0; + rde_stack_trim (tc->off, 0); + } + SCOPE char* + rde_tc_append (RDE_TC tc, char* string, long int len) + { + long int base = tc->num; + long int off = tc->num; + char* ch; + int clen; + Tcl_UniChar uni; + if (len < 0) { + len = strlen (string); + } + + if (!len) { + return tc->str + base; + } + + if ((tc->num + len) >= tc->max) { + int new = len + (tc->max ? (2 * tc->max) : RDE_STACK_INITIAL_SIZE); + char* str = ckrealloc (tc->str, new * sizeof(char)); + ASSERT (str,"Memory allocation failure for token character array"); + tc->max = new; + tc->str = str; + } + tc->num += len; + ASSERT_BOUNDS(tc->num,tc->max); + ASSERT_BOUNDS(off,tc->max); + ASSERT_BOUNDS(off+len-1,tc->max); + ASSERT_BOUNDS(off+len-1,tc->num); + memcpy (tc->str + off, string, len); + + ch = string; + while (ch < (string + len)) { + ASSERT_BOUNDS(off,tc->num); + rde_stack_push (tc->off, (void*) off); + clen = Tcl_UtfToUniChar (ch, &uni); + off += clen; + ch += clen; + } + return tc->str + base; + } + SCOPE void + rde_tc_get (RDE_TC tc, int at, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + off = ov [at]; + if ((at+1) == oc) { + end = tc->num; + } else { + end = ov [at+1]; + } + TRACE (("rde_tc_get (RDE_TC %p, @ %d) => %d.[%d ... %d]/%d",tc,at,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + SCOPE void + rde_tc_get_s (RDE_TC tc, int at, int last, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + ASSERT_BOUNDS(last,oc); + off = ov [at]; + if ((last+1) == oc) { + end = tc->num; + } else { + end = ov [last+1]; + } + TRACE (("rde_tc_get_s (RDE_TC %p, @ %d .. %d) => %d.[%d ... %d]/%d",tc,at,last,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + + +#line 1 "rde_critcl/param.c" + + typedef struct RDE_PARAM_ { + Tcl_Channel IN; + Tcl_Obj* readbuf; + char* CC; + long int CC_len; + RDE_TC TC; + long int CL; + RDE_STACK LS; + ERROR_STATE* ER; + RDE_STACK ES; + long int ST; + Tcl_Obj* SV; + Tcl_HashTable NC; + + RDE_STACK ast ; + RDE_STACK mark ; + + long int numstr; + char** string; + + ClientData clientData; + } RDE_PARAM_; + typedef int (*UniCharClass) (int); + typedef enum test_class_id { + tc_alnum, + tc_alpha, + tc_ascii, + tc_control, + tc_ddigit, + tc_digit, + tc_graph, + tc_lower, + tc_printable, + tc_punct, + tc_space, + tc_upper, + tc_wordchar, + tc_xdigit + } test_class_id; + static void ast_node_free (void* n); + static void error_state_free (void* es); + static void error_set (RDE_PARAM p, int s); + static void nc_clear (RDE_PARAM p); + static int UniCharIsAscii (int character); + static int UniCharIsHexDigit (int character); + static int UniCharIsDecDigit (int character); + static void test_class (RDE_PARAM p, UniCharClass class, test_class_id id); + static int er_int_compare (const void* a, const void* b); + #define SV_INIT(p) \ + p->SV = NULL; \ + TRACE (("SV_INIT (%p => %p)", (p), (p)->SV)) + #define SV_SET(p,newsv) \ + if (((p)->SV) != (newsv)) { \ + TRACE (("SV_CLEAR/set (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = (newsv); \ + TRACE (("SV_SET (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_IncrRefCount ((p)->SV); \ + } \ + } + #define SV_CLEAR(p) \ + TRACE (("SV_CLEAR (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = NULL + #define ER_INIT(p) \ + p->ER = NULL; \ + TRACE (("ER_INIT (%p => %p)", (p), (p)->ER)) + #define ER_CLEAR(p) \ + error_state_free ((p)->ER); \ + (p)->ER = NULL + SCOPE RDE_PARAM + rde_param_new (long int nstr, char** strings) + { + RDE_PARAM p; + ENTER ("rde_param_new"); + TRACE (("\tINT %d strings @ %p", nstr, strings)); + p = ALLOC (RDE_PARAM_); + p->numstr = nstr; + p->string = strings; + p->readbuf = Tcl_NewObj (); + Tcl_IncrRefCount (p->readbuf); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_InitHashTable (&p->NC, TCL_ONE_WORD_KEYS); + p->IN = NULL; + p->CL = -1; + p->ST = 0; + ER_INIT (p); + SV_INIT (p); + p->CC = NULL; + p->CC_len = 0; + p->TC = rde_tc_new (); + p->ES = rde_stack_new (error_state_free); + p->LS = rde_stack_new (NULL); + p->ast = rde_stack_new (ast_node_free); + p->mark = rde_stack_new (NULL); + RETURN ("%p", p); + } + SCOPE void + rde_param_del (RDE_PARAM p) + { + ENTER ("rde_param_del"); + TRACE (("RDE_PARAM %p",p)); + ER_CLEAR (p); TRACE (("\ter_clear")); + SV_CLEAR (p); TRACE (("\tsv_clear")); + nc_clear (p); TRACE (("\tnc_clear")); + Tcl_DeleteHashTable (&p->NC); TRACE (("\tnc hashtable delete")); + rde_tc_del (p->TC); TRACE (("\ttc clear")); + rde_stack_del (p->ES); TRACE (("\tes clear")); + rde_stack_del (p->LS); TRACE (("\tls clear")); + rde_stack_del (p->ast); TRACE (("\tast clear")); + rde_stack_del (p->mark); TRACE (("\tmark clear")); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_DecrRefCount (p->readbuf); + ckfree ((char*) p); + RETURNVOID; + } + SCOPE void + rde_param_reset (RDE_PARAM p, Tcl_Channel chan) + { + ENTER ("rde_param_reset"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("Tcl_Channel %p",chan)); + p->IN = chan; + p->CL = -1; + p->ST = 0; + p->CC = NULL; + p->CC_len = 0; + ER_CLEAR (p); + SV_CLEAR (p); + nc_clear (p); + rde_tc_clear (p->TC); + rde_stack_trim (p->ES, 0); + rde_stack_trim (p->LS, 0); + rde_stack_trim (p->ast, 0); + rde_stack_trim (p->mark, 0); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + RETURNVOID; + } + SCOPE void + rde_param_update_strings (RDE_PARAM p, long int nstr, char** strings) + { + ENTER ("rde_param_update_strings"); + TRACE (("RDE_PARAM %p", p)); + TRACE (("INT %d strings", nstr)); + p->numstr = nstr; + p->string = strings; + RETURNVOID; + } + SCOPE void + rde_param_data (RDE_PARAM p, char* buf, long int len) + { + (void) rde_tc_append (p->TC, buf, len); + } + SCOPE void + rde_param_clientdata (RDE_PARAM p, ClientData clientData) + { + p->clientData = clientData; + } + static void + nc_clear (RDE_PARAM p) + { + Tcl_HashSearch hs; + Tcl_HashEntry* he; + Tcl_HashTable* tablePtr; + for(he = Tcl_FirstHashEntry(&p->NC, &hs); + he != NULL; + he = Tcl_FirstHashEntry(&p->NC, &hs)) { + Tcl_HashSearch hsc; + Tcl_HashEntry* hec; + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (he); + for(hec = Tcl_FirstHashEntry(tablePtr, &hsc); + hec != NULL; + hec = Tcl_NextHashEntry(&hsc)) { + NC_STATE* scs = Tcl_GetHashValue (hec); + error_state_free (scs->ER); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + ckfree ((char*) scs); + } + Tcl_DeleteHashTable (tablePtr); + ckfree ((char*) tablePtr); + Tcl_DeleteHashEntry (he); + } + } + SCOPE ClientData + rde_param_query_clientdata (RDE_PARAM p) + { + return p->clientData; + } + SCOPE void + rde_param_query_amark (RDE_PARAM p, long int* mc, long int** mv) + { + rde_stack_get (p->mark, mc, (void***) mv); + } + SCOPE void + rde_param_query_ast (RDE_PARAM p, long int* ac, Tcl_Obj*** av) + { + rde_stack_get (p->ast, ac, (void***) av); + } + SCOPE const char* + rde_param_query_in (RDE_PARAM p) + { + return p->IN + ? Tcl_GetChannelName (p->IN) + : ""; + } + SCOPE const char* + rde_param_query_cc (RDE_PARAM p, long int* len) + { + *len = p->CC_len; + return p->CC; + } + SCOPE int + rde_param_query_cl (RDE_PARAM p) + { + return p->CL; + } + SCOPE const ERROR_STATE* + rde_param_query_er (RDE_PARAM p) + { + return p->ER; + } + SCOPE Tcl_Obj* + rde_param_query_er_tcl (RDE_PARAM p, const ERROR_STATE* er) + { + Tcl_Obj* res; + if (!er) { + + res = Tcl_NewStringObj ("", 0); + } else { + Tcl_Obj* ov [2]; + Tcl_Obj** mov; + long int mc, i, j; + long int* mv; + int lastid; + const char* msg; + rde_stack_get (er->msg, &mc, (void***) &mv); + + qsort (mv, mc, sizeof (long int), er_int_compare); + + mov = NALLOC (mc, Tcl_Obj*); + lastid = -1; + for (i=0, j=0; i < mc; i++) { + ASSERT_BOUNDS (i,mc); + if (mv [i] == lastid) continue; + lastid = mv [i]; + ASSERT_BOUNDS(mv[i],p->numstr); + msg = p->string [mv[i]]; + ASSERT_BOUNDS (j,mc); + mov [j] = Tcl_NewStringObj (msg, -1); + j++; + } + + ov [0] = Tcl_NewIntObj (er->loc); + ov [1] = Tcl_NewListObj (j, mov); + res = Tcl_NewListObj (2, ov); + ckfree ((char*) mov); + } + return res; + } + SCOPE void + rde_param_query_es (RDE_PARAM p, long int* ec, ERROR_STATE*** ev) + { + rde_stack_get (p->ES, ec, (void***) ev); + } + SCOPE void + rde_param_query_ls (RDE_PARAM p, long int* lc, void*** lv) + { + rde_stack_get (p->LS, lc, lv); + } + SCOPE long int + rde_param_query_lstop (RDE_PARAM p) + { + (long int) rde_stack_top (p->LS); + } + SCOPE Tcl_HashTable* + rde_param_query_nc (RDE_PARAM p) + { + return &p->NC; + } + SCOPE int + rde_param_query_st (RDE_PARAM p) + { + return p->ST; + } + SCOPE Tcl_Obj* + rde_param_query_sv (RDE_PARAM p) + { + TRACE (("SV_QUERY %p => (%p)", (p), (p)->SV)); \ + return p->SV; + } + SCOPE long int + rde_param_query_tc_size (RDE_PARAM p) + { + return rde_tc_size (p->TC); + } + SCOPE void + rde_param_query_tc_get_s (RDE_PARAM p, long int at, long int last, char** ch, long int* len) + { + rde_tc_get_s (p->TC, at, last, ch, len); + } + SCOPE const char* + rde_param_query_string (RDE_PARAM p, long int id) + { + TRACE (("rde_param_query_string (RDE_PARAM %p, %d/%d)", p, id, p->numstr)); + ASSERT_BOUNDS(id,p->numstr); + return p->string [id]; + } + SCOPE void + rde_param_i_ast_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->mark, 1); + } + SCOPE void + rde_param_i_ast_pop_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_pop_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_push (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_ast_value_push (RDE_PARAM p) + { + ENTER ("rde_param_i_ast_value_push"); + TRACE (("RDE_PARAM %p",p)); + ASSERT(p->SV,"Unable to push undefined semantic value"); + TRACE (("rde_param_i_ast_value_push %p => (%p)", p, p->SV)); + TRACE (("SV = (%p rc%d '%s')", p->SV, p->SV->refCount, Tcl_GetString (p->SV))); + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + RETURNVOID; + } + static void + ast_node_free (void* n) + { + Tcl_DecrRefCount ((Tcl_Obj*) n); + } + SCOPE void + rde_param_i_error_clear (RDE_PARAM p) + { + ER_CLEAR (p); + } + SCOPE void + rde_param_i_error_nonterminal (RDE_PARAM p, int s) + { + + return; + long int pos; + if (!p->ER) return; + pos = 1 + (long int) rde_stack_top (p->LS); + if (p->ER->loc != pos) return; + error_set (p, s); + p->ER->loc = pos; + } + SCOPE void + rde_param_i_error_pop_merge (RDE_PARAM p) + { + ERROR_STATE* top = (ERROR_STATE*) rde_stack_top (p->ES); + + if (top == p->ER) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!top) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!p->ER) { + rde_stack_drop (p->ES, 1); + p->ER = top; + + return; + } + + if (top->loc < p->ER->loc) { + rde_stack_pop (p->ES, 1); + return; + } + + if (top->loc > p->ER->loc) { + rde_stack_drop (p->ES, 1); + error_state_free (p->ER); + p->ER = top; + + return; + } + + rde_stack_move (p->ER->msg, top->msg); + rde_stack_pop (p->ES, 1); + } + SCOPE void + rde_param_i_error_push (RDE_PARAM p) + { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + static void + error_set (RDE_PARAM p, int s) + { + error_state_free (p->ER); + p->ER = ALLOC (ERROR_STATE); + p->ER->refCount = 1; + p->ER->loc = p->CL; + p->ER->msg = rde_stack_new (NULL); + ASSERT_BOUNDS(s,p->numstr); + rde_stack_push (p->ER->msg, (void*) s); + } + static void + error_state_free (void* esx) + { + ERROR_STATE* es = esx; + if (!es) return; + es->refCount --; + if (es->refCount > 0) return; + rde_stack_del (es->msg); + ckfree ((char*) es); + } + SCOPE void + rde_param_i_loc_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_pop_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_push (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + } + SCOPE void + rde_param_i_loc_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + } + SCOPE void + rde_param_i_input_next (RDE_PARAM p, int m) + { + int leni; + char* ch; + ASSERT_BOUNDS(m,p->numstr); + p->CL ++; + if (p->CL < rde_tc_size (p->TC)) { + + rde_tc_get (p->TC, p->CL, &p->CC, &p->CC_len); + ASSERT_BOUNDS (p->CC_len, TCL_UTF_MAX); + p->ST = 1; + ER_CLEAR (p); + return; + } + if (!p->IN || + Tcl_Eof (p->IN) || + (Tcl_ReadChars (p->IN, p->readbuf, 1, 0) <= 0)) { + + p->ST = 0; + error_set (p, m); + return; + } + + ch = Tcl_GetStringFromObj (p->readbuf, &leni); + ASSERT_BOUNDS (leni, TCL_UTF_MAX); + p->CC = rde_tc_append (p->TC, ch, leni); + p->CC_len = leni; + p->ST = 1; + ER_CLEAR (p); + } + SCOPE void + rde_param_i_status_fail (RDE_PARAM p) + { + p->ST = 0; + } + SCOPE void + rde_param_i_status_ok (RDE_PARAM p) + { + p->ST = 1; + } + SCOPE void + rde_param_i_status_negate (RDE_PARAM p) + { + p->ST = !p->ST; + } + SCOPE int + rde_param_i_symbol_restore (RDE_PARAM p, int s) + { + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + + hPtr = Tcl_FindHashEntry (&p->NC, (char*) p->CL); + if (!hPtr) { return 0; } + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + hPtr = Tcl_FindHashEntry (tablePtr, (char*) s); + if (!hPtr) { return 0; } + + scs = Tcl_GetHashValue (hPtr); + p->CL = scs->CL; + p->ST = scs->ST; + error_state_free (p->ER); + p->ER = scs->ER; + if (p->ER) { p->ER->refCount ++; } + TRACE (("SV_RESTORE (%p) '%s'",scs->SV, scs->SV ? Tcl_GetString (scs->SV):"")); + SV_SET (p, scs->SV); + return 1; + } + SCOPE void + rde_param_i_symbol_save (RDE_PARAM p, int s) + { + long int at = (long int) rde_stack_top (p->LS); + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + int isnew; + ENTER ("rde_param_i_symbol_save"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("INT %d",s)); + + hPtr = Tcl_CreateHashEntry (&p->NC, (char*) at, &isnew); + if (isnew) { + tablePtr = ALLOC (Tcl_HashTable); + Tcl_InitHashTable (tablePtr, TCL_ONE_WORD_KEYS); + Tcl_SetHashValue (hPtr, tablePtr); + } else { + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + } + hPtr = Tcl_CreateHashEntry (tablePtr, (char*) s, &isnew); + if (isnew) { + + scs = ALLOC (NC_STATE); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "")); + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + Tcl_SetHashValue (hPtr, scs); + } else { + + scs = (NC_STATE*) Tcl_GetHashValue (hPtr); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE/over (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "" )); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + error_state_free (scs->ER); + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + } + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_test_alnum (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlnum, tc_alnum); + } + SCOPE void + rde_param_i_test_alpha (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlpha, tc_alpha); + } + SCOPE void + rde_param_i_test_ascii (RDE_PARAM p) + { + test_class (p, UniCharIsAscii, tc_ascii); + } + SCOPE void + rde_param_i_test_control (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsControl, tc_control); + } + SCOPE void + rde_param_i_test_char (RDE_PARAM p, const char* c, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = Tcl_UtfNcmp (p->CC, c, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_ddigit (RDE_PARAM p) + { + test_class (p, UniCharIsDecDigit, tc_ddigit); + } + SCOPE void + rde_param_i_test_digit (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsDigit, tc_digit); + } + SCOPE void + rde_param_i_test_graph (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsGraph, tc_graph); + } + SCOPE void + rde_param_i_test_lower (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsLower, tc_lower); + } + SCOPE void + rde_param_i_test_print (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPrint, tc_printable); + } + SCOPE void + rde_param_i_test_punct (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPunct, tc_punct); + } + SCOPE void + rde_param_i_test_range (RDE_PARAM p, char* s, char* e, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = + (Tcl_UtfNcmp (s, p->CC, 1) <= 0) && + (Tcl_UtfNcmp (p->CC, e, 1) <= 0); + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_space (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsSpace, tc_space); + } + SCOPE void + rde_param_i_test_upper (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsUpper, tc_upper); + } + SCOPE void + rde_param_i_test_wordchar (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsWordChar, tc_wordchar); + } + SCOPE void + rde_param_i_test_xdigit (RDE_PARAM p) + { + test_class (p, UniCharIsHexDigit, tc_xdigit); + } + static void + test_class (RDE_PARAM p, UniCharClass class, test_class_id id) + { + Tcl_UniChar ch; + Tcl_UtfToUniChar(p->CC, &ch); + ASSERT_BOUNDS(id,p->numstr); + p->ST = !!class (ch); + + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, id); + p->CL --; + } + } + static int + UniCharIsAscii (int character) + { + return (character >= 0) && (character < 0x80); + } + static int + UniCharIsHexDigit (int character) + { + return (character >= 0) && (character < 0x80) && isxdigit(character); + } + static int + UniCharIsDecDigit (int character) + { + return (character >= 0) && (character < 0x80) && isdigit(character); + } + SCOPE void + rde_param_i_value_clear (RDE_PARAM p) + { + SV_CLEAR (p); + } + SCOPE void + rde_param_i_value_leaf (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + Tcl_Obj* ov [3]; + long int pos = 1 + (long int) rde_stack_top (p->LS); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + newsv = Tcl_NewListObj (3, ov); + TRACE (("rde_param_i_value_leaf => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + } + SCOPE void + rde_param_i_value_reduce (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + int oc, i, j; + Tcl_Obj** ov; + long int ac; + Tcl_Obj** av; + long int pos = 1 + (long int) rde_stack_top (p->LS); + long int mark = (long int) rde_stack_top (p->mark); + long int asize = rde_stack_size (p->ast); + long int new = asize - mark; + ASSERT (new >= 0, "Bad number of elements to reduce"); + ov = NALLOC (3+new, Tcl_Obj*); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + rde_stack_get (p->ast, &ac, (void***) &av); + for (i = 3, j = mark; j < asize; i++, j++) { + ASSERT_BOUNDS (i, 3+new); + ASSERT_BOUNDS (j, ac); + ov [i] = av [j]; + } + ASSERT (i == 3+new, "Reduction result incomplete"); + newsv = Tcl_NewListObj (3+new, ov); + TRACE (("rde_param_i_value_reduce => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + ckfree ((char*) ov); + } + static int + er_int_compare (const void* a, const void* b) + { + long int ai = *((long int*) a); + long int bi = *((long int*) b); + if (ai < bi) { return -1; } + if (ai > bi) { return 1; } + return 0; + } + SCOPE int + rde_param_i_symbol_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE void + rde_param_i_symbol_done_d_reduce (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_reduce (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_d_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_symbol_done_d_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_next_char (RDE_PARAM p, char* c, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_char (p, c, m); + } + SCOPE void + rde_param_i_next_range (RDE_PARAM p, char* s, char* e, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_range (p, s, e, m); + } + SCOPE void + rde_param_i_next_alnum (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alnum (p); + } + SCOPE void + rde_param_i_next_alpha (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alpha (p); + } + SCOPE void + rde_param_i_next_ascii (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ascii (p); + } + SCOPE void + rde_param_i_next_control (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_control (p); + } + SCOPE void + rde_param_i_next_ddigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ddigit (p); + } + SCOPE void + rde_param_i_next_digit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_digit (p); + } + SCOPE void + rde_param_i_next_graph (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_graph (p); + } + SCOPE void + rde_param_i_next_lower (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_lower (p); + } + SCOPE void + rde_param_i_next_print (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_print (p); + } + SCOPE void + rde_param_i_next_punct (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_punct (p); + } + SCOPE void + rde_param_i_next_space (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_space (p); + } + SCOPE void + rde_param_i_next_upper (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_upper (p); + } + SCOPE void + rde_param_i_next_wordchar (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_wordchar (p); + } + SCOPE void + rde_param_i_next_xdigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_xdigit (p); + } + SCOPE void + rde_param_i_notahead_start_d (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_notahead_exit_d (RDE_PARAM p) + { + if (p->ST) { + rde_param_i_ast_pop_rewind (p); + } else { + rde_stack_pop (p->mark, 1); + } + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_notahead_exit (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_state_push_2 (RDE_PARAM p) + { + + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + SCOPE void + rde_param_i_state_push_void (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_push_value (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_merge_ok (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } + SCOPE int + rde_param_i_kleene_close (RDE_PARAM p) + { + int stop = !p->ST; + rde_param_i_error_pop_merge (p); + if (stop) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_kleene_abort (RDE_PARAM p) + { + int stop = !p->ST; + if (stop) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_seq_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_bra_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE void + rde_param_i_next_str (RDE_PARAM p, const char* str, int m) + { + int at = p->CL; + + while (*str) { + rde_param_i_input_next (p, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + rde_param_i_test_char (p, str, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + str = Tcl_UtfNext (str); + } + } + SCOPE void + rde_param_i_next_class (RDE_PARAM p, const char* class, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + while (*class) { + p->ST = Tcl_UtfNcmp (p->CC, class, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + return; + } + class = Tcl_UtfNext (class); + } + error_set (p, m); + p->CL --; + } + + + /* + * Declaring the parse functions + */ + + static void kleene_2 (RDE_PARAM p); + + /* + * Precomputed table of strings (symbols, error messages, etc.). + */ + + static char const* p_string [15] = { + /* 0 = */ "alnum", + /* 1 = */ "alpha", + /* 2 = */ "ascii", + /* 3 = */ "control", + /* 4 = */ "ddigit", + /* 5 = */ "digit", + /* 6 = */ "graph", + /* 7 = */ "lower", + /* 8 = */ "print", + /* 9 = */ "punct", + /* 10 = */ "space", + /* 11 = */ "upper", + /* 12 = */ "wordchar", + /* 13 = */ "xdigit", + /* 14 = */ "t a" + }; + + /* + * Grammar Start Expression + */ + + static void MAIN (RDE_PARAM p) { + kleene_2 (p); + return; + } + + static void kleene_2 (RDE_PARAM p) { + /* + * * + * 'a' + */ + + while (1) { + rde_param_i_state_push_2 (p); + rde_param_i_next_char (p, "a", 14); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + /* -*- c -*- */ + + typedef struct PARSERg { + long int counter; + char buf [50]; + } PARSERg; + + static void + PARSERgRelease (ClientData cd, Tcl_Interp* interp) + { + ckfree((char*) cd); + } + + static const char* + PARSERnewName (Tcl_Interp* interp) + { +#define KEY "tcllib/parser/PACKAGE/TEA" + + Tcl_InterpDeleteProc* proc = PARSERgRelease; + PARSERg* parserg; + + parserg = Tcl_GetAssocData (interp, KEY, &proc); + if (parserg == NULL) { + parserg = (PARSERg*) ckalloc (sizeof (PARSERg)); + parserg->counter = 0; + + Tcl_SetAssocData (interp, KEY, proc, + (ClientData) parserg); + } + + parserg->counter ++; + sprintf (parserg->buf, "PARSER%d", parserg->counter); + return parserg->buf; +#undef KEY + } + + static void + PARSERdeleteCmd (ClientData clientData) + { + /* + * Release the whole PARSER + * (Low-level engine only actually). + */ + rde_param_del ((RDE_PARAM) clientData); + } + + + /* * ** *** ***** ******** ************* + ** Functions implementing the object methods, and helper. + */ + + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp); + + static int parser_PARSE (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + int mode; + Tcl_Channel chan; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "chan"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, + Tcl_GetString (objv[2]), + &mode); + + if (!chan) { + return TCL_ERROR; + } + + rde_param_reset (p, chan); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + static int parser_PARSET (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + char* buf; + int len; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "text"); + return TCL_ERROR; + } + + buf = Tcl_GetStringFromObj (objv[2], &len); + + rde_param_reset (p, NULL); + rde_param_data (p, buf, len); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + /* See also rde_critcl/m.c, param_COMPLETE() */ + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp) + { + if (rde_param_query_st (p)) { + long int ac; + Tcl_Obj** av; + + rde_param_query_ast (p, &ac, &av); + + if (ac > 1) { + Tcl_Obj** lv = NALLOC (3+ac, Tcl_Obj*); + + memcpy(lv + 3, av, ac * sizeof (Tcl_Obj*)); + lv [0] = Tcl_NewObj (); + lv [1] = Tcl_NewIntObj (1 + rde_param_query_lstop (p)); + lv [2] = Tcl_NewIntObj (rde_param_query_cl (p)); + + Tcl_SetObjResult (interp, Tcl_NewListObj (3, lv)); + ckfree ((char*) lv); + + } else if (ac == 0) { + /* + * Match, but no AST. This is possible if the grammar + * consists of only the start expression. + */ + Tcl_SetObjResult (interp, Tcl_NewStringObj ("",-1)); + } else { + Tcl_SetObjResult (interp, av [0]); + } + + return TCL_OK; + } else { + Tcl_Obj* xv [1]; + const ERROR_STATE* er = rde_param_query_er (p); + Tcl_Obj* res = rde_param_query_er_tcl (p, er); + /* res = list (location, list(msg)) */ + + /* Stick the exception type-tag before the existing elements */ + xv [0] = Tcl_NewStringObj ("pt::rde",-1); + Tcl_ListObjReplace(interp, res, 0, 0, 1, xv); + + Tcl_SetErrorCode (interp, "PT", "RDE", "SYNTAX", NULL); + Tcl_SetObjResult (interp, res); + return TCL_ERROR; + } + } + + + /* * ** *** ***** ******** ************* + ** Object command, method dispatch. + */ + static int parser_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + RDE_PARAM p = (RDE_PARAM) cd; + int m, res; + + static CONST char* methods [] = { + "destroy", "parse", "parset", NULL + }; + enum methods { + M_DESTROY, M_PARSE, M_PARSET + }; + + if (objc < 2) { + Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option", + 0, &m) != TCL_OK) { + return TCL_ERROR; + } + + /* Dispatch to methods. They check the #args in + * detail before performing the requested + * functionality + */ + + switch (m) { + case M_DESTROY: + if (objc != 2) { + Tcl_WrongNumArgs (interp, 2, objv, NULL); + return TCL_ERROR; + } + + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) rde_param_query_clientdata (p)); + return TCL_OK; + + case M_PARSE: res = parser_PARSE (p, interp, objc, objv); break; + case M_PARSET: res = parser_PARSET (p, interp, objc, objv); break; + default: + /* Not coming to this place */ + ASSERT (0,"Reached unreachable location"); + } + + return res; + } + + /** * ** *** ***** ******** ************* + * Class command, i.e. object construction. + */ + static int ParserClassCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const*objv) { + /* + * Syntax: No arguments beyond the name + */ + + RDE_PARAM parser; + CONST char* name; + Tcl_Obj* fqn; + Tcl_CmdInfo ci; + Tcl_Command c; + +#define USAGE "?name?" + + if ((objc != 2) && (objc != 1)) { + Tcl_WrongNumArgs (interp, 1, objv, USAGE); + return TCL_ERROR; + } + + if (objc < 2) { + name = PARSERnewName (interp); + } else { + name = Tcl_GetString (objv [1]); + } + + if (!Tcl_StringMatch (name, "::*")) { + /* Relative name. Prefix with current namespace */ + + Tcl_Eval (interp, "namespace current"); + fqn = Tcl_GetObjResult (interp); + fqn = Tcl_DuplicateObj (fqn); + Tcl_IncrRefCount (fqn); + + if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { + Tcl_AppendToObj (fqn, "::", -1); + } + Tcl_AppendToObj (fqn, name, -1); + } else { + fqn = Tcl_NewStringObj (name, -1); + Tcl_IncrRefCount (fqn); + } + Tcl_ResetResult (interp); + + if (Tcl_GetCommandInfo (interp, + Tcl_GetString (fqn), + &ci)) { + Tcl_Obj* err; + + err = Tcl_NewObj (); + Tcl_AppendToObj (err, "command \"", -1); + Tcl_AppendObjToObj (err, fqn); + Tcl_AppendToObj (err, "\" already exists", -1); + + Tcl_DecrRefCount (fqn); + Tcl_SetObjResult (interp, err); + return TCL_ERROR; + } + + parser = rde_param_new (sizeof(p_string)/sizeof(char*), (char**) p_string); + c = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), + parser_objcmd, (ClientData) parser, + PARSERdeleteCmd); + rde_param_clientdata (parser, (ClientData) c); + Tcl_SetObjResult (interp, fqn); + Tcl_DecrRefCount (fqn); + return TCL_OK; + } + +int Package_Init(Tcl_Interp* interp) { + if (interp == 0) return TCL_ERROR; + + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + + if (Tcl_CreateObjCommand(interp, "PARSER", ParserClassCmd , NULL, NULL) == NULL) { + Tcl_SetResult(interp, "Can't create constructor", NULL); + return TCL_ERROR; + } + + + Tcl_PkgProvide(interp, "PACKAGE", "0.1"); + + return TCL_OK; +} ADDED modules/pt/tests/data/ok/peg_cparam-tea/8_pkleene Index: modules/pt/tests/data/ok/peg_cparam-tea/8_pkleene ================================================================== --- /dev/null +++ modules/pt/tests/data/ok/peg_cparam-tea/8_pkleene @@ -0,0 +1,2000 @@ +/************************************************************ +** +** TEA-based C/PARAM implementation of the parsing +** expression grammar +** +** TEMPLATE +** +** Generated from file TEST +** for user unknown +** +* * ** *** ***** ******** ************* *********************/ + #include + #include + #include + #include + #define SCOPE static + +#line 1 "rde_critcl/util.h" + + #ifndef _RDE_UTIL_H + #define _RDE_UTIL_H 1 + #ifndef SCOPE + #define SCOPE + #endif + #define ALLOC(type) (type *) ckalloc (sizeof (type)) + #define NALLOC(n,type) (type *) ckalloc ((n) * sizeof (type)) + #undef RDE_DEBUG + #define RDE_DEBUG 1 + #undef RDE_TRACE + #ifdef RDE_DEBUG + #define STOPAFTER(x) { static int count = (x); count --; if (!count) { Tcl_Panic ("stop"); } } + #define XSTR(x) #x + #define STR(x) XSTR(x) + #define RANGEOK(i,n) ((0 <= (i)) && (i < (n))) + #define ASSERT(x,msg) if (!(x)) { Tcl_Panic (msg " (" #x "), in file " __FILE__ " @line " STR(__LINE__));} + #define ASSERT_BOUNDS(i,n) ASSERT (RANGEOK(i,n),"array index out of bounds: " STR(i) " >= " STR(n)) + #else + #define STOPAFTER(x) + #define ASSERT(x,msg) + #define ASSERT_BOUNDS(i,n) + #endif + #ifdef RDE_TRACE + SCOPE void trace_enter (const char* fun); + SCOPE void trace_return (const char *pat, ...); + SCOPE void trace_printf (const char *pat, ...); + #define ENTER(fun) trace_enter (fun) + #define RETURN(format,x) trace_return (format,x) ; return x + #define RETURNVOID trace_return ("%s","(void)") ; return + #define TRACE0(x) trace_printf0 x + #define TRACE(x) trace_printf x + #else + #define ENTER(fun) + #define RETURN(f,x) return x + #define RETURNVOID return + #define TRACE0(x) + #define TRACE(x) + #endif + #endif + + +#line 1 "rde_critcl/stack.h" + + #ifndef _RDE_DS_STACK_H + #define _RDE_DS_STACK_H 1 + typedef void (*RDE_STACK_CELL_FREE) (void* cell); + typedef struct RDE_STACK_* RDE_STACK; + static const int RDE_STACK_INITIAL_SIZE = 256; + #endif + + +#line 1 "rde_critcl/tc.h" + + #ifndef _RDE_DS_TC_H + #define _RDE_DS_TC_H 1 + typedef struct RDE_TC_* RDE_TC; + #endif + + +#line 1 "rde_critcl/param.h" + + #ifndef _RDE_DS_PARAM_H + #define _RDE_DS_PARAM_H 1 + typedef struct RDE_PARAM_* RDE_PARAM; + typedef struct ERROR_STATE { + int refCount; + long int loc; + RDE_STACK msg; + } ERROR_STATE; + typedef struct NC_STATE { + long int CL; + long int ST; + Tcl_Obj* SV; + ERROR_STATE* ER; + } NC_STATE; + #endif + + +#line 1 "rde_critcl/util.c" + + #ifdef RDE_TRACE + typedef struct F_STACK { + const char* str; + struct F_STACK* down; + } F_STACK; + static F_STACK* top = 0; + static int level = 0; + static void + push (const char* str) + { + F_STACK* new = ALLOC (F_STACK); + new->str = str; + new->down = top; + top = new; + level += 4; + } + static void + pop (void) + { + F_STACK* next = top->down; + level -= 4; + ckfree ((char*)top); + top = next; + } + static void + indent (void) + { + int i; + for (i = 0; i < level; i++) { + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + if (top) { + fwrite(top->str, 1, strlen(top->str), stdout); + fflush (stdout); + } + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + SCOPE void + trace_enter (const char* fun) + { + push (fun); + indent(); + fwrite("ENTER\n", 1, 6, stdout); + fflush (stdout); + } + static char msg [1024*1024]; + SCOPE void + trace_return (const char *pat, ...) + { + int len; + va_list args; + indent(); + fwrite("RETURN = ", 1, 9, stdout); + fflush (stdout); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + pop(); + } + SCOPE void + trace_printf (const char *pat, ...) + { + int len; + va_list args; + indent(); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + SCOPE void + trace_printf0 (const char *pat, ...) + { + int len; + va_list args; + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + #endif + + +#line 1 "rde_critcl/stack.c" + + typedef struct RDE_STACK_ { + long int max; + long int top; + RDE_STACK_CELL_FREE freeCellProc; + void** cell; + } RDE_STACK_; + + SCOPE RDE_STACK + rde_stack_new (RDE_STACK_CELL_FREE freeCellProc) + { + RDE_STACK s = ALLOC (RDE_STACK_); + s->cell = NALLOC (RDE_STACK_INITIAL_SIZE, void*); + s->max = RDE_STACK_INITIAL_SIZE; + s->top = 0; + s->freeCellProc = freeCellProc; + return s; + } + SCOPE void + rde_stack_del (RDE_STACK s) + { + if (s->freeCellProc && s->top) { + long int i; + for (i=0; i < s->top; i++) { + ASSERT_BOUNDS(i,s->max); + s->freeCellProc ( s->cell [i] ); + } + } + ckfree ((char*) s->cell); + ckfree ((char*) s); + } + SCOPE void + rde_stack_push (RDE_STACK s, void* item) + { + if (s->top >= s->max) { + long int new = s->max ? (2 * s->max) : RDE_STACK_INITIAL_SIZE; + void** cell = (void**) ckrealloc ((char*) s->cell, new * sizeof(void*)); + ASSERT (cell,"Memory allocation failure for RDE stack"); + s->max = new; + s->cell = cell; + } + ASSERT_BOUNDS(s->top,s->max); + s->cell [s->top] = item; + s->top ++; + } + SCOPE void* + rde_stack_top (RDE_STACK s) + { + ASSERT_BOUNDS(s->top-1,s->max); + return s->cell [s->top - 1]; + } + SCOPE void + rde_stack_pop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + if (s->freeCellProc) { + while (n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + n --; + } + } else { + s->top -= n; + } + } + SCOPE void + rde_stack_trim (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad trimsize"); + if (s->freeCellProc) { + while (s->top > n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + } + } else { + s->top = n; + } + } + SCOPE void + rde_stack_drop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + s->top -= n; + } + SCOPE void + rde_stack_move (RDE_STACK dst, RDE_STACK src) + { + ASSERT (dst->freeCellProc == src->freeCellProc, "Ownership mismatch"); + + while (src->top > 0) { + src->top --; + ASSERT_BOUNDS(src->top,src->max); + rde_stack_push (dst, src->cell [src->top] ); + } + } + SCOPE void + rde_stack_get (RDE_STACK s, long int* cn, void*** cc) + { + *cn = s->top; + *cc = s->cell; + } + SCOPE long int + rde_stack_size (RDE_STACK s) + { + return s->top; + } + + +#line 1 "rde_critcl/tc.c" + + typedef struct RDE_TC_ { + int max; + int num; + char* str; + RDE_STACK off; + } RDE_TC_; + + SCOPE RDE_TC + rde_tc_new (void) + { + RDE_TC tc = ALLOC (RDE_TC_); + tc->max = RDE_STACK_INITIAL_SIZE; + tc->num = 0; + tc->str = NALLOC (RDE_STACK_INITIAL_SIZE, char); + tc->off = rde_stack_new (NULL); + return tc; + } + SCOPE void + rde_tc_del (RDE_TC tc) + { + rde_stack_del (tc->off); + ckfree (tc->str); + ckfree ((char*) tc); + } + SCOPE long int + rde_tc_size (RDE_TC tc) + { + return rde_stack_size (tc->off); + } + SCOPE void + rde_tc_clear (RDE_TC tc) + { + tc->num = 0; + rde_stack_trim (tc->off, 0); + } + SCOPE char* + rde_tc_append (RDE_TC tc, char* string, long int len) + { + long int base = tc->num; + long int off = tc->num; + char* ch; + int clen; + Tcl_UniChar uni; + if (len < 0) { + len = strlen (string); + } + + if (!len) { + return tc->str + base; + } + + if ((tc->num + len) >= tc->max) { + int new = len + (tc->max ? (2 * tc->max) : RDE_STACK_INITIAL_SIZE); + char* str = ckrealloc (tc->str, new * sizeof(char)); + ASSERT (str,"Memory allocation failure for token character array"); + tc->max = new; + tc->str = str; + } + tc->num += len; + ASSERT_BOUNDS(tc->num,tc->max); + ASSERT_BOUNDS(off,tc->max); + ASSERT_BOUNDS(off+len-1,tc->max); + ASSERT_BOUNDS(off+len-1,tc->num); + memcpy (tc->str + off, string, len); + + ch = string; + while (ch < (string + len)) { + ASSERT_BOUNDS(off,tc->num); + rde_stack_push (tc->off, (void*) off); + clen = Tcl_UtfToUniChar (ch, &uni); + off += clen; + ch += clen; + } + return tc->str + base; + } + SCOPE void + rde_tc_get (RDE_TC tc, int at, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + off = ov [at]; + if ((at+1) == oc) { + end = tc->num; + } else { + end = ov [at+1]; + } + TRACE (("rde_tc_get (RDE_TC %p, @ %d) => %d.[%d ... %d]/%d",tc,at,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + SCOPE void + rde_tc_get_s (RDE_TC tc, int at, int last, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + ASSERT_BOUNDS(last,oc); + off = ov [at]; + if ((last+1) == oc) { + end = tc->num; + } else { + end = ov [last+1]; + } + TRACE (("rde_tc_get_s (RDE_TC %p, @ %d .. %d) => %d.[%d ... %d]/%d",tc,at,last,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + + +#line 1 "rde_critcl/param.c" + + typedef struct RDE_PARAM_ { + Tcl_Channel IN; + Tcl_Obj* readbuf; + char* CC; + long int CC_len; + RDE_TC TC; + long int CL; + RDE_STACK LS; + ERROR_STATE* ER; + RDE_STACK ES; + long int ST; + Tcl_Obj* SV; + Tcl_HashTable NC; + + RDE_STACK ast ; + RDE_STACK mark ; + + long int numstr; + char** string; + + ClientData clientData; + } RDE_PARAM_; + typedef int (*UniCharClass) (int); + typedef enum test_class_id { + tc_alnum, + tc_alpha, + tc_ascii, + tc_control, + tc_ddigit, + tc_digit, + tc_graph, + tc_lower, + tc_printable, + tc_punct, + tc_space, + tc_upper, + tc_wordchar, + tc_xdigit + } test_class_id; + static void ast_node_free (void* n); + static void error_state_free (void* es); + static void error_set (RDE_PARAM p, int s); + static void nc_clear (RDE_PARAM p); + static int UniCharIsAscii (int character); + static int UniCharIsHexDigit (int character); + static int UniCharIsDecDigit (int character); + static void test_class (RDE_PARAM p, UniCharClass class, test_class_id id); + static int er_int_compare (const void* a, const void* b); + #define SV_INIT(p) \ + p->SV = NULL; \ + TRACE (("SV_INIT (%p => %p)", (p), (p)->SV)) + #define SV_SET(p,newsv) \ + if (((p)->SV) != (newsv)) { \ + TRACE (("SV_CLEAR/set (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = (newsv); \ + TRACE (("SV_SET (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_IncrRefCount ((p)->SV); \ + } \ + } + #define SV_CLEAR(p) \ + TRACE (("SV_CLEAR (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = NULL + #define ER_INIT(p) \ + p->ER = NULL; \ + TRACE (("ER_INIT (%p => %p)", (p), (p)->ER)) + #define ER_CLEAR(p) \ + error_state_free ((p)->ER); \ + (p)->ER = NULL + SCOPE RDE_PARAM + rde_param_new (long int nstr, char** strings) + { + RDE_PARAM p; + ENTER ("rde_param_new"); + TRACE (("\tINT %d strings @ %p", nstr, strings)); + p = ALLOC (RDE_PARAM_); + p->numstr = nstr; + p->string = strings; + p->readbuf = Tcl_NewObj (); + Tcl_IncrRefCount (p->readbuf); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_InitHashTable (&p->NC, TCL_ONE_WORD_KEYS); + p->IN = NULL; + p->CL = -1; + p->ST = 0; + ER_INIT (p); + SV_INIT (p); + p->CC = NULL; + p->CC_len = 0; + p->TC = rde_tc_new (); + p->ES = rde_stack_new (error_state_free); + p->LS = rde_stack_new (NULL); + p->ast = rde_stack_new (ast_node_free); + p->mark = rde_stack_new (NULL); + RETURN ("%p", p); + } + SCOPE void + rde_param_del (RDE_PARAM p) + { + ENTER ("rde_param_del"); + TRACE (("RDE_PARAM %p",p)); + ER_CLEAR (p); TRACE (("\ter_clear")); + SV_CLEAR (p); TRACE (("\tsv_clear")); + nc_clear (p); TRACE (("\tnc_clear")); + Tcl_DeleteHashTable (&p->NC); TRACE (("\tnc hashtable delete")); + rde_tc_del (p->TC); TRACE (("\ttc clear")); + rde_stack_del (p->ES); TRACE (("\tes clear")); + rde_stack_del (p->LS); TRACE (("\tls clear")); + rde_stack_del (p->ast); TRACE (("\tast clear")); + rde_stack_del (p->mark); TRACE (("\tmark clear")); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_DecrRefCount (p->readbuf); + ckfree ((char*) p); + RETURNVOID; + } + SCOPE void + rde_param_reset (RDE_PARAM p, Tcl_Channel chan) + { + ENTER ("rde_param_reset"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("Tcl_Channel %p",chan)); + p->IN = chan; + p->CL = -1; + p->ST = 0; + p->CC = NULL; + p->CC_len = 0; + ER_CLEAR (p); + SV_CLEAR (p); + nc_clear (p); + rde_tc_clear (p->TC); + rde_stack_trim (p->ES, 0); + rde_stack_trim (p->LS, 0); + rde_stack_trim (p->ast, 0); + rde_stack_trim (p->mark, 0); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + RETURNVOID; + } + SCOPE void + rde_param_update_strings (RDE_PARAM p, long int nstr, char** strings) + { + ENTER ("rde_param_update_strings"); + TRACE (("RDE_PARAM %p", p)); + TRACE (("INT %d strings", nstr)); + p->numstr = nstr; + p->string = strings; + RETURNVOID; + } + SCOPE void + rde_param_data (RDE_PARAM p, char* buf, long int len) + { + (void) rde_tc_append (p->TC, buf, len); + } + SCOPE void + rde_param_clientdata (RDE_PARAM p, ClientData clientData) + { + p->clientData = clientData; + } + static void + nc_clear (RDE_PARAM p) + { + Tcl_HashSearch hs; + Tcl_HashEntry* he; + Tcl_HashTable* tablePtr; + for(he = Tcl_FirstHashEntry(&p->NC, &hs); + he != NULL; + he = Tcl_FirstHashEntry(&p->NC, &hs)) { + Tcl_HashSearch hsc; + Tcl_HashEntry* hec; + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (he); + for(hec = Tcl_FirstHashEntry(tablePtr, &hsc); + hec != NULL; + hec = Tcl_NextHashEntry(&hsc)) { + NC_STATE* scs = Tcl_GetHashValue (hec); + error_state_free (scs->ER); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + ckfree ((char*) scs); + } + Tcl_DeleteHashTable (tablePtr); + ckfree ((char*) tablePtr); + Tcl_DeleteHashEntry (he); + } + } + SCOPE ClientData + rde_param_query_clientdata (RDE_PARAM p) + { + return p->clientData; + } + SCOPE void + rde_param_query_amark (RDE_PARAM p, long int* mc, long int** mv) + { + rde_stack_get (p->mark, mc, (void***) mv); + } + SCOPE void + rde_param_query_ast (RDE_PARAM p, long int* ac, Tcl_Obj*** av) + { + rde_stack_get (p->ast, ac, (void***) av); + } + SCOPE const char* + rde_param_query_in (RDE_PARAM p) + { + return p->IN + ? Tcl_GetChannelName (p->IN) + : ""; + } + SCOPE const char* + rde_param_query_cc (RDE_PARAM p, long int* len) + { + *len = p->CC_len; + return p->CC; + } + SCOPE int + rde_param_query_cl (RDE_PARAM p) + { + return p->CL; + } + SCOPE const ERROR_STATE* + rde_param_query_er (RDE_PARAM p) + { + return p->ER; + } + SCOPE Tcl_Obj* + rde_param_query_er_tcl (RDE_PARAM p, const ERROR_STATE* er) + { + Tcl_Obj* res; + if (!er) { + + res = Tcl_NewStringObj ("", 0); + } else { + Tcl_Obj* ov [2]; + Tcl_Obj** mov; + long int mc, i, j; + long int* mv; + int lastid; + const char* msg; + rde_stack_get (er->msg, &mc, (void***) &mv); + + qsort (mv, mc, sizeof (long int), er_int_compare); + + mov = NALLOC (mc, Tcl_Obj*); + lastid = -1; + for (i=0, j=0; i < mc; i++) { + ASSERT_BOUNDS (i,mc); + if (mv [i] == lastid) continue; + lastid = mv [i]; + ASSERT_BOUNDS(mv[i],p->numstr); + msg = p->string [mv[i]]; + ASSERT_BOUNDS (j,mc); + mov [j] = Tcl_NewStringObj (msg, -1); + j++; + } + + ov [0] = Tcl_NewIntObj (er->loc); + ov [1] = Tcl_NewListObj (j, mov); + res = Tcl_NewListObj (2, ov); + ckfree ((char*) mov); + } + return res; + } + SCOPE void + rde_param_query_es (RDE_PARAM p, long int* ec, ERROR_STATE*** ev) + { + rde_stack_get (p->ES, ec, (void***) ev); + } + SCOPE void + rde_param_query_ls (RDE_PARAM p, long int* lc, void*** lv) + { + rde_stack_get (p->LS, lc, lv); + } + SCOPE long int + rde_param_query_lstop (RDE_PARAM p) + { + (long int) rde_stack_top (p->LS); + } + SCOPE Tcl_HashTable* + rde_param_query_nc (RDE_PARAM p) + { + return &p->NC; + } + SCOPE int + rde_param_query_st (RDE_PARAM p) + { + return p->ST; + } + SCOPE Tcl_Obj* + rde_param_query_sv (RDE_PARAM p) + { + TRACE (("SV_QUERY %p => (%p)", (p), (p)->SV)); \ + return p->SV; + } + SCOPE long int + rde_param_query_tc_size (RDE_PARAM p) + { + return rde_tc_size (p->TC); + } + SCOPE void + rde_param_query_tc_get_s (RDE_PARAM p, long int at, long int last, char** ch, long int* len) + { + rde_tc_get_s (p->TC, at, last, ch, len); + } + SCOPE const char* + rde_param_query_string (RDE_PARAM p, long int id) + { + TRACE (("rde_param_query_string (RDE_PARAM %p, %d/%d)", p, id, p->numstr)); + ASSERT_BOUNDS(id,p->numstr); + return p->string [id]; + } + SCOPE void + rde_param_i_ast_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->mark, 1); + } + SCOPE void + rde_param_i_ast_pop_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_pop_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_push (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_ast_value_push (RDE_PARAM p) + { + ENTER ("rde_param_i_ast_value_push"); + TRACE (("RDE_PARAM %p",p)); + ASSERT(p->SV,"Unable to push undefined semantic value"); + TRACE (("rde_param_i_ast_value_push %p => (%p)", p, p->SV)); + TRACE (("SV = (%p rc%d '%s')", p->SV, p->SV->refCount, Tcl_GetString (p->SV))); + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + RETURNVOID; + } + static void + ast_node_free (void* n) + { + Tcl_DecrRefCount ((Tcl_Obj*) n); + } + SCOPE void + rde_param_i_error_clear (RDE_PARAM p) + { + ER_CLEAR (p); + } + SCOPE void + rde_param_i_error_nonterminal (RDE_PARAM p, int s) + { + + return; + long int pos; + if (!p->ER) return; + pos = 1 + (long int) rde_stack_top (p->LS); + if (p->ER->loc != pos) return; + error_set (p, s); + p->ER->loc = pos; + } + SCOPE void + rde_param_i_error_pop_merge (RDE_PARAM p) + { + ERROR_STATE* top = (ERROR_STATE*) rde_stack_top (p->ES); + + if (top == p->ER) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!top) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!p->ER) { + rde_stack_drop (p->ES, 1); + p->ER = top; + + return; + } + + if (top->loc < p->ER->loc) { + rde_stack_pop (p->ES, 1); + return; + } + + if (top->loc > p->ER->loc) { + rde_stack_drop (p->ES, 1); + error_state_free (p->ER); + p->ER = top; + + return; + } + + rde_stack_move (p->ER->msg, top->msg); + rde_stack_pop (p->ES, 1); + } + SCOPE void + rde_param_i_error_push (RDE_PARAM p) + { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + static void + error_set (RDE_PARAM p, int s) + { + error_state_free (p->ER); + p->ER = ALLOC (ERROR_STATE); + p->ER->refCount = 1; + p->ER->loc = p->CL; + p->ER->msg = rde_stack_new (NULL); + ASSERT_BOUNDS(s,p->numstr); + rde_stack_push (p->ER->msg, (void*) s); + } + static void + error_state_free (void* esx) + { + ERROR_STATE* es = esx; + if (!es) return; + es->refCount --; + if (es->refCount > 0) return; + rde_stack_del (es->msg); + ckfree ((char*) es); + } + SCOPE void + rde_param_i_loc_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_pop_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_push (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + } + SCOPE void + rde_param_i_loc_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + } + SCOPE void + rde_param_i_input_next (RDE_PARAM p, int m) + { + int leni; + char* ch; + ASSERT_BOUNDS(m,p->numstr); + p->CL ++; + if (p->CL < rde_tc_size (p->TC)) { + + rde_tc_get (p->TC, p->CL, &p->CC, &p->CC_len); + ASSERT_BOUNDS (p->CC_len, TCL_UTF_MAX); + p->ST = 1; + ER_CLEAR (p); + return; + } + if (!p->IN || + Tcl_Eof (p->IN) || + (Tcl_ReadChars (p->IN, p->readbuf, 1, 0) <= 0)) { + + p->ST = 0; + error_set (p, m); + return; + } + + ch = Tcl_GetStringFromObj (p->readbuf, &leni); + ASSERT_BOUNDS (leni, TCL_UTF_MAX); + p->CC = rde_tc_append (p->TC, ch, leni); + p->CC_len = leni; + p->ST = 1; + ER_CLEAR (p); + } + SCOPE void + rde_param_i_status_fail (RDE_PARAM p) + { + p->ST = 0; + } + SCOPE void + rde_param_i_status_ok (RDE_PARAM p) + { + p->ST = 1; + } + SCOPE void + rde_param_i_status_negate (RDE_PARAM p) + { + p->ST = !p->ST; + } + SCOPE int + rde_param_i_symbol_restore (RDE_PARAM p, int s) + { + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + + hPtr = Tcl_FindHashEntry (&p->NC, (char*) p->CL); + if (!hPtr) { return 0; } + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + hPtr = Tcl_FindHashEntry (tablePtr, (char*) s); + if (!hPtr) { return 0; } + + scs = Tcl_GetHashValue (hPtr); + p->CL = scs->CL; + p->ST = scs->ST; + error_state_free (p->ER); + p->ER = scs->ER; + if (p->ER) { p->ER->refCount ++; } + TRACE (("SV_RESTORE (%p) '%s'",scs->SV, scs->SV ? Tcl_GetString (scs->SV):"")); + SV_SET (p, scs->SV); + return 1; + } + SCOPE void + rde_param_i_symbol_save (RDE_PARAM p, int s) + { + long int at = (long int) rde_stack_top (p->LS); + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + int isnew; + ENTER ("rde_param_i_symbol_save"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("INT %d",s)); + + hPtr = Tcl_CreateHashEntry (&p->NC, (char*) at, &isnew); + if (isnew) { + tablePtr = ALLOC (Tcl_HashTable); + Tcl_InitHashTable (tablePtr, TCL_ONE_WORD_KEYS); + Tcl_SetHashValue (hPtr, tablePtr); + } else { + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + } + hPtr = Tcl_CreateHashEntry (tablePtr, (char*) s, &isnew); + if (isnew) { + + scs = ALLOC (NC_STATE); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "")); + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + Tcl_SetHashValue (hPtr, scs); + } else { + + scs = (NC_STATE*) Tcl_GetHashValue (hPtr); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE/over (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "" )); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + error_state_free (scs->ER); + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + } + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_test_alnum (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlnum, tc_alnum); + } + SCOPE void + rde_param_i_test_alpha (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlpha, tc_alpha); + } + SCOPE void + rde_param_i_test_ascii (RDE_PARAM p) + { + test_class (p, UniCharIsAscii, tc_ascii); + } + SCOPE void + rde_param_i_test_control (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsControl, tc_control); + } + SCOPE void + rde_param_i_test_char (RDE_PARAM p, const char* c, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = Tcl_UtfNcmp (p->CC, c, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_ddigit (RDE_PARAM p) + { + test_class (p, UniCharIsDecDigit, tc_ddigit); + } + SCOPE void + rde_param_i_test_digit (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsDigit, tc_digit); + } + SCOPE void + rde_param_i_test_graph (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsGraph, tc_graph); + } + SCOPE void + rde_param_i_test_lower (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsLower, tc_lower); + } + SCOPE void + rde_param_i_test_print (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPrint, tc_printable); + } + SCOPE void + rde_param_i_test_punct (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPunct, tc_punct); + } + SCOPE void + rde_param_i_test_range (RDE_PARAM p, char* s, char* e, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = + (Tcl_UtfNcmp (s, p->CC, 1) <= 0) && + (Tcl_UtfNcmp (p->CC, e, 1) <= 0); + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_space (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsSpace, tc_space); + } + SCOPE void + rde_param_i_test_upper (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsUpper, tc_upper); + } + SCOPE void + rde_param_i_test_wordchar (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsWordChar, tc_wordchar); + } + SCOPE void + rde_param_i_test_xdigit (RDE_PARAM p) + { + test_class (p, UniCharIsHexDigit, tc_xdigit); + } + static void + test_class (RDE_PARAM p, UniCharClass class, test_class_id id) + { + Tcl_UniChar ch; + Tcl_UtfToUniChar(p->CC, &ch); + ASSERT_BOUNDS(id,p->numstr); + p->ST = !!class (ch); + + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, id); + p->CL --; + } + } + static int + UniCharIsAscii (int character) + { + return (character >= 0) && (character < 0x80); + } + static int + UniCharIsHexDigit (int character) + { + return (character >= 0) && (character < 0x80) && isxdigit(character); + } + static int + UniCharIsDecDigit (int character) + { + return (character >= 0) && (character < 0x80) && isdigit(character); + } + SCOPE void + rde_param_i_value_clear (RDE_PARAM p) + { + SV_CLEAR (p); + } + SCOPE void + rde_param_i_value_leaf (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + Tcl_Obj* ov [3]; + long int pos = 1 + (long int) rde_stack_top (p->LS); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + newsv = Tcl_NewListObj (3, ov); + TRACE (("rde_param_i_value_leaf => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + } + SCOPE void + rde_param_i_value_reduce (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + int oc, i, j; + Tcl_Obj** ov; + long int ac; + Tcl_Obj** av; + long int pos = 1 + (long int) rde_stack_top (p->LS); + long int mark = (long int) rde_stack_top (p->mark); + long int asize = rde_stack_size (p->ast); + long int new = asize - mark; + ASSERT (new >= 0, "Bad number of elements to reduce"); + ov = NALLOC (3+new, Tcl_Obj*); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + rde_stack_get (p->ast, &ac, (void***) &av); + for (i = 3, j = mark; j < asize; i++, j++) { + ASSERT_BOUNDS (i, 3+new); + ASSERT_BOUNDS (j, ac); + ov [i] = av [j]; + } + ASSERT (i == 3+new, "Reduction result incomplete"); + newsv = Tcl_NewListObj (3+new, ov); + TRACE (("rde_param_i_value_reduce => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + ckfree ((char*) ov); + } + static int + er_int_compare (const void* a, const void* b) + { + long int ai = *((long int*) a); + long int bi = *((long int*) b); + if (ai < bi) { return -1; } + if (ai > bi) { return 1; } + return 0; + } + SCOPE int + rde_param_i_symbol_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE void + rde_param_i_symbol_done_d_reduce (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_reduce (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_d_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_symbol_done_d_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_next_char (RDE_PARAM p, char* c, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_char (p, c, m); + } + SCOPE void + rde_param_i_next_range (RDE_PARAM p, char* s, char* e, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_range (p, s, e, m); + } + SCOPE void + rde_param_i_next_alnum (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alnum (p); + } + SCOPE void + rde_param_i_next_alpha (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alpha (p); + } + SCOPE void + rde_param_i_next_ascii (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ascii (p); + } + SCOPE void + rde_param_i_next_control (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_control (p); + } + SCOPE void + rde_param_i_next_ddigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ddigit (p); + } + SCOPE void + rde_param_i_next_digit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_digit (p); + } + SCOPE void + rde_param_i_next_graph (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_graph (p); + } + SCOPE void + rde_param_i_next_lower (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_lower (p); + } + SCOPE void + rde_param_i_next_print (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_print (p); + } + SCOPE void + rde_param_i_next_punct (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_punct (p); + } + SCOPE void + rde_param_i_next_space (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_space (p); + } + SCOPE void + rde_param_i_next_upper (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_upper (p); + } + SCOPE void + rde_param_i_next_wordchar (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_wordchar (p); + } + SCOPE void + rde_param_i_next_xdigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_xdigit (p); + } + SCOPE void + rde_param_i_notahead_start_d (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_notahead_exit_d (RDE_PARAM p) + { + if (p->ST) { + rde_param_i_ast_pop_rewind (p); + } else { + rde_stack_pop (p->mark, 1); + } + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_notahead_exit (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_state_push_2 (RDE_PARAM p) + { + + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + SCOPE void + rde_param_i_state_push_void (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_push_value (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_merge_ok (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } + SCOPE int + rde_param_i_kleene_close (RDE_PARAM p) + { + int stop = !p->ST; + rde_param_i_error_pop_merge (p); + if (stop) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_kleene_abort (RDE_PARAM p) + { + int stop = !p->ST; + if (stop) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_seq_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_bra_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE void + rde_param_i_next_str (RDE_PARAM p, const char* str, int m) + { + int at = p->CL; + + while (*str) { + rde_param_i_input_next (p, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + rde_param_i_test_char (p, str, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + str = Tcl_UtfNext (str); + } + } + SCOPE void + rde_param_i_next_class (RDE_PARAM p, const char* class, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + while (*class) { + p->ST = Tcl_UtfNcmp (p->CC, class, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + return; + } + class = Tcl_UtfNext (class); + } + error_set (p, m); + p->CL --; + } + + + /* + * Declaring the parse functions + */ + + static void poskleene_2 (RDE_PARAM p); + + /* + * Precomputed table of strings (symbols, error messages, etc.). + */ + + static char const* p_string [15] = { + /* 0 = */ "alnum", + /* 1 = */ "alpha", + /* 2 = */ "ascii", + /* 3 = */ "control", + /* 4 = */ "ddigit", + /* 5 = */ "digit", + /* 6 = */ "graph", + /* 7 = */ "lower", + /* 8 = */ "print", + /* 9 = */ "punct", + /* 10 = */ "space", + /* 11 = */ "upper", + /* 12 = */ "wordchar", + /* 13 = */ "xdigit", + /* 14 = */ "t a" + }; + + /* + * Grammar Start Expression + */ + + static void MAIN (RDE_PARAM p) { + poskleene_2 (p); + return; + } + + static void poskleene_2 (RDE_PARAM p) { + /* + * + + * 'a' + */ + + rde_param_i_loc_push (p); + rde_param_i_next_char (p, "a", 14); + if (rde_param_i_kleene_abort(p)) return; + while (1) { + rde_param_i_state_push_2 (p); + rde_param_i_next_char (p, "a", 14); + if (rde_param_i_kleene_close(p)) return; + } + return; + } + + /* -*- c -*- */ + + typedef struct PARSERg { + long int counter; + char buf [50]; + } PARSERg; + + static void + PARSERgRelease (ClientData cd, Tcl_Interp* interp) + { + ckfree((char*) cd); + } + + static const char* + PARSERnewName (Tcl_Interp* interp) + { +#define KEY "tcllib/parser/PACKAGE/TEA" + + Tcl_InterpDeleteProc* proc = PARSERgRelease; + PARSERg* parserg; + + parserg = Tcl_GetAssocData (interp, KEY, &proc); + if (parserg == NULL) { + parserg = (PARSERg*) ckalloc (sizeof (PARSERg)); + parserg->counter = 0; + + Tcl_SetAssocData (interp, KEY, proc, + (ClientData) parserg); + } + + parserg->counter ++; + sprintf (parserg->buf, "PARSER%d", parserg->counter); + return parserg->buf; +#undef KEY + } + + static void + PARSERdeleteCmd (ClientData clientData) + { + /* + * Release the whole PARSER + * (Low-level engine only actually). + */ + rde_param_del ((RDE_PARAM) clientData); + } + + + /* * ** *** ***** ******** ************* + ** Functions implementing the object methods, and helper. + */ + + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp); + + static int parser_PARSE (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + int mode; + Tcl_Channel chan; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "chan"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, + Tcl_GetString (objv[2]), + &mode); + + if (!chan) { + return TCL_ERROR; + } + + rde_param_reset (p, chan); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + static int parser_PARSET (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + char* buf; + int len; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "text"); + return TCL_ERROR; + } + + buf = Tcl_GetStringFromObj (objv[2], &len); + + rde_param_reset (p, NULL); + rde_param_data (p, buf, len); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + /* See also rde_critcl/m.c, param_COMPLETE() */ + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp) + { + if (rde_param_query_st (p)) { + long int ac; + Tcl_Obj** av; + + rde_param_query_ast (p, &ac, &av); + + if (ac > 1) { + Tcl_Obj** lv = NALLOC (3+ac, Tcl_Obj*); + + memcpy(lv + 3, av, ac * sizeof (Tcl_Obj*)); + lv [0] = Tcl_NewObj (); + lv [1] = Tcl_NewIntObj (1 + rde_param_query_lstop (p)); + lv [2] = Tcl_NewIntObj (rde_param_query_cl (p)); + + Tcl_SetObjResult (interp, Tcl_NewListObj (3, lv)); + ckfree ((char*) lv); + + } else if (ac == 0) { + /* + * Match, but no AST. This is possible if the grammar + * consists of only the start expression. + */ + Tcl_SetObjResult (interp, Tcl_NewStringObj ("",-1)); + } else { + Tcl_SetObjResult (interp, av [0]); + } + + return TCL_OK; + } else { + Tcl_Obj* xv [1]; + const ERROR_STATE* er = rde_param_query_er (p); + Tcl_Obj* res = rde_param_query_er_tcl (p, er); + /* res = list (location, list(msg)) */ + + /* Stick the exception type-tag before the existing elements */ + xv [0] = Tcl_NewStringObj ("pt::rde",-1); + Tcl_ListObjReplace(interp, res, 0, 0, 1, xv); + + Tcl_SetErrorCode (interp, "PT", "RDE", "SYNTAX", NULL); + Tcl_SetObjResult (interp, res); + return TCL_ERROR; + } + } + + + /* * ** *** ***** ******** ************* + ** Object command, method dispatch. + */ + static int parser_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + RDE_PARAM p = (RDE_PARAM) cd; + int m, res; + + static CONST char* methods [] = { + "destroy", "parse", "parset", NULL + }; + enum methods { + M_DESTROY, M_PARSE, M_PARSET + }; + + if (objc < 2) { + Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option", + 0, &m) != TCL_OK) { + return TCL_ERROR; + } + + /* Dispatch to methods. They check the #args in + * detail before performing the requested + * functionality + */ + + switch (m) { + case M_DESTROY: + if (objc != 2) { + Tcl_WrongNumArgs (interp, 2, objv, NULL); + return TCL_ERROR; + } + + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) rde_param_query_clientdata (p)); + return TCL_OK; + + case M_PARSE: res = parser_PARSE (p, interp, objc, objv); break; + case M_PARSET: res = parser_PARSET (p, interp, objc, objv); break; + default: + /* Not coming to this place */ + ASSERT (0,"Reached unreachable location"); + } + + return res; + } + + /** * ** *** ***** ******** ************* + * Class command, i.e. object construction. + */ + static int ParserClassCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const*objv) { + /* + * Syntax: No arguments beyond the name + */ + + RDE_PARAM parser; + CONST char* name; + Tcl_Obj* fqn; + Tcl_CmdInfo ci; + Tcl_Command c; + +#define USAGE "?name?" + + if ((objc != 2) && (objc != 1)) { + Tcl_WrongNumArgs (interp, 1, objv, USAGE); + return TCL_ERROR; + } + + if (objc < 2) { + name = PARSERnewName (interp); + } else { + name = Tcl_GetString (objv [1]); + } + + if (!Tcl_StringMatch (name, "::*")) { + /* Relative name. Prefix with current namespace */ + + Tcl_Eval (interp, "namespace current"); + fqn = Tcl_GetObjResult (interp); + fqn = Tcl_DuplicateObj (fqn); + Tcl_IncrRefCount (fqn); + + if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { + Tcl_AppendToObj (fqn, "::", -1); + } + Tcl_AppendToObj (fqn, name, -1); + } else { + fqn = Tcl_NewStringObj (name, -1); + Tcl_IncrRefCount (fqn); + } + Tcl_ResetResult (interp); + + if (Tcl_GetCommandInfo (interp, + Tcl_GetString (fqn), + &ci)) { + Tcl_Obj* err; + + err = Tcl_NewObj (); + Tcl_AppendToObj (err, "command \"", -1); + Tcl_AppendObjToObj (err, fqn); + Tcl_AppendToObj (err, "\" already exists", -1); + + Tcl_DecrRefCount (fqn); + Tcl_SetObjResult (interp, err); + return TCL_ERROR; + } + + parser = rde_param_new (sizeof(p_string)/sizeof(char*), (char**) p_string); + c = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), + parser_objcmd, (ClientData) parser, + PARSERdeleteCmd); + rde_param_clientdata (parser, (ClientData) c); + Tcl_SetObjResult (interp, fqn); + Tcl_DecrRefCount (fqn); + return TCL_OK; + } + +int Package_Init(Tcl_Interp* interp) { + if (interp == 0) return TCL_ERROR; + + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + + if (Tcl_CreateObjCommand(interp, "PARSER", ParserClassCmd , NULL, NULL) == NULL) { + Tcl_SetResult(interp, "Can't create constructor", NULL); + return TCL_ERROR; + } + + + Tcl_PkgProvide(interp, "PACKAGE", "0.1"); + + return TCL_OK; +} ADDED modules/pt/tests/data/ok/peg_cparam-tea/9_ahead Index: modules/pt/tests/data/ok/peg_cparam-tea/9_ahead ================================================================== --- /dev/null +++ modules/pt/tests/data/ok/peg_cparam-tea/9_ahead @@ -0,0 +1,2034 @@ +/************************************************************ +** +** TEA-based C/PARAM implementation of the parsing +** expression grammar +** +** TEMPLATE +** +** Generated from file TEST +** for user unknown +** +* * ** *** ***** ******** ************* *********************/ + #include + #include + #include + #include + #define SCOPE static + +#line 1 "rde_critcl/util.h" + + #ifndef _RDE_UTIL_H + #define _RDE_UTIL_H 1 + #ifndef SCOPE + #define SCOPE + #endif + #define ALLOC(type) (type *) ckalloc (sizeof (type)) + #define NALLOC(n,type) (type *) ckalloc ((n) * sizeof (type)) + #undef RDE_DEBUG + #define RDE_DEBUG 1 + #undef RDE_TRACE + #ifdef RDE_DEBUG + #define STOPAFTER(x) { static int count = (x); count --; if (!count) { Tcl_Panic ("stop"); } } + #define XSTR(x) #x + #define STR(x) XSTR(x) + #define RANGEOK(i,n) ((0 <= (i)) && (i < (n))) + #define ASSERT(x,msg) if (!(x)) { Tcl_Panic (msg " (" #x "), in file " __FILE__ " @line " STR(__LINE__));} + #define ASSERT_BOUNDS(i,n) ASSERT (RANGEOK(i,n),"array index out of bounds: " STR(i) " >= " STR(n)) + #else + #define STOPAFTER(x) + #define ASSERT(x,msg) + #define ASSERT_BOUNDS(i,n) + #endif + #ifdef RDE_TRACE + SCOPE void trace_enter (const char* fun); + SCOPE void trace_return (const char *pat, ...); + SCOPE void trace_printf (const char *pat, ...); + #define ENTER(fun) trace_enter (fun) + #define RETURN(format,x) trace_return (format,x) ; return x + #define RETURNVOID trace_return ("%s","(void)") ; return + #define TRACE0(x) trace_printf0 x + #define TRACE(x) trace_printf x + #else + #define ENTER(fun) + #define RETURN(f,x) return x + #define RETURNVOID return + #define TRACE0(x) + #define TRACE(x) + #endif + #endif + + +#line 1 "rde_critcl/stack.h" + + #ifndef _RDE_DS_STACK_H + #define _RDE_DS_STACK_H 1 + typedef void (*RDE_STACK_CELL_FREE) (void* cell); + typedef struct RDE_STACK_* RDE_STACK; + static const int RDE_STACK_INITIAL_SIZE = 256; + #endif + + +#line 1 "rde_critcl/tc.h" + + #ifndef _RDE_DS_TC_H + #define _RDE_DS_TC_H 1 + typedef struct RDE_TC_* RDE_TC; + #endif + + +#line 1 "rde_critcl/param.h" + + #ifndef _RDE_DS_PARAM_H + #define _RDE_DS_PARAM_H 1 + typedef struct RDE_PARAM_* RDE_PARAM; + typedef struct ERROR_STATE { + int refCount; + long int loc; + RDE_STACK msg; + } ERROR_STATE; + typedef struct NC_STATE { + long int CL; + long int ST; + Tcl_Obj* SV; + ERROR_STATE* ER; + } NC_STATE; + #endif + + +#line 1 "rde_critcl/util.c" + + #ifdef RDE_TRACE + typedef struct F_STACK { + const char* str; + struct F_STACK* down; + } F_STACK; + static F_STACK* top = 0; + static int level = 0; + static void + push (const char* str) + { + F_STACK* new = ALLOC (F_STACK); + new->str = str; + new->down = top; + top = new; + level += 4; + } + static void + pop (void) + { + F_STACK* next = top->down; + level -= 4; + ckfree ((char*)top); + top = next; + } + static void + indent (void) + { + int i; + for (i = 0; i < level; i++) { + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + if (top) { + fwrite(top->str, 1, strlen(top->str), stdout); + fflush (stdout); + } + fwrite(" ", 1, 1, stdout); + fflush (stdout); + } + SCOPE void + trace_enter (const char* fun) + { + push (fun); + indent(); + fwrite("ENTER\n", 1, 6, stdout); + fflush (stdout); + } + static char msg [1024*1024]; + SCOPE void + trace_return (const char *pat, ...) + { + int len; + va_list args; + indent(); + fwrite("RETURN = ", 1, 9, stdout); + fflush (stdout); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + pop(); + } + SCOPE void + trace_printf (const char *pat, ...) + { + int len; + va_list args; + indent(); + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + SCOPE void + trace_printf0 (const char *pat, ...) + { + int len; + va_list args; + va_start(args, pat); + len = vsprintf(msg, pat, args); + va_end(args); + msg[len++] = '\n'; + msg[len] = '\0'; + fwrite(msg, 1, len, stdout); + fflush (stdout); + } + #endif + + +#line 1 "rde_critcl/stack.c" + + typedef struct RDE_STACK_ { + long int max; + long int top; + RDE_STACK_CELL_FREE freeCellProc; + void** cell; + } RDE_STACK_; + + SCOPE RDE_STACK + rde_stack_new (RDE_STACK_CELL_FREE freeCellProc) + { + RDE_STACK s = ALLOC (RDE_STACK_); + s->cell = NALLOC (RDE_STACK_INITIAL_SIZE, void*); + s->max = RDE_STACK_INITIAL_SIZE; + s->top = 0; + s->freeCellProc = freeCellProc; + return s; + } + SCOPE void + rde_stack_del (RDE_STACK s) + { + if (s->freeCellProc && s->top) { + long int i; + for (i=0; i < s->top; i++) { + ASSERT_BOUNDS(i,s->max); + s->freeCellProc ( s->cell [i] ); + } + } + ckfree ((char*) s->cell); + ckfree ((char*) s); + } + SCOPE void + rde_stack_push (RDE_STACK s, void* item) + { + if (s->top >= s->max) { + long int new = s->max ? (2 * s->max) : RDE_STACK_INITIAL_SIZE; + void** cell = (void**) ckrealloc ((char*) s->cell, new * sizeof(void*)); + ASSERT (cell,"Memory allocation failure for RDE stack"); + s->max = new; + s->cell = cell; + } + ASSERT_BOUNDS(s->top,s->max); + s->cell [s->top] = item; + s->top ++; + } + SCOPE void* + rde_stack_top (RDE_STACK s) + { + ASSERT_BOUNDS(s->top-1,s->max); + return s->cell [s->top - 1]; + } + SCOPE void + rde_stack_pop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + if (s->freeCellProc) { + while (n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + n --; + } + } else { + s->top -= n; + } + } + SCOPE void + rde_stack_trim (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad trimsize"); + if (s->freeCellProc) { + while (s->top > n) { + s->top --; + ASSERT_BOUNDS(s->top,s->max); + s->freeCellProc ( s->cell [s->top] ); + } + } else { + s->top = n; + } + } + SCOPE void + rde_stack_drop (RDE_STACK s, long int n) + { + ASSERT (n >= 0, "Bad pop count"); + if (n == 0) return; + s->top -= n; + } + SCOPE void + rde_stack_move (RDE_STACK dst, RDE_STACK src) + { + ASSERT (dst->freeCellProc == src->freeCellProc, "Ownership mismatch"); + + while (src->top > 0) { + src->top --; + ASSERT_BOUNDS(src->top,src->max); + rde_stack_push (dst, src->cell [src->top] ); + } + } + SCOPE void + rde_stack_get (RDE_STACK s, long int* cn, void*** cc) + { + *cn = s->top; + *cc = s->cell; + } + SCOPE long int + rde_stack_size (RDE_STACK s) + { + return s->top; + } + + +#line 1 "rde_critcl/tc.c" + + typedef struct RDE_TC_ { + int max; + int num; + char* str; + RDE_STACK off; + } RDE_TC_; + + SCOPE RDE_TC + rde_tc_new (void) + { + RDE_TC tc = ALLOC (RDE_TC_); + tc->max = RDE_STACK_INITIAL_SIZE; + tc->num = 0; + tc->str = NALLOC (RDE_STACK_INITIAL_SIZE, char); + tc->off = rde_stack_new (NULL); + return tc; + } + SCOPE void + rde_tc_del (RDE_TC tc) + { + rde_stack_del (tc->off); + ckfree (tc->str); + ckfree ((char*) tc); + } + SCOPE long int + rde_tc_size (RDE_TC tc) + { + return rde_stack_size (tc->off); + } + SCOPE void + rde_tc_clear (RDE_TC tc) + { + tc->num = 0; + rde_stack_trim (tc->off, 0); + } + SCOPE char* + rde_tc_append (RDE_TC tc, char* string, long int len) + { + long int base = tc->num; + long int off = tc->num; + char* ch; + int clen; + Tcl_UniChar uni; + if (len < 0) { + len = strlen (string); + } + + if (!len) { + return tc->str + base; + } + + if ((tc->num + len) >= tc->max) { + int new = len + (tc->max ? (2 * tc->max) : RDE_STACK_INITIAL_SIZE); + char* str = ckrealloc (tc->str, new * sizeof(char)); + ASSERT (str,"Memory allocation failure for token character array"); + tc->max = new; + tc->str = str; + } + tc->num += len; + ASSERT_BOUNDS(tc->num,tc->max); + ASSERT_BOUNDS(off,tc->max); + ASSERT_BOUNDS(off+len-1,tc->max); + ASSERT_BOUNDS(off+len-1,tc->num); + memcpy (tc->str + off, string, len); + + ch = string; + while (ch < (string + len)) { + ASSERT_BOUNDS(off,tc->num); + rde_stack_push (tc->off, (void*) off); + clen = Tcl_UtfToUniChar (ch, &uni); + off += clen; + ch += clen; + } + return tc->str + base; + } + SCOPE void + rde_tc_get (RDE_TC tc, int at, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + off = ov [at]; + if ((at+1) == oc) { + end = tc->num; + } else { + end = ov [at+1]; + } + TRACE (("rde_tc_get (RDE_TC %p, @ %d) => %d.[%d ... %d]/%d",tc,at,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + SCOPE void + rde_tc_get_s (RDE_TC tc, int at, int last, char** ch, long int* len) + { + long int oc, off, top, end; + long int* ov; + rde_stack_get (tc->off, &oc, (void***) &ov); + ASSERT_BOUNDS(at,oc); + ASSERT_BOUNDS(last,oc); + off = ov [at]; + if ((last+1) == oc) { + end = tc->num; + } else { + end = ov [last+1]; + } + TRACE (("rde_tc_get_s (RDE_TC %p, @ %d .. %d) => %d.[%d ... %d]/%d",tc,at,last,end-off,off,end-1,tc->num)); + ASSERT_BOUNDS(off,tc->num); + ASSERT_BOUNDS(end-1,tc->num); + *ch = tc->str + off; + *len = end - off; + } + + +#line 1 "rde_critcl/param.c" + + typedef struct RDE_PARAM_ { + Tcl_Channel IN; + Tcl_Obj* readbuf; + char* CC; + long int CC_len; + RDE_TC TC; + long int CL; + RDE_STACK LS; + ERROR_STATE* ER; + RDE_STACK ES; + long int ST; + Tcl_Obj* SV; + Tcl_HashTable NC; + + RDE_STACK ast ; + RDE_STACK mark ; + + long int numstr; + char** string; + + ClientData clientData; + } RDE_PARAM_; + typedef int (*UniCharClass) (int); + typedef enum test_class_id { + tc_alnum, + tc_alpha, + tc_ascii, + tc_control, + tc_ddigit, + tc_digit, + tc_graph, + tc_lower, + tc_printable, + tc_punct, + tc_space, + tc_upper, + tc_wordchar, + tc_xdigit + } test_class_id; + static void ast_node_free (void* n); + static void error_state_free (void* es); + static void error_set (RDE_PARAM p, int s); + static void nc_clear (RDE_PARAM p); + static int UniCharIsAscii (int character); + static int UniCharIsHexDigit (int character); + static int UniCharIsDecDigit (int character); + static void test_class (RDE_PARAM p, UniCharClass class, test_class_id id); + static int er_int_compare (const void* a, const void* b); + #define SV_INIT(p) \ + p->SV = NULL; \ + TRACE (("SV_INIT (%p => %p)", (p), (p)->SV)) + #define SV_SET(p,newsv) \ + if (((p)->SV) != (newsv)) { \ + TRACE (("SV_CLEAR/set (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = (newsv); \ + TRACE (("SV_SET (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_IncrRefCount ((p)->SV); \ + } \ + } + #define SV_CLEAR(p) \ + TRACE (("SV_CLEAR (%p => %p)", (p), (p)->SV)); \ + if ((p)->SV) { \ + Tcl_DecrRefCount ((p)->SV); \ + } \ + (p)->SV = NULL + #define ER_INIT(p) \ + p->ER = NULL; \ + TRACE (("ER_INIT (%p => %p)", (p), (p)->ER)) + #define ER_CLEAR(p) \ + error_state_free ((p)->ER); \ + (p)->ER = NULL + SCOPE RDE_PARAM + rde_param_new (long int nstr, char** strings) + { + RDE_PARAM p; + ENTER ("rde_param_new"); + TRACE (("\tINT %d strings @ %p", nstr, strings)); + p = ALLOC (RDE_PARAM_); + p->numstr = nstr; + p->string = strings; + p->readbuf = Tcl_NewObj (); + Tcl_IncrRefCount (p->readbuf); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_InitHashTable (&p->NC, TCL_ONE_WORD_KEYS); + p->IN = NULL; + p->CL = -1; + p->ST = 0; + ER_INIT (p); + SV_INIT (p); + p->CC = NULL; + p->CC_len = 0; + p->TC = rde_tc_new (); + p->ES = rde_stack_new (error_state_free); + p->LS = rde_stack_new (NULL); + p->ast = rde_stack_new (ast_node_free); + p->mark = rde_stack_new (NULL); + RETURN ("%p", p); + } + SCOPE void + rde_param_del (RDE_PARAM p) + { + ENTER ("rde_param_del"); + TRACE (("RDE_PARAM %p",p)); + ER_CLEAR (p); TRACE (("\ter_clear")); + SV_CLEAR (p); TRACE (("\tsv_clear")); + nc_clear (p); TRACE (("\tnc_clear")); + Tcl_DeleteHashTable (&p->NC); TRACE (("\tnc hashtable delete")); + rde_tc_del (p->TC); TRACE (("\ttc clear")); + rde_stack_del (p->ES); TRACE (("\tes clear")); + rde_stack_del (p->LS); TRACE (("\tls clear")); + rde_stack_del (p->ast); TRACE (("\tast clear")); + rde_stack_del (p->mark); TRACE (("\tmark clear")); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + Tcl_DecrRefCount (p->readbuf); + ckfree ((char*) p); + RETURNVOID; + } + SCOPE void + rde_param_reset (RDE_PARAM p, Tcl_Channel chan) + { + ENTER ("rde_param_reset"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("Tcl_Channel %p",chan)); + p->IN = chan; + p->CL = -1; + p->ST = 0; + p->CC = NULL; + p->CC_len = 0; + ER_CLEAR (p); + SV_CLEAR (p); + nc_clear (p); + rde_tc_clear (p->TC); + rde_stack_trim (p->ES, 0); + rde_stack_trim (p->LS, 0); + rde_stack_trim (p->ast, 0); + rde_stack_trim (p->mark, 0); + TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); + RETURNVOID; + } + SCOPE void + rde_param_update_strings (RDE_PARAM p, long int nstr, char** strings) + { + ENTER ("rde_param_update_strings"); + TRACE (("RDE_PARAM %p", p)); + TRACE (("INT %d strings", nstr)); + p->numstr = nstr; + p->string = strings; + RETURNVOID; + } + SCOPE void + rde_param_data (RDE_PARAM p, char* buf, long int len) + { + (void) rde_tc_append (p->TC, buf, len); + } + SCOPE void + rde_param_clientdata (RDE_PARAM p, ClientData clientData) + { + p->clientData = clientData; + } + static void + nc_clear (RDE_PARAM p) + { + Tcl_HashSearch hs; + Tcl_HashEntry* he; + Tcl_HashTable* tablePtr; + for(he = Tcl_FirstHashEntry(&p->NC, &hs); + he != NULL; + he = Tcl_FirstHashEntry(&p->NC, &hs)) { + Tcl_HashSearch hsc; + Tcl_HashEntry* hec; + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (he); + for(hec = Tcl_FirstHashEntry(tablePtr, &hsc); + hec != NULL; + hec = Tcl_NextHashEntry(&hsc)) { + NC_STATE* scs = Tcl_GetHashValue (hec); + error_state_free (scs->ER); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + ckfree ((char*) scs); + } + Tcl_DeleteHashTable (tablePtr); + ckfree ((char*) tablePtr); + Tcl_DeleteHashEntry (he); + } + } + SCOPE ClientData + rde_param_query_clientdata (RDE_PARAM p) + { + return p->clientData; + } + SCOPE void + rde_param_query_amark (RDE_PARAM p, long int* mc, long int** mv) + { + rde_stack_get (p->mark, mc, (void***) mv); + } + SCOPE void + rde_param_query_ast (RDE_PARAM p, long int* ac, Tcl_Obj*** av) + { + rde_stack_get (p->ast, ac, (void***) av); + } + SCOPE const char* + rde_param_query_in (RDE_PARAM p) + { + return p->IN + ? Tcl_GetChannelName (p->IN) + : ""; + } + SCOPE const char* + rde_param_query_cc (RDE_PARAM p, long int* len) + { + *len = p->CC_len; + return p->CC; + } + SCOPE int + rde_param_query_cl (RDE_PARAM p) + { + return p->CL; + } + SCOPE const ERROR_STATE* + rde_param_query_er (RDE_PARAM p) + { + return p->ER; + } + SCOPE Tcl_Obj* + rde_param_query_er_tcl (RDE_PARAM p, const ERROR_STATE* er) + { + Tcl_Obj* res; + if (!er) { + + res = Tcl_NewStringObj ("", 0); + } else { + Tcl_Obj* ov [2]; + Tcl_Obj** mov; + long int mc, i, j; + long int* mv; + int lastid; + const char* msg; + rde_stack_get (er->msg, &mc, (void***) &mv); + + qsort (mv, mc, sizeof (long int), er_int_compare); + + mov = NALLOC (mc, Tcl_Obj*); + lastid = -1; + for (i=0, j=0; i < mc; i++) { + ASSERT_BOUNDS (i,mc); + if (mv [i] == lastid) continue; + lastid = mv [i]; + ASSERT_BOUNDS(mv[i],p->numstr); + msg = p->string [mv[i]]; + ASSERT_BOUNDS (j,mc); + mov [j] = Tcl_NewStringObj (msg, -1); + j++; + } + + ov [0] = Tcl_NewIntObj (er->loc); + ov [1] = Tcl_NewListObj (j, mov); + res = Tcl_NewListObj (2, ov); + ckfree ((char*) mov); + } + return res; + } + SCOPE void + rde_param_query_es (RDE_PARAM p, long int* ec, ERROR_STATE*** ev) + { + rde_stack_get (p->ES, ec, (void***) ev); + } + SCOPE void + rde_param_query_ls (RDE_PARAM p, long int* lc, void*** lv) + { + rde_stack_get (p->LS, lc, lv); + } + SCOPE long int + rde_param_query_lstop (RDE_PARAM p) + { + (long int) rde_stack_top (p->LS); + } + SCOPE Tcl_HashTable* + rde_param_query_nc (RDE_PARAM p) + { + return &p->NC; + } + SCOPE int + rde_param_query_st (RDE_PARAM p) + { + return p->ST; + } + SCOPE Tcl_Obj* + rde_param_query_sv (RDE_PARAM p) + { + TRACE (("SV_QUERY %p => (%p)", (p), (p)->SV)); \ + return p->SV; + } + SCOPE long int + rde_param_query_tc_size (RDE_PARAM p) + { + return rde_tc_size (p->TC); + } + SCOPE void + rde_param_query_tc_get_s (RDE_PARAM p, long int at, long int last, char** ch, long int* len) + { + rde_tc_get_s (p->TC, at, last, ch, len); + } + SCOPE const char* + rde_param_query_string (RDE_PARAM p, long int id) + { + TRACE (("rde_param_query_string (RDE_PARAM %p, %d/%d)", p, id, p->numstr)); + ASSERT_BOUNDS(id,p->numstr); + return p->string [id]; + } + SCOPE void + rde_param_i_ast_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->mark, 1); + } + SCOPE void + rde_param_i_ast_pop_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_pop_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_rewind (RDE_PARAM p) + { + long int trim = (long int) rde_stack_top (p->mark); + ENTER ("rde_param_i_ast_rewind"); + TRACE (("RDE_PARAM %p",p)); + rde_stack_trim (p->ast, (int) trim); + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_ast_push (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_ast_value_push (RDE_PARAM p) + { + ENTER ("rde_param_i_ast_value_push"); + TRACE (("RDE_PARAM %p",p)); + ASSERT(p->SV,"Unable to push undefined semantic value"); + TRACE (("rde_param_i_ast_value_push %p => (%p)", p, p->SV)); + TRACE (("SV = (%p rc%d '%s')", p->SV, p->SV->refCount, Tcl_GetString (p->SV))); + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + RETURNVOID; + } + static void + ast_node_free (void* n) + { + Tcl_DecrRefCount ((Tcl_Obj*) n); + } + SCOPE void + rde_param_i_error_clear (RDE_PARAM p) + { + ER_CLEAR (p); + } + SCOPE void + rde_param_i_error_nonterminal (RDE_PARAM p, int s) + { + + return; + long int pos; + if (!p->ER) return; + pos = 1 + (long int) rde_stack_top (p->LS); + if (p->ER->loc != pos) return; + error_set (p, s); + p->ER->loc = pos; + } + SCOPE void + rde_param_i_error_pop_merge (RDE_PARAM p) + { + ERROR_STATE* top = (ERROR_STATE*) rde_stack_top (p->ES); + + if (top == p->ER) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!top) { + rde_stack_pop (p->ES, 1); + return; + } + + if (!p->ER) { + rde_stack_drop (p->ES, 1); + p->ER = top; + + return; + } + + if (top->loc < p->ER->loc) { + rde_stack_pop (p->ES, 1); + return; + } + + if (top->loc > p->ER->loc) { + rde_stack_drop (p->ES, 1); + error_state_free (p->ER); + p->ER = top; + + return; + } + + rde_stack_move (p->ER->msg, top->msg); + rde_stack_pop (p->ES, 1); + } + SCOPE void + rde_param_i_error_push (RDE_PARAM p) + { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + static void + error_set (RDE_PARAM p, int s) + { + error_state_free (p->ER); + p->ER = ALLOC (ERROR_STATE); + p->ER->refCount = 1; + p->ER->loc = p->CL; + p->ER->msg = rde_stack_new (NULL); + ASSERT_BOUNDS(s,p->numstr); + rde_stack_push (p->ER->msg, (void*) s); + } + static void + error_state_free (void* esx) + { + ERROR_STATE* es = esx; + if (!es) return; + es->refCount --; + if (es->refCount > 0) return; + rde_stack_del (es->msg); + ckfree ((char*) es); + } + SCOPE void + rde_param_i_loc_pop_discard (RDE_PARAM p) + { + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_pop_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_loc_push (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + } + SCOPE void + rde_param_i_loc_rewind (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + } + SCOPE void + rde_param_i_input_next (RDE_PARAM p, int m) + { + int leni; + char* ch; + ASSERT_BOUNDS(m,p->numstr); + p->CL ++; + if (p->CL < rde_tc_size (p->TC)) { + + rde_tc_get (p->TC, p->CL, &p->CC, &p->CC_len); + ASSERT_BOUNDS (p->CC_len, TCL_UTF_MAX); + p->ST = 1; + ER_CLEAR (p); + return; + } + if (!p->IN || + Tcl_Eof (p->IN) || + (Tcl_ReadChars (p->IN, p->readbuf, 1, 0) <= 0)) { + + p->ST = 0; + error_set (p, m); + return; + } + + ch = Tcl_GetStringFromObj (p->readbuf, &leni); + ASSERT_BOUNDS (leni, TCL_UTF_MAX); + p->CC = rde_tc_append (p->TC, ch, leni); + p->CC_len = leni; + p->ST = 1; + ER_CLEAR (p); + } + SCOPE void + rde_param_i_status_fail (RDE_PARAM p) + { + p->ST = 0; + } + SCOPE void + rde_param_i_status_ok (RDE_PARAM p) + { + p->ST = 1; + } + SCOPE void + rde_param_i_status_negate (RDE_PARAM p) + { + p->ST = !p->ST; + } + SCOPE int + rde_param_i_symbol_restore (RDE_PARAM p, int s) + { + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + + hPtr = Tcl_FindHashEntry (&p->NC, (char*) p->CL); + if (!hPtr) { return 0; } + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + hPtr = Tcl_FindHashEntry (tablePtr, (char*) s); + if (!hPtr) { return 0; } + + scs = Tcl_GetHashValue (hPtr); + p->CL = scs->CL; + p->ST = scs->ST; + error_state_free (p->ER); + p->ER = scs->ER; + if (p->ER) { p->ER->refCount ++; } + TRACE (("SV_RESTORE (%p) '%s'",scs->SV, scs->SV ? Tcl_GetString (scs->SV):"")); + SV_SET (p, scs->SV); + return 1; + } + SCOPE void + rde_param_i_symbol_save (RDE_PARAM p, int s) + { + long int at = (long int) rde_stack_top (p->LS); + NC_STATE* scs; + Tcl_HashEntry* hPtr; + Tcl_HashTable* tablePtr; + int isnew; + ENTER ("rde_param_i_symbol_save"); + TRACE (("RDE_PARAM %p",p)); + TRACE (("INT %d",s)); + + hPtr = Tcl_CreateHashEntry (&p->NC, (char*) at, &isnew); + if (isnew) { + tablePtr = ALLOC (Tcl_HashTable); + Tcl_InitHashTable (tablePtr, TCL_ONE_WORD_KEYS); + Tcl_SetHashValue (hPtr, tablePtr); + } else { + tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); + } + hPtr = Tcl_CreateHashEntry (tablePtr, (char*) s, &isnew); + if (isnew) { + + scs = ALLOC (NC_STATE); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "")); + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + Tcl_SetHashValue (hPtr, scs); + } else { + + scs = (NC_STATE*) Tcl_GetHashValue (hPtr); + scs->CL = p->CL; + scs->ST = p->ST; + TRACE (("SV_CACHE/over (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "" )); + if (scs->SV) { Tcl_DecrRefCount (scs->SV); } + scs->SV = p->SV; + if (scs->SV) { Tcl_IncrRefCount (scs->SV); } + error_state_free (scs->ER); + scs->ER = p->ER; + if (scs->ER) { scs->ER->refCount ++; } + } + TRACE (("SV = (%p rc%d '%s')", + p->SV, + p->SV ? p->SV->refCount : -1, + p->SV ? Tcl_GetString (p->SV) : "")); + RETURNVOID; + } + SCOPE void + rde_param_i_test_alnum (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlnum, tc_alnum); + } + SCOPE void + rde_param_i_test_alpha (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsAlpha, tc_alpha); + } + SCOPE void + rde_param_i_test_ascii (RDE_PARAM p) + { + test_class (p, UniCharIsAscii, tc_ascii); + } + SCOPE void + rde_param_i_test_control (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsControl, tc_control); + } + SCOPE void + rde_param_i_test_char (RDE_PARAM p, const char* c, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = Tcl_UtfNcmp (p->CC, c, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_ddigit (RDE_PARAM p) + { + test_class (p, UniCharIsDecDigit, tc_ddigit); + } + SCOPE void + rde_param_i_test_digit (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsDigit, tc_digit); + } + SCOPE void + rde_param_i_test_graph (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsGraph, tc_graph); + } + SCOPE void + rde_param_i_test_lower (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsLower, tc_lower); + } + SCOPE void + rde_param_i_test_print (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPrint, tc_printable); + } + SCOPE void + rde_param_i_test_punct (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsPunct, tc_punct); + } + SCOPE void + rde_param_i_test_range (RDE_PARAM p, char* s, char* e, int msg) + { + ASSERT_BOUNDS(msg,p->numstr); + p->ST = + (Tcl_UtfNcmp (s, p->CC, 1) <= 0) && + (Tcl_UtfNcmp (p->CC, e, 1) <= 0); + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, msg); + p->CL --; + } + } + SCOPE void + rde_param_i_test_space (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsSpace, tc_space); + } + SCOPE void + rde_param_i_test_upper (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsUpper, tc_upper); + } + SCOPE void + rde_param_i_test_wordchar (RDE_PARAM p) + { + test_class (p, Tcl_UniCharIsWordChar, tc_wordchar); + } + SCOPE void + rde_param_i_test_xdigit (RDE_PARAM p) + { + test_class (p, UniCharIsHexDigit, tc_xdigit); + } + static void + test_class (RDE_PARAM p, UniCharClass class, test_class_id id) + { + Tcl_UniChar ch; + Tcl_UtfToUniChar(p->CC, &ch); + ASSERT_BOUNDS(id,p->numstr); + p->ST = !!class (ch); + + if (p->ST) { + ER_CLEAR (p); + } else { + error_set (p, id); + p->CL --; + } + } + static int + UniCharIsAscii (int character) + { + return (character >= 0) && (character < 0x80); + } + static int + UniCharIsHexDigit (int character) + { + return (character >= 0) && (character < 0x80) && isxdigit(character); + } + static int + UniCharIsDecDigit (int character) + { + return (character >= 0) && (character < 0x80) && isdigit(character); + } + SCOPE void + rde_param_i_value_clear (RDE_PARAM p) + { + SV_CLEAR (p); + } + SCOPE void + rde_param_i_value_leaf (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + Tcl_Obj* ov [3]; + long int pos = 1 + (long int) rde_stack_top (p->LS); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + newsv = Tcl_NewListObj (3, ov); + TRACE (("rde_param_i_value_leaf => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + } + SCOPE void + rde_param_i_value_reduce (RDE_PARAM p, int s) + { + Tcl_Obj* newsv; + int oc, i, j; + Tcl_Obj** ov; + long int ac; + Tcl_Obj** av; + long int pos = 1 + (long int) rde_stack_top (p->LS); + long int mark = (long int) rde_stack_top (p->mark); + long int asize = rde_stack_size (p->ast); + long int new = asize - mark; + ASSERT (new >= 0, "Bad number of elements to reduce"); + ov = NALLOC (3+new, Tcl_Obj*); + ASSERT_BOUNDS(s,p->numstr); + ov [0] = Tcl_NewStringObj (p->string[s], -1); + ov [1] = Tcl_NewIntObj (pos); + ov [2] = Tcl_NewIntObj (p->CL); + rde_stack_get (p->ast, &ac, (void***) &av); + for (i = 3, j = mark; j < asize; i++, j++) { + ASSERT_BOUNDS (i, 3+new); + ASSERT_BOUNDS (j, ac); + ov [i] = av [j]; + } + ASSERT (i == 3+new, "Reduction result incomplete"); + newsv = Tcl_NewListObj (3+new, ov); + TRACE (("rde_param_i_value_reduce => '%s'",Tcl_GetString (newsv))); + SV_SET (p, newsv); + ckfree ((char*) ov); + } + static int + er_int_compare (const void* a, const void* b) + { + long int ai = *((long int*) a); + long int bi = *((long int*) b); + if (ai < bi) { return -1; } + if (ai > bi) { return 1; } + return 0; + } + SCOPE int + rde_param_i_symbol_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) { + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + return 1; + } + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + return 0; + } + SCOPE int + rde_param_i_symbol_void_start_d (RDE_PARAM p, int s) + { + if (rde_param_i_symbol_restore (p, s)) return 1; + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + return 0; + } + SCOPE void + rde_param_i_symbol_done_d_reduce (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_reduce (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_d_leaf (RDE_PARAM p, int s, int m) + { + if (p->ST) { + rde_param_i_value_leaf (p, s); + } else { + SV_CLEAR (p); + } + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + if (p->ST) { + rde_stack_push (p->ast, p->SV); + Tcl_IncrRefCount (p->SV); + } + } + SCOPE void + rde_param_i_symbol_done_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_symbol_done_d_void (RDE_PARAM p, int s, int m) + { + SV_CLEAR (p); + rde_param_i_symbol_save (p, s); + rde_param_i_error_nonterminal (p, m); + rde_param_i_ast_pop_rewind (p); + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_next_char (RDE_PARAM p, char* c, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_char (p, c, m); + } + SCOPE void + rde_param_i_next_range (RDE_PARAM p, char* s, char* e, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_range (p, s, e, m); + } + SCOPE void + rde_param_i_next_alnum (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alnum (p); + } + SCOPE void + rde_param_i_next_alpha (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_alpha (p); + } + SCOPE void + rde_param_i_next_ascii (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ascii (p); + } + SCOPE void + rde_param_i_next_control (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_control (p); + } + SCOPE void + rde_param_i_next_ddigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_ddigit (p); + } + SCOPE void + rde_param_i_next_digit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_digit (p); + } + SCOPE void + rde_param_i_next_graph (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_graph (p); + } + SCOPE void + rde_param_i_next_lower (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_lower (p); + } + SCOPE void + rde_param_i_next_print (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_print (p); + } + SCOPE void + rde_param_i_next_punct (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_punct (p); + } + SCOPE void + rde_param_i_next_space (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_space (p); + } + SCOPE void + rde_param_i_next_upper (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_upper (p); + } + SCOPE void + rde_param_i_next_wordchar (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_wordchar (p); + } + SCOPE void + rde_param_i_next_xdigit (RDE_PARAM p, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + rde_param_i_test_xdigit (p); + } + SCOPE void + rde_param_i_notahead_start_d (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + } + SCOPE void + rde_param_i_notahead_exit_d (RDE_PARAM p) + { + if (p->ST) { + rde_param_i_ast_pop_rewind (p); + } else { + rde_stack_pop (p->mark, 1); + } + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_notahead_exit (RDE_PARAM p) + { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + p->ST = !p->ST; + } + SCOPE void + rde_param_i_state_push_2 (RDE_PARAM p) + { + + rde_stack_push (p->LS, (void*) p->CL); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + SCOPE void + rde_param_i_state_push_void (RDE_PARAM p) + { + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_push_value (RDE_PARAM p) + { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->LS, (void*) p->CL); + ER_CLEAR (p); + rde_stack_push (p->ES, p->ER); + + } + SCOPE void + rde_param_i_state_merge_ok (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + } + SCOPE void + rde_param_i_state_merge_value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (!p->ST) { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } + SCOPE int + rde_param_i_kleene_close (RDE_PARAM p) + { + int stop = !p->ST; + rde_param_i_error_pop_merge (p); + if (stop) { + p->ST = 1; + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_kleene_abort (RDE_PARAM p) + { + int stop = !p->ST; + if (stop) { + p->CL = (long int) rde_stack_top (p->LS); + } + rde_stack_pop (p->LS, 1); + return stop; + } + SCOPE int + rde_param_i_seq_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_seq_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + return 0; + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_pop (p->LS, 1); + return 1; + } + } + SCOPE int + rde_param_i_bra_void2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_void2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->LS, 1); + } else { + rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2void (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_pop (p->mark, 1); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE int + rde_param_i_bra_value2value (RDE_PARAM p) + { + rde_param_i_error_pop_merge (p); + if (p->ST) { + rde_stack_pop (p->mark, 1); + rde_stack_pop (p->LS, 1); + } else { + long int trim = (long int) rde_stack_top (p->mark); + rde_stack_trim (p->ast, (int) trim); + p->CL = (long int) rde_stack_top (p->LS); + rde_stack_push (p->ES, p->ER); + if (p->ER) { p->ER->refCount ++; } + } + return p->ST; + } + SCOPE void + rde_param_i_next_str (RDE_PARAM p, const char* str, int m) + { + int at = p->CL; + + while (*str) { + rde_param_i_input_next (p, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + rde_param_i_test_char (p, str, m); + if (!p->ST) { + p->ER->loc = at+1; + p->CL = at; + return; + } + str = Tcl_UtfNext (str); + } + } + SCOPE void + rde_param_i_next_class (RDE_PARAM p, const char* class, int m) + { + rde_param_i_input_next (p, m); + if (!p->ST) return; + while (*class) { + p->ST = Tcl_UtfNcmp (p->CC, class, 1) == 0; + if (p->ST) { + ER_CLEAR (p); + return; + } + class = Tcl_UtfNext (class); + } + error_set (p, m); + p->CL --; + } + + + /* + * Declaring the parse functions + */ + + static void ahead_3 (RDE_PARAM p); + static void sequence_6 (RDE_PARAM p); + static void sym_TEST (RDE_PARAM p); + + /* + * Precomputed table of strings (symbols, error messages, etc.). + */ + + static char const* p_string [17] = { + /* 0 = */ "alnum", + /* 1 = */ "alpha", + /* 2 = */ "ascii", + /* 3 = */ "control", + /* 4 = */ "ddigit", + /* 5 = */ "digit", + /* 6 = */ "graph", + /* 7 = */ "lower", + /* 8 = */ "print", + /* 9 = */ "punct", + /* 10 = */ "space", + /* 11 = */ "upper", + /* 12 = */ "wordchar", + /* 13 = */ "xdigit", + /* 14 = */ "t a", + /* 15 = */ "n TEST", + /* 16 = */ "TEST" + }; + + /* + * Grammar Start Expression + */ + + static void MAIN (RDE_PARAM p) { + sym_TEST (p); + return; + } + + /* + * value Symbol 'TEST' + */ + + static void sym_TEST (RDE_PARAM p) { + /* + * x + * & + * 'a' + * (IDENTIFIER) + */ + + if (rde_param_i_symbol_start (p, 16)) return ; + sequence_6 (p); + rde_param_i_symbol_done_leaf (p, 16, 15); + return; + } + + static void sequence_6 (RDE_PARAM p) { + /* + * x + * & + * 'a' + * (IDENTIFIER) + */ + + rde_param_i_state_push_void (p); + ahead_3 (p); + if (rde_param_i_seq_void2void(p)) return; + /* Undefined symbol 'IDENTIFIER' */; + rde_param_i_status_fail (p); + rde_param_i_state_merge_void (p); + return; + } + + static void ahead_3 (RDE_PARAM p) { + /* + * & + * 'a' + */ + + rde_param_i_loc_push (p); + rde_param_i_next_char (p, "a", 14); + rde_param_i_loc_pop_rewind (p); + return; + } + + /* -*- c -*- */ + + typedef struct PARSERg { + long int counter; + char buf [50]; + } PARSERg; + + static void + PARSERgRelease (ClientData cd, Tcl_Interp* interp) + { + ckfree((char*) cd); + } + + static const char* + PARSERnewName (Tcl_Interp* interp) + { +#define KEY "tcllib/parser/PACKAGE/TEA" + + Tcl_InterpDeleteProc* proc = PARSERgRelease; + PARSERg* parserg; + + parserg = Tcl_GetAssocData (interp, KEY, &proc); + if (parserg == NULL) { + parserg = (PARSERg*) ckalloc (sizeof (PARSERg)); + parserg->counter = 0; + + Tcl_SetAssocData (interp, KEY, proc, + (ClientData) parserg); + } + + parserg->counter ++; + sprintf (parserg->buf, "PARSER%d", parserg->counter); + return parserg->buf; +#undef KEY + } + + static void + PARSERdeleteCmd (ClientData clientData) + { + /* + * Release the whole PARSER + * (Low-level engine only actually). + */ + rde_param_del ((RDE_PARAM) clientData); + } + + + /* * ** *** ***** ******** ************* + ** Functions implementing the object methods, and helper. + */ + + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp); + + static int parser_PARSE (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + int mode; + Tcl_Channel chan; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "chan"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, + Tcl_GetString (objv[2]), + &mode); + + if (!chan) { + return TCL_ERROR; + } + + rde_param_reset (p, chan); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + static int parser_PARSET (RDE_PARAM p, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + char* buf; + int len; + + if (objc != 3) { + Tcl_WrongNumArgs (interp, 2, objv, "text"); + return TCL_ERROR; + } + + buf = Tcl_GetStringFromObj (objv[2], &len); + + rde_param_reset (p, NULL); + rde_param_data (p, buf, len); + MAIN (p) ; /* Entrypoint for the generated code. */ + return COMPLETE (p, interp); + } + + /* See also rde_critcl/m.c, param_COMPLETE() */ + static int COMPLETE (RDE_PARAM p, Tcl_Interp* interp) + { + if (rde_param_query_st (p)) { + long int ac; + Tcl_Obj** av; + + rde_param_query_ast (p, &ac, &av); + + if (ac > 1) { + Tcl_Obj** lv = NALLOC (3+ac, Tcl_Obj*); + + memcpy(lv + 3, av, ac * sizeof (Tcl_Obj*)); + lv [0] = Tcl_NewObj (); + lv [1] = Tcl_NewIntObj (1 + rde_param_query_lstop (p)); + lv [2] = Tcl_NewIntObj (rde_param_query_cl (p)); + + Tcl_SetObjResult (interp, Tcl_NewListObj (3, lv)); + ckfree ((char*) lv); + + } else if (ac == 0) { + /* + * Match, but no AST. This is possible if the grammar + * consists of only the start expression. + */ + Tcl_SetObjResult (interp, Tcl_NewStringObj ("",-1)); + } else { + Tcl_SetObjResult (interp, av [0]); + } + + return TCL_OK; + } else { + Tcl_Obj* xv [1]; + const ERROR_STATE* er = rde_param_query_er (p); + Tcl_Obj* res = rde_param_query_er_tcl (p, er); + /* res = list (location, list(msg)) */ + + /* Stick the exception type-tag before the existing elements */ + xv [0] = Tcl_NewStringObj ("pt::rde",-1); + Tcl_ListObjReplace(interp, res, 0, 0, 1, xv); + + Tcl_SetErrorCode (interp, "PT", "RDE", "SYNTAX", NULL); + Tcl_SetObjResult (interp, res); + return TCL_ERROR; + } + } + + + /* * ** *** ***** ******** ************* + ** Object command, method dispatch. + */ + static int parser_objcmd (ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST* objv) + { + RDE_PARAM p = (RDE_PARAM) cd; + int m, res; + + static CONST char* methods [] = { + "destroy", "parse", "parset", NULL + }; + enum methods { + M_DESTROY, M_PARSE, M_PARSET + }; + + if (objc < 2) { + Tcl_WrongNumArgs (interp, objc, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } else if (Tcl_GetIndexFromObj (interp, objv [1], methods, "option", + 0, &m) != TCL_OK) { + return TCL_ERROR; + } + + /* Dispatch to methods. They check the #args in + * detail before performing the requested + * functionality + */ + + switch (m) { + case M_DESTROY: + if (objc != 2) { + Tcl_WrongNumArgs (interp, 2, objv, NULL); + return TCL_ERROR; + } + + Tcl_DeleteCommandFromToken(interp, (Tcl_Command) rde_param_query_clientdata (p)); + return TCL_OK; + + case M_PARSE: res = parser_PARSE (p, interp, objc, objv); break; + case M_PARSET: res = parser_PARSET (p, interp, objc, objv); break; + default: + /* Not coming to this place */ + ASSERT (0,"Reached unreachable location"); + } + + return res; + } + + /** * ** *** ***** ******** ************* + * Class command, i.e. object construction. + */ + static int ParserClassCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const*objv) { + /* + * Syntax: No arguments beyond the name + */ + + RDE_PARAM parser; + CONST char* name; + Tcl_Obj* fqn; + Tcl_CmdInfo ci; + Tcl_Command c; + +#define USAGE "?name?" + + if ((objc != 2) && (objc != 1)) { + Tcl_WrongNumArgs (interp, 1, objv, USAGE); + return TCL_ERROR; + } + + if (objc < 2) { + name = PARSERnewName (interp); + } else { + name = Tcl_GetString (objv [1]); + } + + if (!Tcl_StringMatch (name, "::*")) { + /* Relative name. Prefix with current namespace */ + + Tcl_Eval (interp, "namespace current"); + fqn = Tcl_GetObjResult (interp); + fqn = Tcl_DuplicateObj (fqn); + Tcl_IncrRefCount (fqn); + + if (!Tcl_StringMatch (Tcl_GetString (fqn), "::")) { + Tcl_AppendToObj (fqn, "::", -1); + } + Tcl_AppendToObj (fqn, name, -1); + } else { + fqn = Tcl_NewStringObj (name, -1); + Tcl_IncrRefCount (fqn); + } + Tcl_ResetResult (interp); + + if (Tcl_GetCommandInfo (interp, + Tcl_GetString (fqn), + &ci)) { + Tcl_Obj* err; + + err = Tcl_NewObj (); + Tcl_AppendToObj (err, "command \"", -1); + Tcl_AppendObjToObj (err, fqn); + Tcl_AppendToObj (err, "\" already exists", -1); + + Tcl_DecrRefCount (fqn); + Tcl_SetObjResult (interp, err); + return TCL_ERROR; + } + + parser = rde_param_new (sizeof(p_string)/sizeof(char*), (char**) p_string); + c = Tcl_CreateObjCommand (interp, Tcl_GetString (fqn), + parser_objcmd, (ClientData) parser, + PARSERdeleteCmd); + rde_param_clientdata (parser, (ClientData) c); + Tcl_SetObjResult (interp, fqn); + Tcl_DecrRefCount (fqn); + return TCL_OK; + } + +int Package_Init(Tcl_Interp* interp) { + if (interp == 0) return TCL_ERROR; + + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + + if (Tcl_CreateObjCommand(interp, "PARSER", ParserClassCmd , NULL, NULL) == NULL) { + Tcl_SetResult(interp, "Can't create constructor", NULL); + return TCL_ERROR; + } + + + Tcl_PkgProvide(interp, "PACKAGE", "0.1"); + + return TCL_OK; +} Index: modules/pt/tests/pt_cparam_config_critcl.tests ================================================================== --- modules/pt/tests/pt_cparam_config_critcl.tests +++ modules/pt/tests/pt_cparam_config_critcl.tests @@ -25,11 +25,11 @@ # TODO :: Tests missing for: configure/cget, reset # ------------------------------------------------------------------------- -# Testing the generation of tcl/param output configured for critcl. +# Testing the generation of c/param output configured for critcl. TestFilesProcess $mytestdir ok peg_serial-canonical peg_cparam-critcl -> n label input data expected { test pt-cparam-config-critcl-3.$n "pt::cparam::configuration::critcl, $label, ok :- $input" -setup { pt::peg::to::cparam reset ADDED modules/pt/tests/pt_cparam_config_tea.tests Index: modules/pt/tests/pt_cparam_config_tea.tests ================================================================== --- /dev/null +++ modules/pt/tests/pt_cparam_config_tea.tests @@ -0,0 +1,52 @@ +# -*- tcl -*- +# General set of error cases regarding the number of arguments. + +test pt-cparam-config-tea-1.0 {convert, wrong#args} -body { + pt::cparam::configuration::tea def +} -returnCodes error -result {wrong # args: should be "pt::cparam::configuration::tea def class pkg version cmd"} + +test pt-cparam-config-tea-1.1 {convert, wrong#args} -body { + pt::cparam::configuration::tea def C +} -returnCodes error -result {wrong # args: should be "pt::cparam::configuration::tea def class pkg version cmd"} + +test pt-cparam-config-tea-1.2 {convert, wrong#args} -body { + pt::cparam::configuration::tea def C P +} -returnCodes error -result {wrong # args: should be "pt::cparam::configuration::tea def class pkg version cmd"} + +test pt-cparam-config-tea-1.3 {convert, wrong#args} -body { + pt::cparam::configuration::tea def C P V +} -returnCodes error -result {wrong # args: should be "pt::cparam::configuration::tea def class pkg version cmd"} + +test pt-cparam-config-tea-2.0 {reset, wrong#args} -body { + pt::cparam::configuration::tea def C P V C XXX +} -returnCodes error -result {wrong # args: should be "pt::cparam::configuration::tea def class pkg version cmd"} + +# ------------------------------------------------------------------------- + +# TODO :: Tests missing for: configure/cget, reset + +# ------------------------------------------------------------------------- + +# Testing the generation of c/param output configured for tea. + +TestFilesProcess $mytestdir ok peg_serial-canonical peg_cparam-tea -> n label input data expected { + test pt-cparam-config-tea-3.$n "pt::cparam::configuration::tea, $label, ok :- $input" -setup { + + pt::peg::to::cparam reset + pt::peg::to::cparam configure -name TEMPLATE + pt::peg::to::cparam configure -file TEST + + pt::cparam::configuration::tea def \ + PARSER PACKAGE 1 \ + {pt::peg::to::cparam configure} + + } -body { + pt::peg::to::cparam convert $data + } -cleanup { + pt::peg::to::cparam reset + } -result $expected +} + + +#---------------------------------------------------------------------- +unset n label input data expected Index: support/devel/sak/doc/kwic.txt ================================================================== --- support/devel/sak/doc/kwic.txt +++ support/devel/sak/doc/kwic.txt @@ -427,10 +427,11 @@ [manpage modules/grammar_peg/peg.man grammar::peg] [manpage modules/grammar_peg/peg_interp.man grammar::peg::interp] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -858,10 +859,11 @@ [manpage modules/grammar_aycock/aycock.man grammar::aycock] [key EBNF] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -1003,10 +1005,11 @@ [manpage modules/grammar_peg/peg.man grammar::peg] [manpage modules/grammar_peg/peg_interp.man grammar::peg::interp] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -1226,10 +1229,11 @@ [manpage modules/grammar_peg/peg.man grammar::peg] [manpage modules/grammar_peg/peg_interp.man grammar::peg::interp] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -1621,10 +1625,11 @@ [manpage modules/grammar_peg/peg.man grammar::peg] [manpage modules/grammar_peg/peg_interp.man grammar::peg::interp] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -1779,10 +1784,11 @@ [manpage modules/grammar_me/me_intro.man grammar::me_intro] [manpage modules/grammar_peg/peg_interp.man grammar::peg::interp] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -2101,10 +2107,11 @@ [manpage modules/doctools2toc/toc_parse.man doctools::toc::parse] [manpage modules/grammar_aycock/aycock.man grammar::aycock] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -2181,10 +2188,11 @@ [manpage modules/grammar_peg/peg.man grammar::peg] [manpage modules/grammar_peg/peg_interp.man grammar::peg::interp] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -2227,10 +2235,11 @@ [manpage modules/grammar_peg/peg_interp.man grammar::peg::interp] [manpage modules/page/page_util_peg.man page_util_peg] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -2286,10 +2295,11 @@ [manpage modules/page/page_util_norm_peg.man page_util_norm_peg] [manpage modules/page/page_util_peg.man page_util_peg] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -2436,10 +2446,11 @@ [manpage modules/grammar_peg/peg.man grammar::peg] [manpage modules/grammar_peg/peg_interp.man grammar::peg::interp] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -2524,10 +2535,11 @@ [manpage modules/grammar_peg/peg.man grammar::peg] [manpage modules/grammar_peg/peg_interp.man grammar::peg::interp] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -2957,10 +2969,11 @@ [manpage modules/grammar_peg/peg.man grammar::peg] [manpage modules/grammar_peg/peg_interp.man grammar::peg::interp] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -3120,10 +3133,11 @@ [manpage modules/grammar_peg/peg.man grammar::peg] [manpage modules/grammar_peg/peg_interp.man grammar::peg::interp] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -3338,10 +3352,11 @@ [manpage modules/grammar_peg/peg.man grammar::peg] [manpage modules/grammar_peg/peg_interp.man grammar::peg::interp] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] @@ -3399,10 +3414,11 @@ [manpage modules/grammar_peg/peg.man grammar::peg] [manpage modules/grammar_peg/peg_interp.man grammar::peg::interp] [manpage apps/pt.man pt] [manpage modules/pt/pt_astree.man pt::ast] [manpage modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl] +[manpage modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea] [manpage modules/pt/pt_json_language.man pt::json_language] [manpage modules/pt/pt_param.man pt::param] [manpage modules/pt/pt_pexpression.man pt::pe] [manpage modules/pt/pt_pexpr_op.man pt::pe::op] [manpage modules/pt/pt_pegrammar.man pt::peg] Index: support/devel/sak/doc/manpages.txt ================================================================== --- support/devel/sak/doc/manpages.txt +++ support/devel/sak/doc/manpages.txt @@ -232,10 +232,11 @@ modules/pop3d/pop3d_dbox.man modules/pop3d/pop3d_udb.man modules/profiler/profiler.man modules/pt/pt_astree.man modules/pt/pt_cparam_config_critcl.man +modules/pt/pt_cparam_config_tea.man modules/pt/pt_from_api.man modules/pt/pt_introduction.man modules/pt/pt_json_language.man modules/pt/pt_param.man modules/pt/pt_parse_peg.man Index: support/devel/sak/doc/toc.txt ================================================================== --- support/devel/sak/doc/toc.txt +++ support/devel/sak/doc/toc.txt @@ -270,10 +270,11 @@ [division_end] [division_start {Parsing and Grammars}] [item apps/pt.man pt {Parser Tools Application}] [item modules/pt/pt_astree.man pt::ast {Abstract Syntax Tree Serialization}] [item modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl {C/PARAM, Canned configuration, Critcl}] +[item modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea {C/PARAM, Canned configuration, TEA}] [item modules/pt/pt_json_language.man pt::json_language {The JSON Grammar Exchange Format}] [item modules/pt/pt_param.man pt::param {PackRat Machine Specification}] [item modules/pt/pt_pexpression.man pt::pe {Parsing Expression Serialization}] [item modules/pt/pt_pexpr_op.man pt::pe::op {Parsing Expression Utilities}] [item modules/pt/pt_pegrammar.man pt::peg {Parsing Expression Grammar Serialization}] @@ -851,10 +852,11 @@ [item modules/profiler/profiler.man profiler {Tcl source code profiler}] [division_end] [division_start pt] [item modules/pt/pt_astree.man pt::ast {Abstract Syntax Tree Serialization}] [item modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl {C/PARAM, Canned configuration, Critcl}] +[item modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea {C/PARAM, Canned configuration, TEA}] [item modules/pt/pt_json_language.man pt::json_language {The JSON Grammar Exchange Format}] [item modules/pt/pt_param.man pt::param {PackRat Machine Specification}] [item modules/pt/pt_pexpression.man pt::pe {Parsing Expression Serialization}] [item modules/pt/pt_pexpr_op.man pt::pe::op {Parsing Expression Utilities}] [item modules/pt/pt_pegrammar.man pt::peg {Parsing Expression Grammar Serialization}] Index: support/devel/sak/doc/toc_cats.txt ================================================================== --- support/devel/sak/doc/toc_cats.txt +++ support/devel/sak/doc/toc_cats.txt @@ -270,10 +270,11 @@ [division_end] [division_start {Parsing and Grammars}] [item apps/pt.man pt {Parser Tools Application}] [item modules/pt/pt_astree.man pt::ast {Abstract Syntax Tree Serialization}] [item modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl {C/PARAM, Canned configuration, Critcl}] +[item modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea {C/PARAM, Canned configuration, TEA}] [item modules/pt/pt_json_language.man pt::json_language {The JSON Grammar Exchange Format}] [item modules/pt/pt_param.man pt::param {PackRat Machine Specification}] [item modules/pt/pt_pexpression.man pt::pe {Parsing Expression Serialization}] [item modules/pt/pt_pexpr_op.man pt::pe::op {Parsing Expression Utilities}] [item modules/pt/pt_pegrammar.man pt::peg {Parsing Expression Grammar Serialization}] Index: support/devel/sak/doc/toc_mods.txt ================================================================== --- support/devel/sak/doc/toc_mods.txt +++ support/devel/sak/doc/toc_mods.txt @@ -380,10 +380,11 @@ [item modules/profiler/profiler.man profiler {Tcl source code profiler}] [division_end] [division_start pt] [item modules/pt/pt_astree.man pt::ast {Abstract Syntax Tree Serialization}] [item modules/pt/pt_cparam_config_critcl.man pt::cparam::configuration::critcl {C/PARAM, Canned configuration, Critcl}] +[item modules/pt/pt_cparam_config_tea.man pt::cparam::configuration::tea {C/PARAM, Canned configuration, TEA}] [item modules/pt/pt_json_language.man pt::json_language {The JSON Grammar Exchange Format}] [item modules/pt/pt_param.man pt::param {PackRat Machine Specification}] [item modules/pt/pt_pexpression.man pt::pe {Parsing Expression Serialization}] [item modules/pt/pt_pexpr_op.man pt::pe::op {Parsing Expression Utilities}] [item modules/pt/pt_pegrammar.man pt::peg {Parsing Expression Grammar Serialization}]