leex
leex
模块
leex
模块摘要
Erlang词法分析器生成器
描述
基于正则表达式的Erlang词法分析器生成器,类似于lex或flex。
注
LEEX模块应该被视为实验性的,因为它将在未来的版本中发生变化。
数据类型
ErrorInfo = {ErrorLine,module(),error_descriptor()}
ErrorLine = integer()
Token = tuple()
输出
file(FileName, [, Options]) -> LeexRet
类型
根据输入文件中的定义生成一个词法分析器。输入文件具有扩展名.xrl
。如果未给出,则将其添加到文件名中。结果模块是没有.xrl
扩展名的Xrl文件名。
目前的备选办法是:
dfa_graph
生成一个.dot
包含DFA描述的文件,格式可以使用Graphviz查看www.graphviz.com
。
{includefile,Includefile}
使用特定的或自定义的序言文件,而不是默认的。lib/parsetools/include/leexinc.hrl
否则就包括在内。
{report_errors, bool()}
导致错误在发生时被打印。默认是true
。
{report_warnings, bool()}
导致警告在发生时被打印。默认是true
。
warnings_as_errors
导致将警告视为错误。
{report, bool()}
这是report_errors和report_warnings的简写形式。
{return_errors, bool()}
如果设置了该标志,{error, Errors, Warnings}
则在出现错误时返回。默认是false
。
{return_warnings, bool()}
如果设置了该标志,则Warnings
在成功返回的元组中添加一个额外的包含字段。默认是false
。
{return, bool()}
这是return_errors和return_warnings的简写形式。
{scannerfile, Scannerfile}
Scannerfile
是将包含生成的Erlang扫描程序代码的文件的名称。默认(""
)是添加扩展名.erl
以FileName
去掉.xrl
扩展名。
{verbose, bool()}
从解析输入文件和生成内部表中输出信息。
任何布尔选项都可以true
通过声明选项的名称来设置。例如,verbose
相当于{verbose, true}
。
Leex将添加扩展.hrl
至Includefile
名和扩展名.erl
的Scannerfile
名字,除非扩展已经存在。
format_error(ErrorInfo) -> Chars
类型
返回描述错误的字符串。ErrorInfo
在正则表达式中出现错误时返回。
生成扫描器输出
下面的函数由生成的扫描器导出。
输出
string(String) -> StringRetstring(String, StartLine) -> StringRet
类型
扫描String
并返回其中的所有标记,或一个错误。
注
如果不是所有字符String
都被消耗,则是错误的。
token(Cont, Chars) -> {more,Cont1} | {done,TokenRet,RestChars}token(Cont, Chars, StartLine) -> {more,Cont1} | {done,TokenRet,RestChars}
类型
这是尝试从一个令牌中扫描一个令牌的重新调用Chars。如果有足够的字符Chars来扫描令牌或检测到错误,那么这将与返回{done,...}。否则{cont,Cont}将返回Cont下一次调用时token()使用更多字符尝试扫描令牌的位置。这一直持续到令牌被扫描。Cont最初为[]。
它不是设计为由应用程序直接调用,而是通过I/O系统使用,通常可以通过以下方式在应用程序中调用:
io:request(InFile, {get_until,Prompt,Module,token,[Line]})
-> TokenRet
tokens(Cont, Chars) -> {more,Cont1} | {done,TokensRet,RestChars}tokens(Cont, Chars, StartLine) -> {more,Cont1} | {done,TokensRet,RestChars}
类型
这是一次尝试扫描令牌的重新调用Chars
。如果有足够的字符Chars
来扫描令牌或检测到错误,那么将返回{done,...}
。否则{cont,Cont}
将返回Cont
到下一次使用的位置,tokens()
以更多字符尝试扫描令牌。这一直持续到所有的令牌都被扫描。Cont
最初[]
。
这个功能不同于token
它将继续扫描令牌直到并包括一个{end_token,Token}
已被扫描(见下一节)。它会返回所有的令牌。这通常用于扫描像Erlang这样的语法,其中存在明确的结束标记'.'
。如果没有找到结束标记,则整个文件将被扫描并返回。如果发生错误,则所有令牌将被跳过,并包括下一个结束令牌。
它不是设计为由应用程序直接调用,而是通过I/O系统使用,通常可以通过以下方式在应用程序中调用:
io:request(InFile, {get_until,Prompt,Module,tokens,[Line]})
-> TokensRet
输入文件格式
Erlang样式的注释以%
扫描文件中允许。定义文件具有以下格式:
<Header>
Definitions.
<Macro Definitions>
Rules.
<Token Rules>
Erlang code.
<Erlang code>
“定义”,“规则”。和“Erlang代码”。标题是强制性的,并且必须出现在源代码行的开头。<Header>,<Macro Definitions>和<Erlang code>部分可能为空,但必须至少有一个规则。
宏定义的格式如下:
NAME = VALUE
并且周围必须有空间=
。宏可以通过编写在规则的正则表达式中使用{NAME}
。
注
当宏在表达式中展开时,宏调用被替换为宏值,而不使用任何形式的引用或括号内的括起来。
规则的格式如下:
<Regexp> : <Erlang code>.
<正则表达式>必须出现在一行的开头,不包含任何空格; 使用\t和\s在正则表达式中包含TAB和SPACE字符。如果<Regexp>匹配,则评估相应的<Erlang code>以生成令牌。使用Erlang代码,可以使用以下预定义变量:
TokenChars
匹配令牌中的字符列表。
TokenLen
匹配标记中的字符数。
TokenLine
发生令牌的行号。
代码必须返回:
{token,Token}
回归Token
调用者。
{end_token,Token}
回归Token
是令牌调用中的最后一个令牌。
skip_token
完全跳过这个标记。
{error,ErrString}
标记上的错误,ErrString
描述错误的字符串。
还可以将字符推回输入字符,返回如下内容:
{token,Token,PushBackList}
{end_token,Token,PushBackList}
{skip_token,PushBackList}
这些与正常返回具有相同的含义,但字符PushBackList
将被添加到输入字符并扫描下一个标记。请注意,推回换行将意味着行号将不再正确。
注
推回角色让您意想不到的可能性导致扫描仪循环!
下面的示例将匹配一个简单的Erlang整数或浮点数,并返回一个令牌,该令牌可以发送给Erlang解析器:
D = [0-9]
{D}+ :
{token,{integer,TokenLine,list_to_integer(TokenChars)}}.
{D}+\.{D}+((E|e)(\+|\-)?{D}+)? :
{token,{float,TokenLine,list_to_float(TokenChars)}}.
Erlang代码中的“Erlang代码”。节直接写入输出文件中,在模块声明和预定义导出声明之后,因此可以添加额外的导出、定义导入和其他属性,然后在整个文件中可见。
正则表达式
这里允许的正则表达式是egrep
在AWK编程语言中和AWK编程语言中找到的集合的一个子集,如AV Aho,BW Kernighan,PJ Weinberger在书AWK编程语言中定义的。它们由以下字符组成:
c
匹配非元字符c。
\c
匹配转义序列或文字字符c。
.
任何字符都匹配。
^
匹配字符串的开头。
$
匹配字符串的结尾。
[abc...]
字符类,它匹配任何字符abc...
。字符范围由一对由a分隔的字符指定-
。
[^abc...]
否定字符类,它匹配除abc以外的任何字符....
r1 | r2
轮换。它匹配r1
或者r2
。
r1r2
级联。它匹配r1
,之后为r2
。
r+
匹配一个或多个rs
...
r*
匹配零个或更多rs
。
r?
匹配零个或一个rs
。
(r)
分组。它匹配r
。
允许的转义序列与Erlang字符串相同:
\b
Backspace
\f
换页
\n
Newline (line feed).
\r
回车
\t
Tab
\e
转义键
\v
垂直标签
\s
Space
\d
Delete
\ddd
八进制值ddd
。
\xhh
十六进制值hh
。
\x{h...}
十六进制值h...
。
\c
字面上的任何其他字符,例如\\
反斜杠,\"
用于"
。
以下示例定义了几个Erlang数据类型的简化版本:
Atoms [a-z][0-9a-zA-Z_]*
Variables [A-Z_][0-9a-zA-Z_]*
Floats (\+|-)?[0-9]+\.[0-9]+((E|e)(\+|-)?[0-9]+)?
注
在当前版本的Leex中锚定一个正则表达式^
并且$
不会实现,只会生成一个解析错误。