$("parent > child")、$("A B")、$("div#test")、$("div,#test")、$(".test","div")

本文深入解析jQuery中的多种选择器用法,包括子元素选择器、并列选择器、限定范围选择器等,通过实例帮助读者理解不同选择器的功能及应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个标题似乎有些奇怪,但这些都是合法有效的jquery选择器。在这里将他们逻列一起,是因为他们比较容易引起混淆。下面就通过例子来说明他们之间的不同之处。

$("parent > child")

<div>
  <span>123</span>
  <p>
    <span>456</span>
  </p>
  <span>789</span>
</div>
$('div > span').css('color', '#FF0000');
结果显示如下:

123

456

789

这样理解:在parent的儿子辈中找child。这里div有三个儿子:span p和span,> 表示仅在div的儿子辈中查找。这里<span>456</span>不符合条件,因为他是div的孙子辈(二公子p的儿子)。

它等同于$("parent").children("child");

$("A B")

<form>
  <label>Name:</label>
  <input name="name" value="a" />
  <fieldset>
    <label>Newsletter:</label>
    <input name="newsletter" value="b" />
  </fieldset>
</form>
<input name="a1" value='c' />
<div>789</div>
<input name="a2" value='d' />
<fieldset>
  <label>Newsletter:</label>
  <input name="newsletter" value="e" />
</fieldset>
$("form input").css('color', '#FF0000');
//它也等同于:$("input","form").css('color','#ff0000');这在下面会有讲解
//也等同于:$("form").find("input").css('color', '#FF0000');

设置form中的所有input为红色。祖先为form,子孙为input。也可以理解,只要在form的后代中有input,就符合条件。思考一下与:$("form > input").css('color','#ff0000')的区别。


它等同于:$("A").find("B")

$("div#test")

中间没有空格,表示是“”的关系。$("div#test")意思是所有的div且id=test的元素。在看个例子:$(".intro.demo") 所有 class="intro" 且 class="demo" 的元素。

例1:

<div>
  <span class="test">123</span>
  <p>
    <span class="test">456</span>
  </p>
  <span>789</span>
  <div class="test">abc</div>
</div>
$("span.test").css('color', '#FF0000');
结果如下:

123

456

789
abc

例2:

<div>
  <span class="intro">123</span>
  <p>
    <span class="intro demo">456</span>
  </p>
  <span>789</span>
  <div class="demo">abc</div>
</div>
$(".intro.demo") .css('color', '#FF0000');
结果如下所示:

123

456

789
abc

例3:

$("div#intro .head")  id="intro" 的 <div> 元素中的所有 class="head" 的元素

$("div,#test")

一个双引号中用逗号分隔不同的选择器,称之为并列选择器。

<div>123</span>
<div style="border:1px solid #ccc;">
    <span id="test">456</span>
</div>
$('div,#test').css('color', '#FF0000');
结果如下图所示:

将div、id="test"元素设为红色字体。

$(".test","div")

这个看似有些奇特,它与上面的并列选择器虽然相似,但有本质的不同。其实这里的第二个参数"div"是限定查找.test的范围。

先看个简单例子:

<div>
  <span class="test">123</span>
</div>
<span class="test">456</span>
$(".test","div").css('color', '#FF0000');
结果为:

123

456

在看个稍微复杂一点的例子:

<!DOCTYPE html>
<html>
<head>
<script language="JavaScript" type="text/JavaScript" src="http://lock.5186.me/js/jQuery1.6.2.js"></script>
<script>
$(document).ready(function(){
  $(".del").click(function(){
    id=$("input[name='id']",$(this).parents("form:first")).val();
    alert(id);
  });
});
</script>
</head>
<body>
<table width="100%">
  <tr style="text-align:center;">
    <td>1</td>
    <td>218.11.56.*</td>
    <td>16:51 2012-10-30</td>
    <td><form><input type="hidden" name="id" value="1" /><span class="del">删除</span></form></td>
  </tr>
  <tr style="text-align:center;">
    <td>2</td>
    <td>218.11.56.*</td>
    <td>16:59 2012-10-30</td>
    <td><form><input type="hidden" name="id" value="2" /><span class="del">删除</span></form></td>
  </tr>
</table>
</body>
</html>
你会发现,点击不同数据的删除,会弹出当前数据的ID值。

jQuery()函数有三种用法。利用选择器进行的操作只是其中的一种用法。其语法为:

jQuery(selector, [context])

这种用法还包含了四种用法。

设置选择器环境

接受一个字符串,其中包含了用于匹配元素集合的 CSS 选择器

一般情况对jquery的选择器的用法,都是做为第一个参数的用法。其实jquery()函数的这种用法还可以传递第二个参数。传递这个参数的目的是将前面选择器限定在context这个环境中。在默认情况下,即不传第二个参数,选择器从文档根部对 DOM 进行搜索($()将在当前的HTML document中查找DOM元素);如果指定了第二个参数,如一个DOM元素集或jquery对象,那就会在这个context中查找。

下面看个例子

$("div.foo").click(function() {
    $("span", this).addClass("bar");
});
由于我们已经将 span 选择器限定到 this 这个环境中,只有被点击元素中的 span 会得到附加的class。在内部,选择器环境是通过 .find() 方法实现的,因此 $("span", this) 等价于 $(this).find("span")。

这里结合一下去掉的一个项目做说明:

下面这个tr有N个,这里只列出一个做为演示
<tr style="text-align:center;">
    <td><input type="checkbox" name="checkbox" value="$arr[id]" /></td>
    <td>$arr[id]</td>
    <td>$arr[log]</td>
    <td>$arr[ip]</td>
    <td>$arr[time]</td>
    <td><form><input type="hidden" name="id" value="$arr[id]" /><span class="del">删除</span></form></td>
</tr>

    //del event
    $(".del").bind("click",function(event){
        var _tmpQuery=$(this);//为什么要加上这一句?
        var id=$("input[name='id']",$(this).parents("form:first")).attr("value");//要关注的就是这一句,获取当前点击“删除”信息的ID
        art.dialog.confirm('你确认删除该日志吗?',function(){
            $.post("myRun/managerlog_del.php",{id:id},function(tips){
                if(tips=='ok'){
                    art.dialog.tips('成功删除');
                    $(_tmpQuery.parents('tr:first')).hide();//如果不加第一句,这里用$(_tmpQuery.parents('tr:first')).hide();则不会隐藏。因为这里的this,并不是当前的class="del"这个DOM对象了。而是jQuery的AJAX配置对象ajaxSettings。测试:alert(this.url); 大头爸爸注:现在处理这个隐藏有更好的方案,详细请访问:
                }else{
                    art.dialog.tips(tips,5);
                }
            });
            return true;
        });
    });
现在,终于明白了var id=$("input[name='id']",$(this).parents("form:first")).attr("value");的来龙去脉。它的意思是在被点击元素最近的父元素开始向外寻找第一个form元素,这个jquery对象就做为前面input[name='id']的范围。实际上在<form><input type="hidden" name="id" value="$arr[id]" /><span class="del">删除</span><img src="images/del.gif" width="16" height="16" /></form>中,input[name='id']是唯一的,即只有一个name值等于id的input,只有一个。

更多了解请访问:http://www.w3school.com.cn/jquery/core_jquery.asp

那么,在看一下jQuery(selector, [context]),这种用法的第二个用法:克隆 jQuery 对象

在上面例子中有这样一句:$(_tmpQuery.parents('tr:first')).hide();

在其它页面中,有这样的句子:$($(this).parents('form:first')).serialize()。完整代码如下:

  //edit event
  $(".edit").click(function(){
    art.dialog.open('manager_edit_control.php?'+$($(this).parents('form:first')).serialize(),{id:'edit',title:'管理员修改',lock:true,resize:false},false);
  });

用法 3 :克隆 jQuery 对象
语法
jQuery(jQuery object)

当以参数的形式向 $() 函数传递 jQuery 对象后,会创建一个该对象的副本。与初始对象一样,新的 jQuery 对象引用相同的 DOM 元素。
 
完全可以将上面代码改为:

_tmpQuery.parents('tr:first').hide();

$(this).parents('form:first').serialize()

sailor@sailor:~/Test/compiler-labs/build$ make [ 2%] [BISON][syntax] Building parser with bison 3.8.2 syntax_analyzer.y:89.15-24: warning: symbol FLOATCONST redeclared [-Wother] 89 | %token <fval> FLOATCONST | ^~~~~~~~~~ syntax_analyzer.y:43.20-29: note: previous declaration 43 | IDENT INTCONST FLOATCONST HEX_CONST OCT_CONST STRING_CONST CHAR_CONST | ^~~~~~~~~~ syntax_analyzer.y:89.15-24: error: %type redeclaration for FLOATCONST 89 | %token <fval> FLOATCONST | ^~~~~~~~~~ syntax_analyzer.y:43.20-29: note: previous declaration 43 | IDENT INTCONST FLOATCONST HEX_CONST OCT_CONST STRING_CONST CHAR_CONST | ^~~~~~~~~~ make[2]: *** [src/parser/CMakeFiles/syntax.dir/build.make:74: src/parser/syntax_analyzer.c] Error 1 make[1]: *** [CMakeFiles/Makefile2:350: src/parser/CMakeFiles/syntax.dir/all] Error 2 make: *** [Makefile:136: all] Error 2 sailor@sailor:~/Test/compiler-labs/build$ make clean sailor@sailor:~/Test/compiler-labs/build$ cmake … – Found LLVM 14.0.0 – Using LLVMConfig.cmake in: /usr/lib/llvm-14/cmake – Configuring done – Generating done – Build files have been written to: /home/sailor/Test/compiler-labs/build sailor@sailor:~/Test/compiler-labs/build$ make [ 2%] [BISON][syntax] Building parser with bison 3.8.2 syntax_analyzer.y:89.14-23: warning: symbol ‘FloatConst’ is used, but is not defined as a token and has no rules [-Wother] 89 | %type <node> FloatConst | ^~~~~~~~~~ syntax_analyzer.y: warning: 1 nonterminal useless in grammar [-Wother] syntax_analyzer.y:89.14-23: warning: nonterminal useless in grammar: FloatConst [-Wother] 89 | %type <node> FloatConst | ^~~~~~~~~~ syntax_analyzer.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] syntax_analyzer.y: warning: 18 reduce/reduce conflicts [-Wconflicts-rr] syntax_analyzer.y: note: rerun with option ‘-Wcounterexamples’ to generate conflict counterexamples syntax_analyzer.y:464.14-467.1: warning: rule useless in parser due to conflicts [-Wother] 464 | PrimaryExp : Floatnum { | ^~~~~~~~~~ [ 4%] [FLEX][lex] Building scanner with flex 2.6.4 [ 6%] Building C object src/parser/CMakeFiles/syntax.dir/syntax_analyzer.c.o syntax_analyzer.y: In function ‘yyparse’: syntax_analyzer.y:459:17: error: ‘struct _parse_tree_node’ has no member named ‘float_val’ syntax_analyzer.y:460:17: error: ‘struct _parse_tree_node’ has no member named ‘data_type’ syntax_analyzer.y:460:31: error: ‘FLOAT_TYPE’ undeclared (first use in this function) syntax_analyzer.y:460:31: note: each undeclared identifier is reported only once for each function it appears in syntax_analyzer.y:466:17: error: ‘struct _parse_tree_node’ has no member named ‘data_type’ make[2]: *** [src/parser/CMakeFiles/syntax.dir/build.make:87: src/parser/CMakeFiles/syntax.dir/syntax_analyzer.c.o] Error 1 make[1]: *** [CMakeFiles/Makefile2:351: src/parser/CMakeFiles/syntax.dir/all] Error 2 make: *** [Makefile:136: all] Error 2 %option noyywrap %{ #include <stdio.h> #include <stdlib.h> #include <string.h> #include “parse_tree.h” #include “syntax_analyzer.h” int lines = 1; int pos_start = 1; int pos_end = 1; char token_name[20]; void new_node(char *text) { yylval.node = new_parse_tree_node(text); } void handle_float_suffix(char* text) { char *endptr; if (text[strlen(text)-1] == ‘f’ || text[strlen(text)-1] == ‘F’) { text[strlen(text)-1] = ‘\0’; } yylval.fval = strtof(text, &endptr); } #define SET_TOKEN(name) do { pos_start = pos_end; pos_end += yyleng; strcpy(token_name, #name); new_node(yytext); } while(0) %} %x COMMENT DIGIT [0-9] OCTAL [0-7] HEX [0-9a-fA-F] ID [a-zA-Z_][a-zA-Z0-9_]* EXPONENT [Ee][±]?{DIGIT}+ HEX_EXP [Pp][±]?{DIGIT}+ DEC_INT 0|([1-9]{DIGIT}*) OCT_INT 0{OCTAL}+ HEX_INT 0[xX]{HEX}+ FLOAT_SUFFIX [fF] DEC_FLOAT ({DIGIT}+.{DIGIT}*|.{DIGIT}+){EXPONENT}?{FLOAT_SUFFIX}? HEX_FLOAT 0xX{HEX_EXP}{FLOAT_SUFFIX}? %% <INITIAL>{ “/” { BEGIN(COMMENT); pos_start = pos_end; pos_end += 2; } “//”. { pos_start = pos_end; pos_end += yyleng; } /* 数字常量 */ {DEC_INT} { SET_TOKEN(INTCONST); return INTCONST; } {OCT_INT} { SET_TOKEN(INTCONST); return INTCONST; } {HEX_INT} { SET_TOKEN(INTCONST); return INTCONST; } {DEC_FLOAT} { handle_float_suffix(yytext); SET_TOKEN(FLOATCONST); return FLOATCONST; } {HEX_FLOAT} { handle_float_suffix(yytext); SET_TOKEN(FLOATCONST); return FLOATCONST; } /* 关键字 */ “int” { SET_TOKEN(INT); return INT; } “float” { SET_TOKEN(FLOAT); return FLOAT; } “void” { SET_TOKEN(VOID); return VOID; } “return” { SET_TOKEN(RETURN); return RETURN; } “if” { SET_TOKEN(IF); return IF; } “else” { SET_TOKEN(ELSE); return ELSE; } “while” { SET_TOKEN(WHILE); return WHILE; } “break” { SET_TOKEN(BREAK); return BREAK; } “continue” { SET_TOKEN(CONTINUE); return CONTINUE; } “const” { SET_TOKEN(CONST); return CONST; } /* 运算符 / “;” { SET_TOKEN(SEMICOLON); return SEMICOLON; } “,” { SET_TOKEN(COMMA); return COMMA; } “=” { SET_TOKEN(ASSIGN); return ASSIGN; } “<” { SET_TOKEN(LT); return LT; } “<=” { SET_TOKEN(LET); return LET; } “>” { SET_TOKEN(GT); return GT; } “>=” { SET_TOKEN(GET); return GET; } “==” { SET_TOKEN(EQ); return EQ; } “!=” { SET_TOKEN(NEQ); return NEQ; } “+” { SET_TOKEN(ADD); return ADD; } “-” { SET_TOKEN(SUB); return SUB; } "" { SET_TOKEN(MUL); return MUL; } “/” { SET_TOKEN(DIV); return DIV; } “%” { SET_TOKEN(MOD); return MOD; } “&&” { SET_TOKEN(AND); return AND; } “||” { SET_TOKEN(OR); return OR; } “!” { SET_TOKEN(NOT); return NOT; } /* 括号 */ “(” { SET_TOKEN(LPARENTHESIS); return LPARENTHESIS; } “)” { SET_TOKEN(RPARENTHESIS); return RPARENTHESIS; } “[” { SET_TOKEN(LBRACKET); return LBRACKET; } “]” { SET_TOKEN(RBRACKET); return RBRACKET; } “{” { SET_TOKEN(LBRACE); return LBRACE; } “}” { SET_TOKEN(RBRACE); return RBRACE; } /* 标识符 */ {ID} { SET_TOKEN(IDENT); return IDENT; } /* 空白处理 */ [ \t\r]+ { pos_start = pos_end; pos_end += yyleng; } \n { lines++; pos_start = 1; pos_end = 1; } . { SET_TOKEN(ERROR); return ERROR; } } <COMMENT>{ “*/” { BEGIN(INITIAL); pos_end += 2; } \n { lines++; pos_start = 1; pos_end = 1; } . { pos_end++; } <<EOF>> { fprintf(stderr, “Error: Unclosed comment at line %d\n”, lines); exit(1); } } %% %{ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include “parse_tree.h” extern int yylex(); extern int yyparse(); extern int yyrestart(); extern FILE * yyin; extern int lines; extern char * yytext; extern int pos_end; extern int pos_start; parse_tree *gt; void yyerror(const char *s); parse_tree_node *node(const char *node_name, int children_num, …); %} %union { struct _parse_tree_node *node; float fval; } %token <node> // 运算符 EQ NEQ LE GE ADD_ASSIGN SUB_ASSIGN MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ASSIGN LT LET GT GET ADD SUB MUL DIV MOD AND OR NOT LSHIFT RSHIFT INC DEC BIT_NOT BIT_AND BIT_OR BIT_XOR // 分隔符 LPARENTHESIS RPARENTHESIS LBRACE RBRACE LBRACKET RBRACKET SEMICOLON COMMA DOT ARROW COLON QUESTION // 关键字 IF ELSE WHILE FOR RETURN INT CHAR FLOAT VOID STRUCT TYPEDEF DO BREAK CONTINUE CONST // 标识符和常量 IDENT INTCONST HEX_CONST OCT_CONST STRING_CONST CHAR_CONST // 错误标记 ERROR %type <node> Program %type <node> CompUnit %type <node> Decl %type <node> ConstDecl %type <node> VarDecl %type <node> ConstDefList %type <node> BType %type <node> ConstDef %type <node> ConstExpList %type <node> ConstInitVal %type <node> ConstInitValList %type <node> VarDef %type <node> VarDeclList %type <node> InitVal %type <node> InitValList %type <node> FuncDef %type <node> FuncFParams %type <node> FuncFParam %type <node> ExpList %type <node> Block %type <node> BlockList %type <node> BlockItem %type <node> Stmt %type <node> Exp %type <node> Cond %type <node> LVal %type <node> PrimaryExp %type <node> Number %type <node> UnaryExp %type <node> UnaryOp %type <node> FuncRParams %type <node> MulExp %type <node> AddExp %type <node> RelExp %type <node> EqExp %type <node> LAndExp %type <node> LOrExp %type <node> ConstExp %type <node> Integer %type <node> Floatnum %type <node> FloatConst %token <fval> FLOATCONST // 指定起始符号 %start Program %% Program : CompUnit { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 23: …("Program", 1, $̲1); gt->roo… ; } ; CompUnit : CompUnit Decl { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 24: …"CompUnit", 2, $̲1, $2); } | Com… = node(“CompUnit”, 2, $1, $2); } | Decl { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 24: …"CompUnit", 1, $̲1); } | FuncDef… = node(“CompUnit”, 1, $1); } ; Decl : ConstDecl { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 20: …ode("Decl", 1, $̲1); } | VarDecl… = node(“Decl”, 1, $1); } ; ConstDecl : CONST BType ConstDefList SEMICOLON { $$ = node(“ConstDecl”, 4, $1, $2, $3, $4); } ; ConstDefList : ConstDef { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 28: …stDefList", 1, $̲1); } | ConstDe… = node(“ConstDefList”, 3, $1, $2, $3); } ; BType : INT { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 21: …de("BType", 1, $̲1); } | FLOAT {… = node(“BType”, 1, $1); } ; ConstDef : IDENT ConstExpList ASSIGN ConstInitVal { $$ = node(“ConstDef”, 4, $1, $2, $3, $4); } ; ConstExpList : /* ε */ { ParseError: KaTeX parse error: Expected 'EOF', got '}' at position 29: …tExpList", 0); }̲ | ConstExpList… = node(“ConstExpList”, 4, $1, $2, $3, $4); } ; ConstInitVal : ConstExp { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 28: …stInitVal", 1, $̲1); } | LBRACE … = node(“ConstInitVal”, 3, $1, $2, $3); } | LBRACE RBRACE { $$ = node(“ConstInitVal”, 2, $1, $2); } ; ConstInitValList : ConstInitVal { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 32: …itValList", 1, $̲1); } | ConstIn… = node(“ConstInitValList”, 3, $1, $2, $3); } ; VarDecl : BType VarDef VarDeclList SEMICOLON { $$ = node(“VarDecl”, 4, $1, $2, $3, $4); } ; VarDeclList : /* ε */ { ParseError: KaTeX parse error: Expected 'EOF', got '}' at position 28: …DeclList", 0); }̲ | VarDeclList … = node(“VarDeclList”, 3, $1, $2, $3); } ; VarDef : IDENT ConstExpList { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("VarDef", 2, $̲1, $2); } | IDE… = node(“VarDef”, 4, $1, $2, $3, $4); } ; InitVal : Exp { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 23: …("InitVal", 1, $̲1); } | LBRACE … = node(“InitVal”, 3, $1, $2, $3); } | LBRACE RBRACE { $$ = node(“InitVal”, 2, $1, $2); } ; InitValList : InitVal { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 27: …itValList", 1, $̲1); } | InitVal… = node(“InitValList”, 3, $1, $2, $3); } ; FuncDef : BType IDENT LPARENTHESIS RPARENTHESIS Block { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 23: …("FuncDef", 5, $̲1, $2, $3, $4, … = node(“FuncDef”, 5, $1, $2, $3, $4, $5); } | VOID IDENT LPARENTHESIS FuncFParams RPARENTHESIS Block { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 23: …("FuncDef", 6, $̲1, $2, $3, $4, … = node(“FuncDef”, 6, $1, $2, $3, $4, $5, $6); } ; FuncFParams : FuncFParam { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 27: …ncFParams", 1, $̲1); } | FuncFPa… = node(“FuncFParams”, 3, $1, $2, $3); } ; FuncFParam : BType IDENT { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 26: …uncFParam", 2, $̲1, $2); } | BTy… = node(“FuncFParam”, 5, $1, $2, $3, $4, $5); } ; ExpList : /* ε */ { ParseError: KaTeX parse error: Expected 'EOF', got '}' at position 24: …"ExpList", 0); }̲ | ExpList LBRA… = node(“ExpList”, 4, $1, $2, $3, $4); } ; Block : LBRACE BlockList RBRACE { $$ = node(“Block”, 3, $1, $2, $3); } ; BlockList : /* ε */ { ParseError: KaTeX parse error: Expected 'EOF', got '}' at position 26: …lockList", 0); }̲ | BlockList Bl… = node(“BlockList”, 2, $1, $2); } ; BlockItem : Decl { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 25: …BlockItem", 1, $̲1); } | Stmt { … = node(“BlockItem”, 1, $1); } ; Stmt : LVal ASSIGN Exp SEMICOLON { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 20: …ode("Stmt", 4, $̲1, $2, $3, $4);… = node(“Stmt”, 2, $1, $2); } | SEMICOLON { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 20: …ode("Stmt", 1, $̲1); } | Block {… = node(“Stmt”, 1, $1); } | IF LPARENTHESIS Cond RPARENTHESIS Stmt { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 20: …ode("Stmt", 5, $̲1, $2, $3, $4, … = node(“Stmt”, 7, $1, $2, $3, $4, $5, $6, $7); } | WHILE LPARENTHESIS Cond RPARENTHESIS Stmt { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 20: …ode("Stmt", 5, $̲1, $2, $3, $4, … = node(“Stmt”, 2, $1, $2); } | CONTINUE SEMICOLON { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 20: …ode("Stmt", 2, $̲1, $2); } | RET… = node(“Stmt”, 3, $1, $2, $3); } | RETURN SEMICOLON { $$ = node(“Stmt”, 2, $1, $2); } ; Exp : AddExp { $$ = node(“Exp”, 1, $1); } ; Cond : LOrExp { $$ = node(“Cond”, 1, $1); } ; LVal : IDENT ExpList { $$ = node(“LVal”, 2, $1, $2); } ; PrimaryExp : LPARENTHESIS Exp RPARENTHESIS { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 26: …rimaryExp", 3, $̲1, $2, $3); } |… = node(“PrimaryExp”, 1, $1); } | Number { $$ = node(“PrimaryExp”, 1, $1); } ; Number : Integer { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("Number", 1, $̲1); } | Floatnu… = node(“Number”, 1, $1); } ; UnaryExp : PrimaryExp { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 24: …"UnaryExp", 1, $̲1); } | IDENT L… = node(“UnaryExp”, 4, $1, $2, $3, $4); } | IDENT LPARENTHESIS RPARENTHESIS { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 24: …"UnaryExp", 3, $̲1, $2, $3); } |… = node(“UnaryExp”, 2, $1, $2); } ; UnaryOp : ADD { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 23: …("UnaryOp", 1, $̲1); } | SUB { … = node(“UnaryOp”, 1, $1); } | NOT { $$ = node(“UnaryOp”, 1, $1); } ; FuncRParams : Exp { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 27: …ncRParams", 1, $̲1); } | FuncRPa… = node(“FuncRParams”, 3, $1, $2, $3); } ; MulExp : UnaryExp { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("MulExp", 1, $̲1); } | MulExp … = node(“MulExp”, 3, $1, $2, $3); } | MulExp DIV UnaryExp { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("MulExp", 3, $̲1, $2, $3); } |… = node(“MulExp”, 3, $1, $2, $3); } ; AddExp : MulExp { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("AddExp", 1, $̲1); } | AddExp … = node(“AddExp”, 3, $1, $2, $3); } | AddExp SUB MulExp { $$ = node(“AddExp”, 3, $1, $2, $3); } ; RelExp : AddExp { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("RelExp", 1, $̲1); } | RelExp … = node(“RelExp”, 3, $1, $2, $3); } | RelExp LET AddExp { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("RelExp", 3, $̲1, $2, $3); } |… = node(“RelExp”, 3, $1, $2, $3); } | RelExp GET AddExp { $$ = node(“RelExp”, 3, $1, $2, $3); } ; EqExp : RelExp { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 21: …de("EqExp", 1, $̲1); } | EqExp E… = node(“EqExp”, 3, $1, $2, $3); } | EqExp NEQ RelExp { $$ = node(“EqExp”, 3, $1, $2, $3); } ; LAndExp : EqExp { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 23: …("LAndExp", 1, $̲1); } | LAndExp… = node(“LAndExp”, 3, $1, $2, $3); } ; LOrExp : LAndExp { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("LOrExp", 1, $̲1); } | LOrExp … = node(“LOrExp”, 3, $1, $2, $3); } ; ConstExp : AddExp { $$ = node(“ConstExp”, 1, $1); } ; Integer : INTCONST { $$ = node(“Integer”, 1, $1); } ; Floatnum : FLOATCONST { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 26: …loatConst", 1, $̲1); ->float_val = $1; $$->data_type = FLOAT_TYPE; } ; PrimaryExp : Floatnum { ParseError: KaTeX parse error: Can't use function '$' in math mode at position 26: …rimaryExp", 1, $̲1); ->data_type = FLOAT_TYPE; } ; %% void yyerror(const char * s) { fprintf(stderr, “Syntax Error at line %d, column %d: %s. Near ‘%s’\n”, lines, pos_start, s, yytext); exit(1); } parse_tree *parse(const char *input_path) { if (input_path != NULL) { if (!(yyin = fopen(input_path, “r”))) { fprintf(stderr, “[ERR] Open input file %s failed.\n”, input_path); exit(1); } } else { yyin = stdin; } lines = pos_start = pos_end = 1; gt = new_parse_tree(); yyrestart(yyin); yyparse(); return gt; } parse_tree_node *node(const char *name, int children_num, …) { parse_tree_node *p = new_parse_tree_node(name); parse_tree_node *child; if (children_num == 0) { child = new_parse_tree_node(“epsilon”); parse_tree_add_child(p, child); } else { va_list ap; va_start(ap, children_num); for (int i = 0; i < children_num; ++i) { child = va_arg(ap, parse_tree_node *); parse_tree_add_child(p, child); } va_end(ap); } return p; } 给出改正后的完整代码 #ifndef __PARSETREE_H__ #define __PARSETREE_H__ #include <stdio.h> #define PARSE_TREE_NODE_NAME_MAX 5000 struct _parse_tree_node { struct _parse_tree_node * parent; // 父节点指针 struct _parse_tree_node * children[10]; // 子节点数组 int children_num; // 子节点数量 char name[PARSE_TREE_NODE_NAME_MAX]; // 节点名称 }; typedef struct _parse_tree_node parse_tree_node; // 创建一个新的解析树节点 parse_tree_node * new_parse_tree_node(const char * name); // 向父节点添加子节点 int parse_tree_add_child(parse_tree_node * parent, parse_tree_node * child); // 删除解析树节点 void del_parse_tree_node(parse_tree_node * node, int recursive); // 解析树结构 struct _parse_tree { parse_tree_node * root; // 解析树根节点 }; typedef struct _parse_tree parse_tree; // 创建一个新的解析树 parse_tree* new_parse_tree(); // 删除解析树 void del_parse_tree(parse_tree * tree); // 打印解析树 void print_parse_tree(FILE * fout, parse_tree * tree); #endif /* PARSETree.h */
05-30
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值