Lex与YACC解析文本

Lex/Yacc 整体做的能把 code -> tokens -> syntax tree

Lex会生成一个叫做词法分析器的程序。这是一个函数,它带有一个字符流传入参数,词法分析器函数看到一组字符就会去匹配一个关键字(key),采取相应措施。

YACC可以解析输入流中的标识符(token),同时可以根据标识符运行程序,对标识符进行处理,返回结果。

恒温控制器程序:

Lex与YACC详解 - 知乎 (zhihu.com),

建议先看完链接,了解程序流程。

工程目录:

app
  Main.cc
build
test
  test.hh
  test.cc
  input.hh
  LibertyExprLex.ll
  LibertyExprParse.ll
CMakeLists.txt

CmakeLists:

cmake_minimum_required (VERSION 3.9)

project(STA VERSION 2.3.2
  LANGUAGES CXX
)

set(CMAKE_VERBOSE_MAKEFILE ON)

set(STA_HOME ${PROJECT_SOURCE_DIR})
message(STATUS "STA version: ${PROJECT_VERSION}")

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE DEBUG)
endif()


find_package(FLEX)
find_package(BISON)

flex_target(LibertyExprLex ${STA_HOME}/test/LibertyExprLex.ll ${CMAKE_CURRENT_BINARY_DIR}/LibertyExprLex.cc
  COMPILE_FLAGS --prefix=LibertyExprLex_)
bison_target(LibertyExprParser ${STA_HOME}/test/LibertyExprParse.yy ${CMAKE_CURRENT_BINARY_DIR}/LibertyExprParse.cc
  COMPILE_FLAGS --name-prefix=LibertyExprParse_
  )
add_flex_bison_dependency(LibertyExprLex LibertyExprParser)


add_library(OpenSTA
  ${STA_HOME}/test/test.cc
  ${FLEX_LibertyExprLex_OUTPUTS}
  ${BISON_LibertyExprParser_OUTPUTS}
)

target_include_directories(OpenSTA
  PUBLIC
  ${STA_HOME}/test
  PRIVATE
  ${STA_HOME}
  )

target_compile_features(OpenSTA PUBLIC cxx_std_11)

add_executable(sta app/Main.cc)

target_link_libraries(sta
  OpenSTA
  )

add_custom_target(sta_tags etags -o TAGS
  */*.hh
  WORKING_DIRECTORY ${STA_HOME}
  )

LibertyExprLex.ll

%{
#include <stdio.h>
#include "LibertyExprParse.hh"
#include "input.hh"

extern Test* test;

%}

%option noyywrap


%%
[0-9]+ { test->print("num"); return NUMBER; }
heat { test->print("heat");return TOKHEAT;}
on|off { test->print("on|off");return STATE; }
target { test->print("target"); return TOKTARGET; }
temperature { test->print("temperature");return TOKTEMPERATURE;}
\n /* ignore end of line */;
[ \t]+ /* ignore whitespace */
%%


LibertyExprParse.yy

%{

#include <stdio.h>
#include <string.h>
#include "test.hh"
//在lex.yy.c里定义,会被yyparse()调用。在此声明消除编译和链接错误。
extern int yylex(void); 
extern Test* test;

int LibertyExprLex_lex();
#define LibertyExprParse_lex LibertyExprLex_lex

 void yyerror(const char *s)
 {
 	printf("[error] %s\n", s);
 }

%}

%token NUMBER TOKHEAT STATE TOKTARGET TOKTEMPERATURE

%%
commands: /* empty */
| commands command
;

command: heat_switch | target_set ;

heat_switch:
TOKHEAT STATE
{
	test->printState();
};

target_set:
TOKTARGET TOKTEMPERATURE NUMBER
{
	test->printSetTem($3);
};
%%

test.hh

#include<string>
class Test
{
public:
    void printState();
    void printSetTem(int t);
    void print(const std::string& data);
};

test.cc

#include <stdio.h>
#include "test.hh"

Test *test;
void Test::printState()
{
    printf("\tHeat turned on or off\n");
}
void Test::printSetTem(int t)
{
    printf("\tTemperature set  %d\n", t);
}
void Test::print(const std::string &data)
{
    printf("\t%s\n", data.c_str());
}

input.hh

#include "test.hh"
#include "../build/LibertyExprParse.hh"
extern Test *test;

static void intput()
{
    Test t;
    test = &t;
    LibertyExprParse_parse();
}

Main.cc

#include <stdio.h>
#include <string.h>
#include "input.hh"
int main()
{
    intput();
    return 0;
}

可输入指令:

heat on
heat off
target temperature 10

测试:

heat on                           //输入
        heat                      //lex分词输出
        on|off                    //lex分词输出
        Heat turned on or off     //yacc输出

heat off                          //输入
        heat                      //lex分词输出
        on|off                    //lex分词输出
        Heat turned on or off     //yacc输出

target temperature 10             //输入
        target                    //lex分词输出
        temperature               //lex分词输出
        num                       //lex分词输出
        Temperature set  0        //yacc输出

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值