用于解析 PHP 类语言的语法,以便它可以处理语法中的 PHP 开始和结束标记(“<?”和“?>”)
Grammar for parsing PHP like language such that it can handle the PHP begin and end tokens ("<?" and "?>") in the grammar
我试图理解如何定义类似 PHP 的语法。在 PHP 中,可以退出 PHP 模式进入 HTML 模式,然后返回 PHP 模式。
为了问这个问题,我正在定义我的 PHP-like 语言
简单得可笑。在下面这个问题的剩余部分中,这种语言将被称为 "PHP-like"。
它只包含一个构造:if (expression) { block_list }
,即
if 语句。 block_list 是一系列嵌套的 if 语句,
表达式或 HTMLs。同样,为了使语言简单得可笑,一个
表达式必须是标识符。
这是一个示例,显示了该语言的有效代码。这里 HTML 后面跟着两个嵌套的 if 语句,后面跟着另一个 HTML.
<body><p>Some HTML text here</p>
<?
if (expression1) {
if (expression2) {
expression3
}
}
?>
</p>Some more HTML text here</p></body>
这是另一个例子,展示了我们如何在 if 语句中摆脱 PHP 模式进入 HTML 模式。
<? if (expression1) { ?>
some html here
<? if (expession2) { ?>
some html here
<? }
}
?>
为了实现这一点,我有一个可以识别以下标记的词法分析器。
HTML = All characters from the beginning of the code or the last
occurrence of "?>" to the end of the code or the next
occurrence of "<?". Zero length string is allowed.
IDENTIFIER = [_a-zA-Z][_a-zA-Z0-9]* i.e. C identifier, a sequence
of underscores, letters and
digits such that the first
character is not a digit.
WHITESPACE = [ \t\r\n]+ i.e. a sequence of spaces, tabs
and newlines.
BEGIN = "<?"
END = "?>"
IF = "if"
LPAREN = "("
RPAREN = ")"
LBRACE = "{"
RBRACE = "}"
词法分析器将 HTML 的每个块(即 PHP-like 模式之外的东西)输出为一个标记,即整个 HTML 块是一个标记。它不输出空白。它不会在每个类似 PHP 的模式中输出开始 <?
和结束 ?>
,即它不会输出第一次出现的 BEGIN 和下一次出现的 END。一旦到达 END,其后的任何内容都会再次被解析为 HTML,直到下一次出现 BEGIN。
因此,对于这个问题中的第二个代码示例,词法分析器输出这个。
代码:
<? if (expression1) { ?>
some html here
<? if (expession2) { ?>
some html here
<? }
}
?>
词法分析器输出:
HTML ""
IF "if"
LPAREN "("
IDENTIFIER "expression1"
RPAREN ")"
LBRACE "{"
HTML "\n some html here\n"
IF "if"
LPAREN "("
...
不输出 BEGIN 和 END 标记使解析器语法简单。现在我可以使用以下语法解析这些标记。由于解析器不必处理 BEGIN 和 END 标记,因此不必在语法中的任何地方提及它们。它使语法简单。
block_list = block | block_list block;
block = HTML | if_statement | expression;
if_statement = IF LPAREN expression RPAREN LBRACE block_list RBRACE;
expression = IDENTIFIER;
但是,比方说,我想在词法分析器中输出 BEGIN 和 END 标记。有没有一种为它编写语法的好方法,以便它处理嵌套的 if 语句,这些语句中也可能包含 HTML?
我正在尝试使用以下语法处理词法分析器输出中存在的 BEGIN 和 END 标记,但我无法想出一个有效的语法。
block_list = block | block_list block;
block = HTML | php_like | code;
php_like = BEGIN code | BEGIN code END;
code = if_statement | expression;
if_statement = IF LPAREN expression RPAREN LBRACE block_list RBRACE |
IF LPAREN expression RPAREN LBRACE END block_list RBRACE |
IF LPAREN expression RPAREN LBRACE END block_list BEGIN RBRACE
expression = IDENTIFIER;
上述语法允许本题中的上述代码示例。但它也允许以下无效代码。
<?
if (expression1) {
<? expression2
}
?>
我有两个问题。
- 如果词法分析器输出 BEGIN 和 END 标记,我该如何编写语法来处理它们?
- 是否最好不要输出 BEGIN 和 END 标记,以便语法保持简单?
假设您的词法分析器继续是有状态的,因此将为 END
和 BEGIN
之间的文本发出单个 HTML
标记,语法上几乎没有区别.
除了第一个和最后一个 HTML
标记外,其他每个 HTML
个标记都将在 END
之前,然后是 BEGIN
。换句话说,我们有:
html: END HTML BEGIN;
稍微有点复杂的是我们需要处理第一个和最后一个 HTML
个标记,这意味着我们需要一个新的非终结符(这将是开始符号):
program: HTML BEGIN block_list END HTML;
除了 HTML
变为 html
:
之外,其余语法与原始语法相同
block_list = block | block_list block;
block = html /* Change is here */ | if_statement | expression;
if_statement = IF LPAREN expression RPAREN LBRACE block_list RBRACE;
expression = IDENTIFIER;
如果您的新词法分析器在关联文本为空字符串的情况下不再发出 HTML
个标记,则需要一些替代规则:
program: leading_html block_list trailing_html;
leading_html: HTML BEGIN | BEGIN;
trailing_html: END HTML | END;
html: END HTML BEGIN | END BEGIN;
/* Remainder as above */
我试图理解如何定义类似 PHP 的语法。在 PHP 中,可以退出 PHP 模式进入 HTML 模式,然后返回 PHP 模式。
为了问这个问题,我正在定义我的 PHP-like 语言 简单得可笑。在下面这个问题的剩余部分中,这种语言将被称为 "PHP-like"。
它只包含一个构造:if (expression) { block_list }
,即
if 语句。 block_list 是一系列嵌套的 if 语句,
表达式或 HTMLs。同样,为了使语言简单得可笑,一个
表达式必须是标识符。
这是一个示例,显示了该语言的有效代码。这里 HTML 后面跟着两个嵌套的 if 语句,后面跟着另一个 HTML.
<body><p>Some HTML text here</p>
<?
if (expression1) {
if (expression2) {
expression3
}
}
?>
</p>Some more HTML text here</p></body>
这是另一个例子,展示了我们如何在 if 语句中摆脱 PHP 模式进入 HTML 模式。
<? if (expression1) { ?>
some html here
<? if (expession2) { ?>
some html here
<? }
}
?>
为了实现这一点,我有一个可以识别以下标记的词法分析器。
HTML = All characters from the beginning of the code or the last
occurrence of "?>" to the end of the code or the next
occurrence of "<?". Zero length string is allowed.
IDENTIFIER = [_a-zA-Z][_a-zA-Z0-9]* i.e. C identifier, a sequence
of underscores, letters and
digits such that the first
character is not a digit.
WHITESPACE = [ \t\r\n]+ i.e. a sequence of spaces, tabs
and newlines.
BEGIN = "<?"
END = "?>"
IF = "if"
LPAREN = "("
RPAREN = ")"
LBRACE = "{"
RBRACE = "}"
词法分析器将 HTML 的每个块(即 PHP-like 模式之外的东西)输出为一个标记,即整个 HTML 块是一个标记。它不输出空白。它不会在每个类似 PHP 的模式中输出开始 <?
和结束 ?>
,即它不会输出第一次出现的 BEGIN 和下一次出现的 END。一旦到达 END,其后的任何内容都会再次被解析为 HTML,直到下一次出现 BEGIN。
因此,对于这个问题中的第二个代码示例,词法分析器输出这个。
代码:
<? if (expression1) { ?>
some html here
<? if (expession2) { ?>
some html here
<? }
}
?>
词法分析器输出:
HTML ""
IF "if"
LPAREN "("
IDENTIFIER "expression1"
RPAREN ")"
LBRACE "{"
HTML "\n some html here\n"
IF "if"
LPAREN "("
...
不输出 BEGIN 和 END 标记使解析器语法简单。现在我可以使用以下语法解析这些标记。由于解析器不必处理 BEGIN 和 END 标记,因此不必在语法中的任何地方提及它们。它使语法简单。
block_list = block | block_list block;
block = HTML | if_statement | expression;
if_statement = IF LPAREN expression RPAREN LBRACE block_list RBRACE;
expression = IDENTIFIER;
但是,比方说,我想在词法分析器中输出 BEGIN 和 END 标记。有没有一种为它编写语法的好方法,以便它处理嵌套的 if 语句,这些语句中也可能包含 HTML?
我正在尝试使用以下语法处理词法分析器输出中存在的 BEGIN 和 END 标记,但我无法想出一个有效的语法。
block_list = block | block_list block;
block = HTML | php_like | code;
php_like = BEGIN code | BEGIN code END;
code = if_statement | expression;
if_statement = IF LPAREN expression RPAREN LBRACE block_list RBRACE |
IF LPAREN expression RPAREN LBRACE END block_list RBRACE |
IF LPAREN expression RPAREN LBRACE END block_list BEGIN RBRACE
expression = IDENTIFIER;
上述语法允许本题中的上述代码示例。但它也允许以下无效代码。
<?
if (expression1) {
<? expression2
}
?>
我有两个问题。
- 如果词法分析器输出 BEGIN 和 END 标记,我该如何编写语法来处理它们?
- 是否最好不要输出 BEGIN 和 END 标记,以便语法保持简单?
假设您的词法分析器继续是有状态的,因此将为 END
和 BEGIN
之间的文本发出单个 HTML
标记,语法上几乎没有区别.
除了第一个和最后一个 HTML
标记外,其他每个 HTML
个标记都将在 END
之前,然后是 BEGIN
。换句话说,我们有:
html: END HTML BEGIN;
稍微有点复杂的是我们需要处理第一个和最后一个 HTML
个标记,这意味着我们需要一个新的非终结符(这将是开始符号):
program: HTML BEGIN block_list END HTML;
除了 HTML
变为 html
:
block_list = block | block_list block;
block = html /* Change is here */ | if_statement | expression;
if_statement = IF LPAREN expression RPAREN LBRACE block_list RBRACE;
expression = IDENTIFIER;
如果您的新词法分析器在关联文本为空字符串的情况下不再发出 HTML
个标记,则需要一些替代规则:
program: leading_html block_list trailing_html;
leading_html: HTML BEGIN | BEGIN;
trailing_html: END HTML | END;
html: END HTML BEGIN | END BEGIN;
/* Remainder as above */