提交 1e1a03ef 创建 作者: 赵鹏翀's avatar 赵鹏翀

init template

上级
/Debug
/Release
<?xml version="1.0" encoding="gb2312"?>
<OSLProject Version="1.00" Name="scan" SubjectID="11c951f4-9b13-40e1-8b73-39ba7d73b89b" ProjectTemplateID="6fdce38e-9162-4060-b427-666eb3e3556b">
<Configurations>
<Configuration Name="Debug" CommandArgument="sample.txt">
<Tool Name="PreBuildEventTool"/>
<Tool Name="CustomBuildTool"/>
<Tool Name="GCCCompilerTool" PreprocessorDefinitions="_DEBUG" GenerateDebugInformation="-1"/>
<Tool Name="PreLinkEventTool"/>
<Tool Name="GCCLinkerTool" AdditionalLibraries="fl"/>
<Tool Name="PostBuildEventTool"/>
</Configuration>
<Configuration Name="Release" CommandArgument="sample.txt">
<Tool Name="PreBuildEventTool"/>
<Tool Name="CustomBuildTool"/>
<Tool Name="GCCCompilerTool" PreprocessorDefinitions="NDEBUG"/>
<Tool Name="PreLinkEventTool"/>
<Tool Name="GCCLinkerTool" AdditionalLibraries="fl"/>
<Tool Name="PostBuildEventTool"/>
</Configuration>
</Configurations>
<Files>
<Filter Name="Lex输入文件">
<File RelativePath=".\scan.txt">
<FileConfiguration Name="Debug">
<Tool Name="CustomBuildTool" CommandLine="flex.exe -b -omain.c &quot;$(InputPath)&quot;&#xA;" Description="正在使用 Lex 生成扫描程序..." Outputs="lex.backup" AdditionalDependencies=""/>
</FileConfiguration>
<FileConfiguration Name="Release">
<Tool Name="CustomBuildTool" CommandLine="flex.exe -b -omain.c &quot;$(InputPath)&quot;&#xA;" Description="正在使用 Lex 生成扫描程序..." Outputs="lex.backup" AdditionalDependencies=""/>
</FileConfiguration>
</File>
</Filter>
<Filter Name="TINY语言样例">
<File RelativePath=".\sample.txt">
</File>
</Filter>
<Filter Name="头文件">
<File RelativePath=".\define.h">
</File>
</Filter>
<Filter Name="源文件" Filter="cpp;c;cc;cxx">
<File RelativePath=".\main.c">
</File>
</Filter>
</Files>
</OSLProject>
添加文件
#ifndef _DEFINE_H_
#define _DEFINE_H_
typedef enum
{
// 文件结束
ENDFILE,
// 错误
ERROR,
// 关键字
IF, // if
THEN, // then
ELSE, // else
END, // end
REPEAT, // repeat
UNTIL, // until
READ, // read
WRITE, // write
// 标识符
ID,
// 无符号整数
NUM,
// 特殊符号
ASSIGN, // :=
EQ, // =
LT, // <
PLUS, // +
MINUS, // -
TIMES, // *
OVER, // /
LPAREN, // (
RPAREN, // )
SEMI, // ;
// 注释
COMMENT // {...}
}TokenType;
#endif // _DEFINE_H_
{ Sample program
int TINY language -
computes factorial
}
read x; { input an integer }
if 0 < x then { don't compute if x <= 0 }
fact := 1;
repeat
fact := fact * x;
x := x - 1
until
x = 0;
write fact { output factorial of x }
end
%{
#include <stdio.h>
#include "define.h"
int lineno = 0; // 行数
// 符号计数器
int error_no = 0;
int if_no = 0;
int then_no = 0;
int else_no = 0;
int end_no = 0;
int repeat_no = 0;
int until_no = 0;
int read_no = 0;
int write_no = 0;
int id_no = 0;
int num_no = 0;
int assign_no = 0;
int eq_no = 0;
int lt_no = 0;
int plus_no = 0;
int minus_no = 0;
int times_no = 0;
int over_no = 0;
int lparen_no = 0;
int rparen_no = 0;
int semi_no = 0;
int comment_no = 0;
%}
newline \n
whitespace [ \t]+
%%
":=" { return ASSIGN; }
"=" { return EQ; }
"<" { return LT; }
"+" { return PLUS; }
"-" { return MINUS; }
"*" { return TIMES; }
"/" { return OVER; }
"(" { return LPAREN; }
")" { return RPAREN; }
";" { return SEMI; }
{newline} { lineno++; }
{whitespace} { /* 忽略空白 */ }
"{" {
// 匹配注释 {...}
char c;
int comment = 1;
do
{
c = input();
if(c == EOF)
{
comment = 0;
break;
}
else if(c == '\n')
lineno++;
else if(c == '}')
break;
}while(1);
return comment ? COMMENT : ERROR;
}
. { return ERROR; }
%%
TokenType id2keyword(const char* token);
void stat(TokenType tt, const char* token);
void output();
/*
功能:
主函数
参数:
argc - argv 数组的长度,大小至少为 1,argc - 1 为命令行参数的数量。
argv - 字符串指针数组,数组长度为命令行参数个数 + 1。其中 argv[0] 固定指向当前
所执行的可执行文件的路径字符串,argv[1] 及其后面的指针指向各个命令行参数。
例如通过命令行输入 "C:\hello.exe -a -b" 后,main 函数的 argc 的值为 3,
argv[0] 指向字符串 "C:\hello.exe",argv[1] 指向字符串 "-a",argv[2] 指向字符串 "-b"。
返回值:
成功返回 0, 失败返回 1
*/
int main(int argc, char* argv[])
{
TokenType tt;
// 使用第一个参数输入待处理文件的名称,若没有没有输入此参数就报告错误
if(argc < 2)
{
printf("Usage: scan.exe filename.\n");
return 1;
}
// 打开待处理的文件
FILE* file = fopen(argv[1], "rt");
if(NULL == file)
{
printf("Can not open file \"%s\".\n", argv[1]);
return 1;
}
// 将打开的文件作为 lex 扫描程序的输入
yyin = file;
// 开始扫描,直到文件结束
while((tt = yylex()) != ENDFILE)
{
// 根据符号类型统计其数量
stat(tt, yytext);
}
// 输出统计结果
output();
// 关闭文件
fclose(file);
return 0;
}
// 定义关键字与其类型的映射关系
typedef struct _KeyWord_Entry
{
const char* word;
TokenType type;
}KeyWord_Entry;
static const KeyWord_Entry key_table[] =
{
{ "if", IF },
{ "then", THEN },
{ "else", ELSE },
{ "end", END },
{ "repeat", REPEAT },
{ "until", UNTIL },
{ "read", READ },
{ "write", WRITE }
};
/*
功能:
将标识符转换为对应的关键字类型
参数:
id - 标识符字符串指针。可能是一个关键字,也可能是用户定义的标识符。
返回值:
成功返回 0, 失败返回 1
*/
TokenType id2keyword(const char* id)
{
//
// TODO: 在此添加源代码
//
return ID;
}
/*
功能:
根据符号类型进行数量统计。
参数:
tt - 符号类型。
token - 符号字符串指针。当符号被识别为标识符时,需要判断其是否为一个关键字。
返回值:
*/
void stat(TokenType tt, const char* token)
{
if(ID == tt)
{
tt = id2keyword(token);
}
switch(tt)
{
case IF: // if
if_no++;
break;
case THEN: // then
then_no++;
break;
case ELSE: // else
else_no++;
break;
case END: // end
end_no++;
break;
case REPEAT: // repeat
repeat_no++;
break;
case UNTIL: // until
until_no++;
break;
case READ: // read
read_no++;
break;
case WRITE: // write
write_no++;
break;
case ID: // 标识符
id_no++;
break;
case NUM: // 无符号整数
num_no++;
break;
case ASSIGN: // :=
assign_no++;
break;
case EQ: // =
eq_no++;
break;
case LT: // <
lt_no++;
break;
case PLUS: // +
plus_no++;
break;
case MINUS: // -
minus_no++;
break;
case TIMES: // *
times_no++;
break;
case OVER: // /
over_no++;
break;
case LPAREN: // (
lparen_no++;
break;
case RPAREN: // )
rparen_no++;
break;
case SEMI: // ;
semi_no++;
break;
case COMMENT: // {...}
comment_no++;
break;
case ERROR: // 错误
error_no++;
break;
}
}
// 输出统计结果
void output()
{
printf("if: %d\n", if_no);
printf("then: %d\n", then_no);
printf("else: %d\n", else_no);
printf("end: %d\n", end_no);
printf("repeat: %d\n", repeat_no);
printf("until: %d\n", until_no);
printf("read: %d\n", read_no);
printf("write: %d\n", write_no);
printf("id: %d\n", id_no);
printf("num: %d\n", num_no);
printf("assign: %d\n", assign_no);
printf("eq: %d\n", eq_no);
printf("lt: %d\n", lt_no);
printf("plus: %d\n", plus_no);
printf("minus: %d\n", minus_no);
printf("times: %d\n", times_no);
printf("over: %d\n", over_no);
printf("lparen: %d\n", lparen_no);
printf("rparen: %d\n", rparen_no);
printf("semi: %d\n", semi_no);
printf("comment: %d\n", comment_no);
printf("error: %d\n", error_no);
printf("line: %d\n", lineno);
}
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论