flex&bison系列第一章:flex Hello World

系列文章目录

flex&bison系列第一章:flex Hello World
flex&bison系列第二章:写一个简单的单词统计工具Word Counter
flex&bison系列第三章:写一个简单的计算器Calculator

LLVM系列



前言

在此记录下基于flex写一个Hello World的过程,以备查阅。

flex是用来生成程序的工具,比如用来生成编译器程序(一般指编译器的前端部分)。它所生成的程序能够处理结构化的输入。在这里,为简单起见,我们可以把“结构化的输入”理解为有一定组织结构的文本,我们用flex对文本进行处理时,应提前了解一下正则表达式和编译原理相关的知识(如词法分析器、自动机等)。

本章,我们就来利用flex写一个简单的Hello World程序。

一、开发环境

1. 操作系统

我用的操作系统是macOS 11.6.4:

System Version:	macOS 12.5 (21G72)
Kernel Version:	Darwin 21.6.0

Model Name:	MacBook Pro
Model Identifier:	MacBookPro15,1
Processor Name:	8-Core Intel Core i9
Processor Speed:	2.3 GHz
Number of Processors:	1
Total Number of Cores:	8
Memory:	16 GB

2. 安装工具

用到的工具有Clang (Xcode)、flex。

关于安装Xcode, 可参考这个简易教程:

How to download Xcode DMG or XIP file? - Stack Overflow

安装后确认信息如下(示例):

% clang -v                                                        
Apple clang version 14.0.0 (clang-1400.0.29.100)
Target: x86_64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

对于其它工具,可借助brew (https://brew.sh) 进行安装(示例):

# Install flex
brew install flex

# Upgrade flex
brew upgrade flex

macOS已经自带flex工具,所以无需自己安装了。

二、Hello World

这个Hello World程序要做的事很简单,具体如下:

  1. 当检测到“World”这个单词时,输出“Hello World”
  2. 否则,输出原来的单词即可

首先,我们要写一个简单的flex脚本文件(示例):

/*
 * hello-world.l
 */

%option noyywrap

%{
%}

%%
World    printf("Hello World");
%%

int main(int argc, char** argv)
{
  yylex();
}

一个flex文件一般分为三部分,用符合“%%”隔开:

<第一部分>

%%

<第二部分>

%%

<第三部分>

我们的例子中,比较重要的是第二部分:

World    printf("Hello World");

这一行代码包含两个部分:

  1. World,它其实是一个匹配字符串,意思是用“World”去匹配输入的数据。
  2. printf("Hello World");,这是匹配成功后的“行动”,意思是如果匹配成功,则打印“Hello World”。

三、编译

1. 生成C代码

运行如下命令即可生成C代码(示例):

flex hello-world.l

其生成的C代码文件名为“lex.yy.c”。

2. 编译

我们可以用clang对以上生成的C代码进行编译(示例):

# Set up C++ standard library and header path for clang
export SDKROOT=$(xcrun --sdk macosx --show-sdk-path)

# Build with clang
clang lex.yy.c -o hello-world

# Or, build with gcc
gcc lex.yy.c -o hello-world

以上命令会生成一个名为“hello-world”的可执行程序。

四、运行

可以用如下命令运行Hello World程序(示例):

./hello-world

接下来,程序会等待用户的输入。我们可以随意打一个字符,然后按回车键,可以看到如下输出(示例):

abc
abc
World
Hello World
123
123

注意到,当我们输入单词“World”时,程序会输出“Hello World”;而当输入其它单词时,则仅输出原来的单词而已。

总结

我们基于flex,用C++写了一个Hello World,并且编译运行成功。完整源码示例请参看:
https://github.com/wuzhanglin/flex-bison-examples

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,下面是一个简单计算器的flexbison文件示例: flex文件(calc.lex): ``` %{ #include "calc.tab.h" %} %% [ \t\n] ; /* ignore whitespace */ [-9]+ { yylval = atoi(yytext); return NUMBER; } [-+*/()] { return yytext[]; } . { printf("Invalid character: %s\n", yytext); } %% int yywrap() { return 1; } ``` bison文件(calc.y): ``` %{ #include <stdio.h> #include <stdlib.h> %} %token NUMBER %left '+' '-' %left '*' '/' %left UMINUS %% calc: /* empty */ | calc expr '\n' { printf("= %d\n", $2); } ; expr: NUMBER | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { $$ = $1 / $3; } | '-' expr %prec UMINUS { $$ = -$2; } | '(' expr ')' { $$ = $2; } ; %% int main() { yyparse(); return ; } void yyerror(char *s) { printf("Error: %s\n", s); } ``` 这个计算器支持加减乘除和括号,并且可以处理负数。你可以使用以下命令编译和运行: ``` flex calc.lex bison -d calc.y gcc -o calc calc.tab.c lex.yy.c ./calc ``` 然后你就可以输入表达式进行计算了,例如: ``` 1+2*3 = 7 (1+2)*3 = 9 -2*3+(4-1)*5 = 11 ``` ### 回答2: 在编写一个简单的计算器程序时,FlexBison是很好的工具。Flex可用于进行词法分析,将输入数据(例如用户从键盘输入的数据)转化为单词,也就是词法单元。而Bison是类似的工具,但是它用于进行语法解析,将这些单词转化成计算机程序所能理解的语法结构。 要开始编写这个程序,您首先需要创建一个.flex文件和一个.y文件。在.flex文件中,您将定义程序的所有单词,包括数字、操作符等。每个词都会有一个“模式”,用于将输入数据与正确的单词匹配。然后,这些单词将被传递给Bison进行进一步处理。 在Bison文件中,您将定义计算器所需的语法。这将涉及到规定语法结构,如如何组成表达式以及如何计算它们。另外,您还需要定义如何处理语法错误,以及如何处理计算结果。 一旦您完成这些步骤,就可以将程序编译成可执行文件并运行它。这时,用户将可以从键盘输入表达式,并以计算结果作为输出。例如,用户可以输入“3 + 5 * 2”,程序将把它解析为正确的语法结构,并输出结果“13”。 总之,使用FlexBison编写计算器程序是一个非常有趣和有用的练习,并且可以帮助您更好地理解编译原理的基本概念和操作。如果您想进一步提高您的编程技能,并且对编译原理感兴趣,那么使用这些工具编写一个简单的计算器程序是一个很好的起点! ### 回答3: 在计算机科学中,flexbison是两种常用的工具,用于编写编译器和解释器。在本篇文章中,我们将使用这两个工具来编写一个简单的计算器程序。 1. 设计语法 首先,我们需要设计一个简单的语法,以便让我们的程序知道如何解析输入的数学方程式。在这个例子中,我们将支持加减乘除四种运算符,以及括号。 下面是我们所设计的语法: <expr> ::= <expr> + <term> | <expr> - <term> | <term> <term> ::= <term> * <factor> | <term> / <factor> | <factor> <factor> ::= ( <expr> ) | Number 2.建立词法分析器 接下来,我们需要建立一个词法分析器,用于将输入的字符串分解成单词的形式,这些单词是在后续的解析中会用到的。 下面是我们简单的词法分析器: %{ #include "y.tab.h" %} %% [0-9]+ { yylval = atoi(yytext); return NUMBER; } [ \t] { /* Ignore whitespace */ } \n { return EOL; } . { return yytext[0]; } %% int yywrap(void) { return 1; } 3.建立语法规则 在完成词法分析器后,我们需要建立语法规则,以便让程序根据输入的数学表达式来对其进行解析。在这个例子中,我们将使用bison来帮助我们建立语法规则。 下面是我们简单的语法规则: %{ #include<stdio.h> %} %token NUMBER %token EOL %% input: /* empty */ | input line line: EOL | expr EOL { printf("%d\n", $1); } expr: expr '+' term { $$ = $1 + $3; } | expr '-' term { $$ = $1 - $3; } | term term: term '*' factor { $$ = $1 * $3; } | term '/' factor { $$ = $1 / $3; } | factor factor: '(' expr ')' { $$ = $2; } | NUMBER %% int main(void) { yyparse(); return 0; } 4.编译和运行 完成上述步骤后,我们可以将这个程序编译成一个可执行文件,并输入一些数学表达式来测试它。 下面是编译和运行的步骤: $ flex calculator.l $ bison -dy calculator.y $ gcc lex.yy.c y.tab.c -o calculator $ ./calculator 输入的数学表达式应该包含任意数量的数字和运算符,例如: 1+1 3*4-2 (5*6)/3 在输入完表达式后,我们应该看到程序输出相应的结果,例如: 2 10 10 总结 通过使用flexbison两个工具,我们可以很容易地编写一个简单的计算器程序。在完成这个例子后,我们能够更好地理解编译器和解释器的概念以及它们的工作原理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值