php-parser/internal/scanner/scanner.rl

506 lines
28 KiB
Plaintext
Raw Normal View History

2019-03-10 21:37:01 +00:00
package scanner
import (
"fmt"
"strconv"
"strings"
2019-03-10 21:37:01 +00:00
)
%%{
machine lexer;
write data;
access lex.;
variable p lex.p;
variable pe lex.pe;
}%%
func initLexer(lex *Lexer) {
2019-03-10 21:37:01 +00:00
%% write init;
}
func (lex *Lexer) Lex() *Token {
lex.hiddenTokens = nil
2019-03-10 21:37:01 +00:00
eof := lex.pe
var tok TokenID
token := lex.tokenPool.Get()
token.Hidden = nil
2020-05-12 21:16:36 +00:00
token.Value = lex.data[0:0]
2019-12-21 12:44:25 +00:00
2019-03-10 21:37:01 +00:00
lblStart := 0
lblEnd := 0
_, _ = lblStart, lblEnd
%%{
action heredoc_lbl_start {lblStart = lex.p}
action heredoc_lbl_end {lblEnd = lex.p}
2019-06-07 06:33:35 +00:00
action constant_string_new_line {
if lex.data[lex.p] == '\n' {
lex.newLines.Append(lex.p)
2019-06-07 06:33:35 +00:00
}
if lex.data[lex.p] == '\r' && lex.data[lex.p+1] != '\n' {
lex.newLines.Append(lex.p)
2019-06-07 06:33:35 +00:00
}
}
2019-03-10 21:37:01 +00:00
action is_not_heredoc_end { lex.isNotHeredocEnd(lex.p) }
action is_not_comment_end { lex.isNotPhpCloseToken() && lex.isNotNewLine() }
action is_not_heredoc_end_or_var { lex.isNotHeredocEnd(lex.p) && lex.isNotStringVar() }
action is_not_string_end_or_var { lex.isNotStringEnd('"') && lex.isNotStringVar() }
action is_not_backqoute_end_or_var { lex.isNotStringEnd('`') && lex.isNotStringVar() }
newline = ('\r\n' >(nl, 1) | '\r' >(nl, 0) | '\n' >(nl, 0)) %{lex.newLines.Append(lex.p);};
2019-03-10 21:37:01 +00:00
any_line = any | newline;
whitespace = [\t\v\f ];
whitespace_line = [\t\v\f ] | newline;
lnum = [0-9]+('_'[0-9]+)*;
dnum = (lnum?"." lnum)|(lnum"."lnum?);
hnum = '0x'[0-9a-fA-F]+('_'[0-9a-fA-F]+)*;
bnum = '0b'[01]+('_'[01]+)*;
2019-03-10 21:37:01 +00:00
exponent_dnum = (lnum | dnum) ('e'|'E') ('+'|'-')? lnum;
varname_first = [a-zA-Z_] | (0x0080..0x00FF);
varname_second = varname_first | [0-9];
varname = varname_first (varname_second)*;
2019-03-10 21:37:01 +00:00
heredoc_label = varname >heredoc_lbl_start %heredoc_lbl_end;
operators = ';'|':'|','|'.'|'['|']'|'('|')'|'|'|'/'|'^'|'&'|'+'|'-'|'*'|'='|'%'|'!'|'~'|'$'|'<'|'>'|'?'|'@';
prepush { lex.growCallStack(); }
constant_string =
start: (
2019-06-07 06:33:35 +00:00
"'" -> qoute
2019-03-10 21:37:01 +00:00
| "b"i? '"' -> double_qoute
),
2019-06-07 06:33:35 +00:00
# single qoute string
2019-03-10 21:37:01 +00:00
qoute: (
2019-06-07 06:33:35 +00:00
(any - [\\'\r\n]) -> qoute
| "\r" @constant_string_new_line -> qoute
| "\n" @constant_string_new_line -> qoute
| "\\" -> qoute_any
| "'" -> final
2019-03-10 21:37:01 +00:00
),
qoute_any: (
2019-06-07 06:33:35 +00:00
(any - [\r\n]) -> qoute
| "\r" @constant_string_new_line -> qoute
| "\n" @constant_string_new_line -> qoute
2019-03-10 21:37:01 +00:00
),
2019-06-07 06:33:35 +00:00
# double qoute string
2019-03-10 21:37:01 +00:00
double_qoute: (
2019-06-07 06:33:35 +00:00
(any - [\\"${\r\n]) -> double_qoute
| "\r" @constant_string_new_line -> double_qoute
| "\n" @constant_string_new_line -> double_qoute
| "\\" -> double_qoute_any
| '"' -> final
| '$' -> double_qoute_nonvarname
| '{' -> double_qoute_nondollar
2019-03-10 21:37:01 +00:00
),
double_qoute_any: (
2019-06-07 06:33:35 +00:00
(any - [\r\n]) -> double_qoute
| "\r" @constant_string_new_line -> double_qoute
| "\n" @constant_string_new_line -> double_qoute
2019-03-10 21:37:01 +00:00
),
double_qoute_nondollar: (
2020-01-08 07:31:40 +00:00
(any - [\\$"\r\n]) -> double_qoute
2019-06-07 06:33:35 +00:00
| "\r" @constant_string_new_line -> double_qoute
| "\n" @constant_string_new_line -> double_qoute
2020-01-08 07:31:40 +00:00
| "\\" -> double_qoute_any
2019-06-07 06:33:35 +00:00
| '"' -> final
2019-03-10 21:37:01 +00:00
),
double_qoute_nonvarname: (
2019-06-07 06:33:35 +00:00
(any - [\\{"\r\n] - varname_first) -> double_qoute
| "\r" @constant_string_new_line -> double_qoute
| "\n" @constant_string_new_line -> double_qoute
| "\\" -> double_qoute_any
| '"' -> final
2019-03-10 21:37:01 +00:00
);
main := |*
2019-12-29 22:20:20 +00:00
"#!" any* :>> newline => {
lex.addHiddenToken(T_COMMENT, lex.ts, lex.te)
2019-12-29 22:20:20 +00:00
};
any => {
fnext html;
lex.ungetCnt(1)
};
*|;
html := |*
2019-03-10 21:37:01 +00:00
any_line+ -- '<?' => {
lex.ungetStr("<")
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token)
2019-03-10 21:37:01 +00:00
tok = T_INLINE_HTML;
fbreak;
};
'<?' => {
lex.addHiddenToken(T_OPEN_TAG, lex.ts, lex.te)
2019-03-10 21:37:01 +00:00
fnext php;
};
'<?php'i ( [ \t] | newline ) => {
lex.ungetCnt(lex.te - lex.ts - 5)
lex.addHiddenToken(T_OPEN_TAG, lex.ts, lex.ts+5)
2019-03-10 21:37:01 +00:00
fnext php;
};
'<?='i => {
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token);
2019-03-10 21:37:01 +00:00
tok = T_ECHO;
fnext php;
fbreak;
};
*|;
php := |*
whitespace_line* => {lex.addHiddenToken(T_WHITESPACE, lex.ts, lex.te)};
2019-12-29 22:20:20 +00:00
'?>' newline? => {lex.setTokenPosition(token); tok = TokenID(int(';')); fnext html; fbreak;};
';' whitespace_line* '?>' newline? => {lex.setTokenPosition(token); tok = TokenID(int(';')); fnext html; fbreak;};
2019-03-10 21:37:01 +00:00
2019-12-21 12:44:25 +00:00
(dnum | exponent_dnum) => {lex.setTokenPosition(token); tok = T_DNUMBER; fbreak;};
2019-03-10 21:37:01 +00:00
bnum => {
s := strings.Replace(string(lex.data[lex.ts+2:lex.te]), "_", "", -1)
_, err := strconv.ParseInt(s, 2, 0)
2019-03-10 21:37:01 +00:00
if err == nil {
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token); tok = T_LNUMBER; fbreak;
}
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token); tok = T_DNUMBER; fbreak;
2019-03-10 21:37:01 +00:00
};
lnum => {
base := 10
if lex.data[lex.ts] == '0' {
base = 8
2019-03-10 21:37:01 +00:00
}
s := strings.Replace(string(lex.data[lex.ts:lex.te]), "_", "", -1)
_, err := strconv.ParseInt(s, base, 0)
if err == nil {
lex.setTokenPosition(token); tok = T_LNUMBER; fbreak;
}
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token); tok = T_DNUMBER; fbreak;
2019-03-10 21:37:01 +00:00
};
hnum => {
s := strings.Replace(string(lex.data[lex.ts+2:lex.te]), "_", "", -1)
_, err := strconv.ParseInt(s, 16, 0)
2019-03-10 21:37:01 +00:00
if err == nil {
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token); tok = T_LNUMBER; fbreak;
2019-03-10 21:37:01 +00:00
}
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token); tok = T_DNUMBER; fbreak;
2019-03-10 21:37:01 +00:00
};
2019-12-21 12:44:25 +00:00
'abstract'i => {lex.setTokenPosition(token); tok = T_ABSTRACT; fbreak;};
'array'i => {lex.setTokenPosition(token); tok = T_ARRAY; fbreak;};
'as'i => {lex.setTokenPosition(token); tok = T_AS; fbreak;};
'break'i => {lex.setTokenPosition(token); tok = T_BREAK; fbreak;};
'callable'i => {lex.setTokenPosition(token); tok = T_CALLABLE; fbreak;};
'case'i => {lex.setTokenPosition(token); tok = T_CASE; fbreak;};
'catch'i => {lex.setTokenPosition(token); tok = T_CATCH; fbreak;};
'class'i => {lex.setTokenPosition(token); tok = T_CLASS; fbreak;};
'clone'i => {lex.setTokenPosition(token); tok = T_CLONE; fbreak;};
'const'i => {lex.setTokenPosition(token); tok = T_CONST; fbreak;};
'continue'i => {lex.setTokenPosition(token); tok = T_CONTINUE; fbreak;};
'declare'i => {lex.setTokenPosition(token); tok = T_DECLARE; fbreak;};
'default'i => {lex.setTokenPosition(token); tok = T_DEFAULT; fbreak;};
'do'i => {lex.setTokenPosition(token); tok = T_DO; fbreak;};
'echo'i => {lex.setTokenPosition(token); tok = T_ECHO; fbreak;};
'else'i => {lex.setTokenPosition(token); tok = T_ELSE; fbreak;};
'elseif'i => {lex.setTokenPosition(token); tok = T_ELSEIF; fbreak;};
'empty'i => {lex.setTokenPosition(token); tok = T_EMPTY; fbreak;};
'enddeclare'i => {lex.setTokenPosition(token); tok = T_ENDDECLARE; fbreak;};
'endfor'i => {lex.setTokenPosition(token); tok = T_ENDFOR; fbreak;};
'endforeach'i => {lex.setTokenPosition(token); tok = T_ENDFOREACH; fbreak;};
'endif'i => {lex.setTokenPosition(token); tok = T_ENDIF; fbreak;};
'endswitch'i => {lex.setTokenPosition(token); tok = T_ENDSWITCH; fbreak;};
'endwhile'i => {lex.setTokenPosition(token); tok = T_ENDWHILE; fbreak;};
'eval'i => {lex.setTokenPosition(token); tok = T_EVAL; fbreak;};
'exit'i | 'die'i => {lex.setTokenPosition(token); tok = T_EXIT; fbreak;};
'extends'i => {lex.setTokenPosition(token); tok = T_EXTENDS; fbreak;};
'final'i => {lex.setTokenPosition(token); tok = T_FINAL; fbreak;};
'finally'i => {lex.setTokenPosition(token); tok = T_FINALLY; fbreak;};
'for'i => {lex.setTokenPosition(token); tok = T_FOR; fbreak;};
'foreach'i => {lex.setTokenPosition(token); tok = T_FOREACH; fbreak;};
'function'i | 'cfunction'i => {lex.setTokenPosition(token); tok = T_FUNCTION; fbreak;};
'fn'i => {lex.setTokenPosition(token); tok = T_FN; fbreak;};
2019-12-21 12:44:25 +00:00
'global'i => {lex.setTokenPosition(token); tok = T_GLOBAL; fbreak;};
'goto'i => {lex.setTokenPosition(token); tok = T_GOTO; fbreak;};
'if'i => {lex.setTokenPosition(token); tok = T_IF; fbreak;};
'isset'i => {lex.setTokenPosition(token); tok = T_ISSET; fbreak;};
'implements'i => {lex.setTokenPosition(token); tok = T_IMPLEMENTS; fbreak;};
'instanceof'i => {lex.setTokenPosition(token); tok = T_INSTANCEOF; fbreak;};
'insteadof'i => {lex.setTokenPosition(token); tok = T_INSTEADOF; fbreak;};
'interface'i => {lex.setTokenPosition(token); tok = T_INTERFACE; fbreak;};
'list'i => {lex.setTokenPosition(token); tok = T_LIST; fbreak;};
'namespace'i => {lex.setTokenPosition(token); tok = T_NAMESPACE; fbreak;};
'private'i => {lex.setTokenPosition(token); tok = T_PRIVATE; fbreak;};
'public'i => {lex.setTokenPosition(token); tok = T_PUBLIC; fbreak;};
'print'i => {lex.setTokenPosition(token); tok = T_PRINT; fbreak;};
'protected'i => {lex.setTokenPosition(token); tok = T_PROTECTED; fbreak;};
'return'i => {lex.setTokenPosition(token); tok = T_RETURN; fbreak;};
'static'i => {lex.setTokenPosition(token); tok = T_STATIC; fbreak;};
'switch'i => {lex.setTokenPosition(token); tok = T_SWITCH; fbreak;};
'throw'i => {lex.setTokenPosition(token); tok = T_THROW; fbreak;};
'trait'i => {lex.setTokenPosition(token); tok = T_TRAIT; fbreak;};
'try'i => {lex.setTokenPosition(token); tok = T_TRY; fbreak;};
'unset'i => {lex.setTokenPosition(token); tok = T_UNSET; fbreak;};
'use'i => {lex.setTokenPosition(token); tok = T_USE; fbreak;};
'var'i => {lex.setTokenPosition(token); tok = T_VAR; fbreak;};
'while'i => {lex.setTokenPosition(token); tok = T_WHILE; fbreak;};
'yield'i whitespace_line* 'from'i => {lex.setTokenPosition(token); tok = T_YIELD_FROM; fbreak;};
'yield'i => {lex.setTokenPosition(token); tok = T_YIELD; fbreak;};
'include'i => {lex.setTokenPosition(token); tok = T_INCLUDE; fbreak;};
'include_once'i => {lex.setTokenPosition(token); tok = T_INCLUDE_ONCE; fbreak;};
'require'i => {lex.setTokenPosition(token); tok = T_REQUIRE; fbreak;};
'require_once'i => {lex.setTokenPosition(token); tok = T_REQUIRE_ONCE; fbreak;};
'__CLASS__'i => {lex.setTokenPosition(token); tok = T_CLASS_C; fbreak;};
'__DIR__'i => {lex.setTokenPosition(token); tok = T_DIR; fbreak;};
'__FILE__'i => {lex.setTokenPosition(token); tok = T_FILE; fbreak;};
'__FUNCTION__'i => {lex.setTokenPosition(token); tok = T_FUNC_C; fbreak;};
'__LINE__'i => {lex.setTokenPosition(token); tok = T_LINE; fbreak;};
'__NAMESPACE__'i => {lex.setTokenPosition(token); tok = T_NS_C; fbreak;};
'__METHOD__'i => {lex.setTokenPosition(token); tok = T_METHOD_C; fbreak;};
'__TRAIT__'i => {lex.setTokenPosition(token); tok = T_TRAIT_C; fbreak;};
'__halt_compiler'i => {lex.setTokenPosition(token); tok = T_HALT_COMPILER; fnext halt_compiller_open_parenthesis; fbreak;};
'new'i => {lex.setTokenPosition(token); tok = T_NEW; fbreak;};
'and'i => {lex.setTokenPosition(token); tok = T_LOGICAL_AND; fbreak;};
'or'i => {lex.setTokenPosition(token); tok = T_LOGICAL_OR; fbreak;};
'xor'i => {lex.setTokenPosition(token); tok = T_LOGICAL_XOR; fbreak;};
'\\' => {lex.setTokenPosition(token); tok = T_NS_SEPARATOR; fbreak;};
'...' => {lex.setTokenPosition(token); tok = T_ELLIPSIS; fbreak;};
'::' => {lex.setTokenPosition(token); tok = T_PAAMAYIM_NEKUDOTAYIM; fbreak;};
'&&' => {lex.setTokenPosition(token); tok = T_BOOLEAN_AND; fbreak;};
'||' => {lex.setTokenPosition(token); tok = T_BOOLEAN_OR; fbreak;};
'&=' => {lex.setTokenPosition(token); tok = T_AND_EQUAL; fbreak;};
'|=' => {lex.setTokenPosition(token); tok = T_OR_EQUAL; fbreak;};
'.=' => {lex.setTokenPosition(token); tok = T_CONCAT_EQUAL; fbreak;};
'*=' => {lex.setTokenPosition(token); tok = T_MUL_EQUAL; fbreak;};
'**=' => {lex.setTokenPosition(token); tok = T_POW_EQUAL; fbreak;};
'/=' => {lex.setTokenPosition(token); tok = T_DIV_EQUAL; fbreak;};
'+=' => {lex.setTokenPosition(token); tok = T_PLUS_EQUAL; fbreak;};
'-=' => {lex.setTokenPosition(token); tok = T_MINUS_EQUAL; fbreak;};
'^=' => {lex.setTokenPosition(token); tok = T_XOR_EQUAL; fbreak;};
'%=' => {lex.setTokenPosition(token); tok = T_MOD_EQUAL; fbreak;};
'--' => {lex.setTokenPosition(token); tok = T_DEC; fbreak;};
'++' => {lex.setTokenPosition(token); tok = T_INC; fbreak;};
'=>' => {lex.setTokenPosition(token); tok = T_DOUBLE_ARROW; fbreak;};
'<=>' => {lex.setTokenPosition(token); tok = T_SPACESHIP; fbreak;};
'!=' | '<>' => {lex.setTokenPosition(token); tok = T_IS_NOT_EQUAL; fbreak;};
'!==' => {lex.setTokenPosition(token); tok = T_IS_NOT_IDENTICAL; fbreak;};
'==' => {lex.setTokenPosition(token); tok = T_IS_EQUAL; fbreak;};
'===' => {lex.setTokenPosition(token); tok = T_IS_IDENTICAL; fbreak;};
'<<=' => {lex.setTokenPosition(token); tok = T_SL_EQUAL; fbreak;};
'>>=' => {lex.setTokenPosition(token); tok = T_SR_EQUAL; fbreak;};
'>=' => {lex.setTokenPosition(token); tok = T_IS_GREATER_OR_EQUAL; fbreak;};
'<=' => {lex.setTokenPosition(token); tok = T_IS_SMALLER_OR_EQUAL; fbreak;};
'**' => {lex.setTokenPosition(token); tok = T_POW; fbreak;};
'<<' => {lex.setTokenPosition(token); tok = T_SL; fbreak;};
'>>' => {lex.setTokenPosition(token); tok = T_SR; fbreak;};
'??' => {lex.setTokenPosition(token); tok = T_COALESCE; fbreak;};
'??=' => {lex.setTokenPosition(token); tok = T_COALESCE_EQUAL; fbreak;};
2019-12-21 12:44:25 +00:00
'(' whitespace* 'array'i whitespace* ')' => {lex.setTokenPosition(token); tok = T_ARRAY_CAST; fbreak;};
'(' whitespace* ('bool'i|'boolean'i) whitespace* ')' => {lex.setTokenPosition(token); tok = T_BOOL_CAST; fbreak;};
'(' whitespace* ('real'i|'double'i|'float'i) whitespace* ')' => {lex.setTokenPosition(token); tok = T_DOUBLE_CAST; fbreak;};
'(' whitespace* ('int'i|'integer'i) whitespace* ')' => {lex.setTokenPosition(token); tok = T_INT_CAST; fbreak;};
'(' whitespace* 'object'i whitespace* ')' => {lex.setTokenPosition(token); tok = T_OBJECT_CAST; fbreak;};
'(' whitespace* ('string'i|'binary'i) whitespace* ')' => {lex.setTokenPosition(token); tok = T_STRING_CAST; fbreak;};
'(' whitespace* 'unset'i whitespace* ')' => {lex.setTokenPosition(token); tok = T_UNSET_CAST; fbreak;};
2019-03-10 21:37:01 +00:00
('#' | '//') any_line* when is_not_comment_end => {
lex.ungetStr("?>")
lex.addHiddenToken(T_COMMENT, lex.ts, lex.te)
2019-03-10 21:37:01 +00:00
};
'/*' any_line* :>> '*/' {
isDocComment := false;
if lex.te - lex.ts > 4 && string(lex.data[lex.ts:lex.ts+3]) == "/**" {
isDocComment = true;
}
if isDocComment {
lex.addHiddenToken(T_DOC_COMMENT, lex.ts, lex.te)
2020-05-12 21:16:36 +00:00
} else {
lex.addHiddenToken(T_COMMENT, lex.ts, lex.te)
2019-03-10 21:37:01 +00:00
}
};
operators => {
// rune, _ := utf8.DecodeRune(lex.data[lex.ts:lex.te]);
// tok = TokenID(Rune2Class(rune));
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token);
2019-03-10 21:37:01 +00:00
tok = TokenID(int(lex.data[lex.ts]));
fbreak;
};
2019-12-21 12:44:25 +00:00
"{" => { lex.setTokenPosition(token); tok = TokenID(int('{')); lex.call(ftargs, fentry(php)); goto _out; };
"}" => { lex.setTokenPosition(token); tok = TokenID(int('}')); lex.ret(1); goto _out;};
2019-12-21 12:44:25 +00:00
"$" varname => { lex.setTokenPosition(token); tok = T_VARIABLE; fbreak; };
varname => { lex.setTokenPosition(token); tok = T_STRING; fbreak; };
2019-03-10 21:37:01 +00:00
2019-12-21 12:44:25 +00:00
"->" => { lex.setTokenPosition(token); tok = T_OBJECT_OPERATOR; fnext property; fbreak; };
2019-03-10 21:37:01 +00:00
constant_string => {
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token);
2019-03-10 21:37:01 +00:00
tok = T_CONSTANT_ENCAPSED_STRING;
fbreak;
};
"b"i? "<<<" [ \t]* ( heredoc_label | ("'" heredoc_label "'") | ('"' heredoc_label '"') ) newline => {
lex.heredocLabel = lex.data[lblStart:lblEnd]
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token);
2019-03-10 21:37:01 +00:00
tok = T_START_HEREDOC;
if lex.isHeredocEnd(lex.p+1) {
fnext heredoc_end;
} else if lex.data[lblStart-1] == '\'' {
fnext nowdoc;
} else {
fnext heredoc;
}
fbreak;
};
2019-12-21 12:44:25 +00:00
"`" => {lex.setTokenPosition(token); tok = TokenID(int('`')); fnext backqote; fbreak;};
'"' => {lex.setTokenPosition(token); tok = TokenID(int('"')); fnext template_string; fbreak;};
2019-03-10 21:37:01 +00:00
any_line => {
c := lex.data[lex.p]
lex.error(fmt.Sprintf("WARNING: Unexpected character in input: '%c' (ASCII=%d)", c, c));
2019-03-10 21:37:01 +00:00
};
*|;
property := |*
whitespace_line* => {lex.addHiddenToken(T_WHITESPACE, lex.ts, lex.te)};
2019-12-21 12:44:25 +00:00
"->" => {lex.setTokenPosition(token); tok = T_OBJECT_OPERATOR; fbreak;};
varname => {lex.setTokenPosition(token); tok = T_STRING; fnext php; fbreak;};
2019-03-10 21:37:01 +00:00
any => {lex.ungetCnt(1); fgoto php;};
*|;
nowdoc := |*
any_line* when is_not_heredoc_end => {
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token);
2019-03-10 21:37:01 +00:00
tok = T_ENCAPSED_AND_WHITESPACE;
fnext heredoc_end;
fbreak;
};
*|;
heredoc := |*
2019-12-21 12:44:25 +00:00
"{$" => {lex.ungetCnt(1); lex.setTokenPosition(token); tok = T_CURLY_OPEN; lex.call(ftargs, fentry(php)); goto _out;};
"${" => {lex.setTokenPosition(token); tok = T_DOLLAR_OPEN_CURLY_BRACES; lex.call(ftargs, fentry(string_var_name)); goto _out;};
2019-03-10 21:37:01 +00:00
"$" => {lex.ungetCnt(1); fcall string_var;};
any_line* when is_not_heredoc_end_or_var => {
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token);
2019-03-10 21:37:01 +00:00
tok = T_ENCAPSED_AND_WHITESPACE;
2019-12-26 13:41:06 +00:00
if len(lex.data) > lex.p+1 && lex.data[lex.p+1] != '$' && lex.data[lex.p+1] != '{' {
2019-03-10 21:37:01 +00:00
fnext heredoc_end;
}
fbreak;
};
*|;
backqote := |*
2019-12-21 12:44:25 +00:00
"{$" => {lex.ungetCnt(1); lex.setTokenPosition(token); tok = T_CURLY_OPEN; lex.call(ftargs, fentry(php)); goto _out;};
"${" => {lex.setTokenPosition(token); tok = T_DOLLAR_OPEN_CURLY_BRACES; lex.call(ftargs, fentry(string_var_name)); goto _out;};
2019-03-10 21:37:01 +00:00
"$" => {lex.ungetCnt(1); fcall string_var;};
2019-12-21 12:44:25 +00:00
'`' => {lex.setTokenPosition(token); tok = TokenID(int('`')); fnext php; fbreak;};
2019-03-10 21:37:01 +00:00
any_line* when is_not_backqoute_end_or_var => {
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token);
2019-03-10 21:37:01 +00:00
tok = T_ENCAPSED_AND_WHITESPACE;
fbreak;
};
*|;
template_string := |*
2019-12-21 12:44:25 +00:00
"{$" => {lex.ungetCnt(1); lex.setTokenPosition(token); tok = T_CURLY_OPEN; lex.call(ftargs, fentry(php)); goto _out;};
"${" => {lex.setTokenPosition(token); tok = T_DOLLAR_OPEN_CURLY_BRACES; lex.call(ftargs, fentry(string_var_name)); goto _out;};
2019-03-10 21:37:01 +00:00
"$" => {lex.ungetCnt(1); fcall string_var;};
2019-12-21 12:44:25 +00:00
'"' => {lex.setTokenPosition(token); tok = TokenID(int('"')); fnext php; fbreak;};
2019-03-10 21:37:01 +00:00
any_line* when is_not_string_end_or_var => {
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token);
2019-03-10 21:37:01 +00:00
tok = T_ENCAPSED_AND_WHITESPACE;
fbreak;
};
*|;
heredoc_end := |*
varname -- ";" => {
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token);
2019-03-10 21:37:01 +00:00
tok = T_END_HEREDOC;
fnext php;
fbreak;
};
varname => {
2019-12-21 12:44:25 +00:00
lex.setTokenPosition(token);
2019-03-10 21:37:01 +00:00
tok = T_END_HEREDOC;
fnext php;
fbreak;
};
*|;
string_var := |*
2019-12-21 12:44:25 +00:00
'$' varname => {lex.setTokenPosition(token); tok = T_VARIABLE; fbreak;};
'->' varname_first => {lex.ungetCnt(1); lex.setTokenPosition(token); tok = T_OBJECT_OPERATOR; fbreak;};
varname => {lex.setTokenPosition(token); tok = T_STRING; fbreak;};
'[' => {lex.setTokenPosition(token); tok = TokenID(int('[')); lex.call(ftargs, fentry(string_var_index)); goto _out;};
2019-03-10 21:37:01 +00:00
any => {lex.ungetCnt(1); fret;};
*|;
string_var_index := |*
2019-12-21 12:44:25 +00:00
lnum | hnum | bnum => {lex.setTokenPosition(token); tok = T_NUM_STRING; fbreak;};
'$' varname => {lex.setTokenPosition(token); tok = T_VARIABLE; fbreak;};
varname => {lex.setTokenPosition(token); tok = T_STRING; fbreak;};
whitespace_line | [\\'#] => {lex.setTokenPosition(token); tok = T_ENCAPSED_AND_WHITESPACE; lex.ret(2); goto _out;};
operators > (svi, 1) => {lex.setTokenPosition(token); tok = TokenID(int(lex.data[lex.ts])); fbreak;};
']' > (svi, 2) => {lex.setTokenPosition(token); tok = TokenID(int(']')); lex.ret(2); goto _out;};
2019-03-10 21:37:01 +00:00
any_line => {
c := lex.data[lex.p]
lex.error(fmt.Sprintf("WARNING: Unexpected character in input: '%c' (ASCII=%d)", c, c));
2019-03-10 21:37:01 +00:00
};
*|;
string_var_name := |*
2019-12-21 12:44:25 +00:00
varname ("[" | "}") => {lex.ungetCnt(1); lex.setTokenPosition(token); tok = T_STRING_VARNAME; fnext php; fbreak;};
2019-03-10 21:37:01 +00:00
any => {lex.ungetCnt(1); fnext php;};
*|;
halt_compiller_open_parenthesis := |*
whitespace_line* => {lex.addHiddenToken(T_WHITESPACE, lex.ts, lex.te)};
2019-12-21 12:44:25 +00:00
"(" => {lex.setTokenPosition(token); tok = TokenID(int('(')); fnext halt_compiller_close_parenthesis; fbreak;};
2019-03-10 21:37:01 +00:00
any => {lex.ungetCnt(1); fnext php;};
*|;
halt_compiller_close_parenthesis := |*
whitespace_line* => {lex.addHiddenToken(T_WHITESPACE, lex.ts, lex.te)};
2019-12-21 12:44:25 +00:00
")" => {lex.setTokenPosition(token); tok = TokenID(int(')')); fnext halt_compiller_close_semicolon; fbreak;};
2019-03-10 21:37:01 +00:00
any => {lex.ungetCnt(1); fnext php;};
*|;
halt_compiller_close_semicolon := |*
whitespace_line* => {lex.addHiddenToken(T_WHITESPACE, lex.ts, lex.te)};
2019-12-21 12:44:25 +00:00
";" => {lex.setTokenPosition(token); tok = TokenID(int(';')); fnext halt_compiller_end; fbreak;};
2019-03-10 21:37:01 +00:00
any => {lex.ungetCnt(1); fnext php;};
*|;
halt_compiller_end := |*
any_line* => { lex.addHiddenToken(T_HALT_COMPILER, lex.ts, lex.te); };
2019-03-10 21:37:01 +00:00
*|;
write exec;
}%%
token.Hidden = lex.hiddenTokens
2020-05-12 21:16:36 +00:00
token.Value = lex.data[lex.ts:lex.te]
2020-05-17 19:56:32 +00:00
token.ID = tok
2019-12-21 12:44:25 +00:00
return token
2019-03-10 21:37:01 +00:00
}