📄 parser.cpp
字号:
publicid,
systemid ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
return 0;
}
int
ACEXML_Parser::parse_external_id_and_ref (ACEXML_Char *&publicId,
ACEXML_Char *&systemId ACEXML_ENV_ARG_DECL)
{
publicId = systemId = 0;
ACEXML_Char nextch = this->get ();
switch (nextch)
{
case 'S': // External SYSTEM id.
if (this->parse_token (ACE_TEXT ("YSTEM")) < 0 ||
this->skip_whitespace_count () == 0)
{
this->report_fatal_error(ACE_TEXT("Expecting keyword 'SYSTEM'") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
if (this->get_quoted_string (systemId) != 0)
{
this->report_fatal_error(ACE_TEXT("Error while parsing SYSTEM literal for SYSTEM id.") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
this->locator_.setSystemId (systemId);
break;
case 'P': // External PUBLIC id or previously defined PUBLIC id.
if (this->parse_token (ACE_TEXT ("UBLIC")) < 0 ||
this->skip_whitespace_count () == 0)
{
this->report_fatal_error(ACE_TEXT("Expecting keyword 'PUBLIC'") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
if (this->get_quoted_string (publicId) != 0)
{
this->report_fatal_error(ACE_TEXT("Error while parsing public literal for PUBLIC id.") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
this->locator_.setPublicId (publicId);
this->skip_whitespace_count (&nextch);
if (nextch == '\'' || nextch == '"') // not end of NOTATION yet.
{
if (this->get_quoted_string (systemId) != 0)
{
this->report_fatal_error(ACE_TEXT("Error while parsing system literal for PUBLIC id.") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
this->locator_.setSystemId (systemId);
}
break;
default:
this->report_fatal_error(ACE_TEXT("Expecting either keyword `SYSTEM' or `PUBLIC'.") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
return 0;
}
int
ACEXML_Parser::parse_children_definition (ACEXML_ENV_SINGLE_ARG_DECL)
{
this->get (); // consume the '('
ACEXML_Char nextch;
int subelement_number = 0;
this->skip_whitespace_count (&nextch);
switch (nextch)
{
case '#': // Mixed element,
if (this->parse_token (ACE_TEXT ("#PCDATA")) < 0)
{
this->report_fatal_error(ACE_TEXT("Expecting keyword `#PCDATA' while defining an element.") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
this->skip_whitespace_count (&nextch);
while (nextch != ')')
{
if (this->get () != '|')
{
this->report_fatal_error(ACE_TEXT("Expecting end of Mixed section while defining an element.") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
this->skip_whitespace_count ();
ACEXML_Char *name = this->read_name ();
// @@ name will be used in the Validator later.
ACE_UNUSED_ARG (name);
++subelement_number;
// @@ Install Mixed element name into the validator.
this->skip_whitespace_count (&nextch);
}
if (this->get () != ')' ||
(subelement_number && this->get () != '*'))
{
this->report_fatal_error(ACE_TEXT("Expecting closing `)*' or ')' while defining an element.") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
// @@ close the element definition in the validator.
break;
default:
int status = this->parse_child (1 ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
if (status != 0)
return -1;
}
return 0;
}
int
ACEXML_Parser::parse_child (int skip_open_paren ACEXML_ENV_ARG_DECL)
{
// Conditionally consume the open paren.
if (skip_open_paren == 0 &&
this->get () != '(')
{
this->report_fatal_error(ACE_TEXT("Expecting opening `(' while defining an element.") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
ACEXML_Char node_type = 0;
ACEXML_Char nextch;
do {
this->skip_whitespace_count (&nextch);
switch (nextch)
{
case '(':
this->parse_child (0 ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK_RETURN (-1);
break;
default:
// must be an element name here.
ACEXML_Char *subelement = this->read_name ();
if (subelement == 0)
{
this->report_fatal_error(ACE_TEXT("Error reading sub-element name while defining an element.") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
// @@ Inform validator of the new element here.
break;
}
this->skip_whitespace_count (&nextch);
switch (nextch)
{
case '|':
switch (node_type)
{
case 0:
node_type = '|';
// @@ inform validator of this new type??
break;
case '|':
break;
default:
this->report_fatal_error(ACE_TEXT("Expecting `,', `|', or `)' while defining an element.") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
break;
case ',':
switch (node_type)
{
case 0:
node_type = ',';
// @@ inform validator of this new type??
break;
case ',':
break;
default:
this->report_fatal_error(ACE_TEXT("Expecting `,', `|', or `)'while defining an element.") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
case ')':
break;
default:
this->report_fatal_error(ACE_TEXT("Expecting `,', `|', or `)' while defining an element.") ACEXML_ENV_ARG_PARAMETER);
return -1;
}
this->get (); // consume , | or )
} while (nextch != ')');
// Check for trailing '?', '*', '+'
nextch = this->peek ();
switch (nextch)
{
case '?':
// @@ Consume the character and inform validator as such,
this->get ();
break;
case '*':
// @@ Consume the character and inform validator as such,
this->get ();
break;
case '+':
// @@ Consume the character and inform validator as such,
this->get ();
break;
default:
break; // not much to do.
}
return 0;
}
ACEXML_Char
ACEXML_Parser::skip_whitespace (ACEXML_Char **whitespace)
{
ACEXML_Char ch = this->get ();
if (this->is_whitespace (ch) == 0)
{
if (whitespace != 0)
*whitespace = 0;
return ch;
}
do
{
if (whitespace != 0)
this->obstack_.grow (ch);
ch = this->get ();
}
while (this->is_whitespace (ch));
if (whitespace != 0)
*whitespace = this->obstack_.freeze ();
return ch;
}
int
ACEXML_Parser::skip_whitespace_count (ACEXML_Char *peeky)
{
int wscount = 0;
ACEXML_Char dummy;
ACEXML_Char &forward = (peeky == 0 ? dummy : *peeky);
for (;this->is_whitespace ((forward = this->peek ())); ++wscount)
this->get ();
return wscount;
}
int
ACEXML_Parser::parse_token (const ACEXML_Char* keyword)
{
if (keyword == 0)
return -1;
const ACEXML_Char* ptr = keyword;
ACEXML_Char ch;
for (; *ptr != 0 && ((ch = this->get()) == *ptr); ++ptr)
{
// ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ch = %c : ptr = %c"), ch, *ptr));
}
if (*ptr == 0)
return 0;
else
return -1;
}
int
ACEXML_Parser::skip_equal (void)
{
if (this->skip_whitespace (0) != '=')
return -1;
while (this->is_whitespace (this->peek ()))
this->get ();
return 0;
}
int
ACEXML_Parser::get_quoted_string (ACEXML_Char *&str)
{
ACEXML_Char quote = this->get ();
if (quote != '\'' && quote != '"') // Not a quoted string.
return -1;
while (1)
{
ACEXML_Char ch = this->get ();
// @@ Deoes not handle buffer overflow yet.
if (ch == quote)
{
str = this->obstack_.freeze ();
return 0;
}
const ACEXML_String *replace = 0;
ACEXML_String charval;
ACEXML_Char buffer[6];
size_t i = 0;
switch (ch)
{
case '&':
if (this->peek () == '#')
{
if (this->parse_char_reference (buffer, 6) != 0)
{
// xmlenv.exception (new ACEXML_SAXParseException
// (ACE_TEXT ("CharRef does not resolves to a valid character")));
return -1;
}
charval.set (buffer, 0);
replace = &charval;
}
else
replace = this->parse_reference ();
if (replace == 0)
{
// xmlenv.exception (new ACEXML_SAXParseException
// (ACE_TEXT ("Undefined reference")));
return -1;
}
for (i = 0; i < replace->length (); ++i)
this->obstack_.grow ((*replace)[i]);
// handle reference here.
break;
case 0x0D: // End-of-Line handling
ch = (this->peek () == 0x0A ? this->get () : 0x0A);
// Fall thru...
case 0x0A:
// Fall thru...
default:
this->obstack_.grow (ch);
break;
}
}
}
ACEXML_Char *
ACEXML_Parser::read_name (ACEXML_Char ch)
{
if (ch == 0)
{
ch = this->get ();
if (this->is_whitespace (ch))
// No white space is allowed here.
return 0;
}
else if (this->is_nonname (ch))
return 0;
while (1)
{
this->obstack_.grow (ch);
ch = this->peek ();
if (this->is_nonname (ch))
break;
ch = this->get ();
};
return this->obstack_.freeze ();
}
void
ACEXML_Parser::report_prefix_mapping (const ACEXML_Char* prefix,
const ACEXML_Char* uri,
const ACEXML_Char* name,
int start ACEXML_ENV_ARG_DECL)
{
if (this->namespaces_)
{
const ACEXML_Char* temp = (name == 0) ? empty_string : prefix;
if (start) {
this->content_handler_->startPrefixMapping (temp, uri ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK;
}
else
{
this->content_handler_->endPrefixMapping(temp ACEXML_ENV_ARG_PARAMETER);
ACEXML_CHECK;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -